兄弟,你是不是也遇到过这种情况:公司就一台破服务器,老板却要求同时跑Django做后台管理,Flask做API接口。两个框架互不兼容,怎么让它们和平共处?别慌,今天我就用大白话跟你唠唠这件事。
先整明白:Nginx和uWSGI是干啥的?
打个比方:Nginx就像公司前台,来了客户(用户请求),前台先判断你是找销售部还是技术部,然后把你带到对应部门。uWSGI就像部门里的工人,Django的工人和Flask的工人各干各的,互不干扰。
我们做的事其实就是:前台(Nginx)根据URL或者域名,把不同请求分给不同工人(uWSGI进程),每个工人只干自己框架的活。
具体怎么搞?分三步走
第一步:让两个应用“分房住”
Django和Flask就像两个人,不能挤一张床。我们得给它们各自准备独立的虚拟环境,就像分房睡,你爱用什么枕头、什么被子,对方管不着。
# 给Django建个房间
python -m venv django_env
source django_env/bin/activate
pip install django uwsgi
# 给Flask建个房间
python -m venv flask_env
source flask_env/bin/activate
pip install flask uwsgi
注意:uWSGI也要各自安装,因为每个环境里的Python版本、依赖都可能不同。千万别图省事只装一个全局uWSGI,那样两个框架用同一个进程,迟早打架。
第二步:让Nginx当“导流员”
这个最关键。我们要告诉Nginx:当用户访问 yourdomain.com/admin/ 的时候,去找Django;访问 yourdomain.com/api/ 的时候,去找Flask。或者更简单,用两个不同的域名或端口。
我一般用路径区分,比如:
server {
listen 80;
server_name yourdomain.com;
# Django 应用走这里
location /admin/ {
include uwsgi_params;
uwsgi_pass unix:///tmp/django.sock;
}
# Flask 应用走这里
location /api/ {
include uwsgi_params;
uwsgi_pass unix:///tmp/flask.sock;
}
# 其他静态文件直接交给Nginx处理
location /static/ {
alias /var/www/static/;
}
}
这里用了Unix Socket通信,比TCP端口更快,也避免了端口冲突。当然你也可以用127.0.0.1:8001和8002两个端口,但记得防火墙要开放。
第三步:让uWSGI开“两条生产线”
接下来启动两个uWSGI实例,每个监听自己的socket,加载自己的应用。
Django的uWSGI配置文件(django_uwsgi.ini):
[uwsgi]
chdir = /home/projects/django_app
module = myproject.wsgi:application
socket = /tmp/django.sock
chmod-socket = 666
virtualenv = /home/projects/django_env
processes = 2
threads = 1
master = true
vacuum = true
Flask的uWSGI配置文件(flask_uwsgi.ini):
[uwsgi]
chdir = /home/projects/flask_app
module = app:app
socket = /tmp/flask.sock
chmod-socket = 666
virtualenv = /home/projects/flask_env
processes = 2
threads = 1
master = true
vacuum = true
注意看:两个配置里的socket不一样(django.sock vs flask.sock),chdir指向不同项目目录,virtualenv指向各自的虚拟环境。这样它们就是完全独立的进程,互不干扰。
然后分别启动:
uwsgi --ini django_uwsgi.ini & # Django生产线
uwsgi --ini flask_uwsgi.ini & # Flask生产线
真实场景:我踩过的坑
有一回,我把两个应用放在了同一个虚拟环境,结果Flask升级了一个库,Django的ORM就报错了。后来改成独立环境,但忘了改Nginx里的socket路径,结果所有请求都跑到了Flask那边,Django后台打不开。排查了一下午才发现是socket写错了。
还有一次,一个同事把两个uWSGI配置里的processes都设成4,结果8个进程把2G内存吃满了。后来根据实际访问量,Django进程设成2个,Flask设成4个,好多了。
怎么确认它们没打架?
启动之后,你可以通过两个测试URL验证:
- 访问
http://yourdomain.com/admin/login/应该看到Django的登录页 - 访问
http://yourdomain.com/api/health/应该返回Flask的JSON数据
还可以用 ps aux | grep uwsgi 查看进程,你会发现两拨进程互不相干。
如果某天Flask挂了,Django照样能跑,因为它们是独立的进程——就像你家厕所漏水,厨房照样能做饭,明白了吧?
最后说句实在话
这种一台服务器硬扛两个应用的方式,适合小公司、个人项目或者测试环境。如果流量大了,还是得考虑分开部署或者上容器。不过从0到1解决“只有一个破服务器”的问题,这个方案足够用。
当然,实际生产环境还有更多骚操作,比如用Supervisor管理进程保活、用Ansible自动化部署等等。如果你想看更多类似的“低成本解决方案”,可以逛逛 itfangan.com,那里的套路比我多多了。
好了,不说了,我去看看我的Flask API有没有被老板的测试机打爆。