上一节中我们已经能够成功在nginx返回本地静态资源,没有太多django有关的配置。但是动态资源必须要借助django中的MTV模型来完成了,这一节我们就来看看如何真正将django部署到nginx上。
我是T型人小付,一位坚持终身学习的互联网从业者。喜欢我的博客欢迎在csdn上关注我,如果有问题欢迎在底下的评论区交流,谢谢。
什么是wsgi
wsgi,全称Web Server Gateway Interface,是 PEP 3333中定义的一个python标准。这个标准描述了一个web服务器(例如nginx)如何和web应用(例如django)进行通讯的,同时也描述了多个web应用如何通过级联来对一个请求进行处理的。
如上图所示,这里的uwsgi是对wsgi协议的一种实现,是一个单独组件,可和nginx部署在不同服务器,不过其必须和django安装在一台服务器上。uwsgi中可以配置django的信息,同时又可以暴露ip和端口给nginx来访问,从而完成一个中间件的目的。在接下来的操作中,我们分阶段来完成配置,首先确保uwsgi和django的连接正常,再确保nginx到uwsgi的连接正常。
django框架已经天然支持wsgi协议,如下图所示,新创建的项目目录中会自带一个wsgi.py
文件。这个文件在稍后的操作中会作为django暴露给uwsgi的一个接口
而nginx也天然对uwsgi支持,如果是按照上一节的方式安装的nginx,会发现在配置目录/etc/nginx/
已经有了和uwsgi有关的配置文件。这个配置文件会在稍后的操作中用于转发请求到uwsgi
(therm) (base) [root@ai-therm nginx]# ll *wsgi*
-rw-r--r-- 1 root root 664 Oct 3 2019 uwsgi_params
-rw-r--r-- 1 root root 664 Oct 3 2019 uwsgi_params.default
uwsgi的安装和基本配置
首先要进行uwsgi的安装,直接pip安装即可
pip install uwsgi
我这里安装的是2.0.18版本
(therm) (base) [root@ai-therm therm]# pip freeze
Django==2.2.10
pytz==2020.1
sqlparse==0.3.1
uWSGI==2.0.18
如果出现类似you need a C compiler to build uWSGI
的报错,需要安装一下gcc
yum -y install gcc
接下来在django的项目根目录新建uwsgi的配置文件uwsgi.ini
,类似下面这样
[uwsgi]
#for nginx
#socket=0.0.0.0:9999
#for web server
http=0.0.0.0:9999
#working dir
chdir=/root/projects/therm/API
#wsgi.py file, relative to chdir
wsgi-file=API/wsgi.py
processes=2
threads=2
enable-threads=True
master=True
pidfile=uwsgi.pid
daemonize=uwsgi.log
首先有必要解释下websocket和http的区别。这两者都是不同的应用层协议,并且都基于tcp。区别就在于
-
http是单向传输,而websocket是双向
-
http是短连接,客户端发送请求之后会在收到服务器的返回后断掉连接。而websocket是长连接,该连接会一直保持直到心跳检测失败
-
websocket经常用于频繁发起请求的场景,例如语音聊天,股票实时更新等,这种情况下使用http会对服务器造成很大负载
这里的几个字段说明如下
- socket - 采用websocket方式监听请求,因为nginx连接uwsgi采用socket方式,所以最后一定通过这个配置完成连接
- http - 采用http方式监听请求,这个配置使得uwsgi可以直接做为web服务器处理http请求,方便用来检测uwsgi和django的连接
- chdir - 整个配置的根目录,配置为django项目的根目录即可
- wsgi-file - 就是前面提到的django项目初始化的时候自带的
wsgi.py
文件的地址,相对于上面chdir
的路径 - master - 采用类似nginx的master+worker的方式启动
- pidfile/daemonize - 记录pid和日志的文件路径,也是相对于上面
chdir
的相对路径,直接和配置文件一起放在django项目根目录即可
因为我们接下来要进行uwsgi和django的对接,所以这里将uwsgi配置为http模式,监听在所有网卡的9999端口。
uwsgi对接django
创建一个应用test用作测试,先在主目录中包含该应用的路由
path('test/', include('Test.urls')),
然后在test应用中新建路由入下
path('hello/', views.hello),
以及view函数
def hello(request):
return JsonResponse(data={'status': 'Success', 'message': 'hello from xiaofu'})
先验证下django的配置没问题,采用自带的runserver来验证下
python manage.py runserver
(therm) (base) [root@ai-therm API]# curl 127.0.0.1:8000/test/hello/
{"status": "Success", "message": "hello from xiaofu"}
然后采用如下方式启动uwsgi,建议使用绝对路径
(therm) (base) [root@ai-therm API]# uwsgi --ini /root/projects/therm/API/uwsgi.ini
[uWSGI] getting INI configuration from /root/projects/therm/API/uwsgi.ini
之后就能看到master+worker的方式启动了uwsgi
(therm) (base) [root@ai-therm API]# ps -ef | grep wsgi
root 31446 1 0 21:17 ? 00:00:00 uwsgi --ini /root/projects/therm/API/uwsgi.ini
root 31447 31446 0 21:17 ? 00:00:00 uwsgi --ini /root/projects/therm/API/uwsgi.ini
root 31448 31446 0 21:17 ? 00:00:00 uwsgi --ini /root/projects/therm/API/uwsgi.ini
root 31449 31446 0 21:17 ? 00:00:00 uwsgi --ini /root/projects/therm/API/uwsgi.ini
root 31453 31120 0 21:18 pts/1 00:00:00 grep --color=auto wsgi
尝试通过外网的9999端口访问看看
这样就说明uwsgi到django的连接是没问题的,一会儿只需要将http改为socket即可。
nginx对接uwsgi
首先将uwsgi的配置从http改为socket
[uwsgi]
#for nginx
socket=0.0.0.0:9999
#for web server
#http=0.0.0.0:9999
#working dir
chdir=/root/projects/therm/API
#wsgi.py file, relative to chdir
wsgi-file=API/wsgi.py
processes=2
threads=2
enable-threads=True
master=True
pidfile=uwsgi.pid
daemonize=uwsgi.log
停掉进程
(therm) (base) [root@ai-therm API]# ps -ef | grep uwsgi
root 31446 1 0 21:17 ? 00:00:00 uwsgi --ini /root/projects/therm/API/uwsgi.ini
root 31447 31446 0 21:17 ? 00:00:00 uwsgi --ini /root/projects/therm/API/uwsgi.ini
root 31448 31446 0 21:17 ? 00:00:00 uwsgi --ini /root/projects/therm/API/uwsgi.ini
root 31449 31446 0 21:17 ? 00:00:00 uwsgi --ini /root/projects/therm/API/uwsgi.ini
root 31462 31120 0 21:22 pts/1 00:00:00 grep --color=auto uwsgi
(therm) (base) [root@ai-therm API]# kill -9 31446
(therm) (base) [root@ai-therm API]# ps -ef | grep uwsgi
root 31464 31120 0 21:23 pts/1 00:00:00 grep --color=auto uwsgi
重新启动
(therm) (base) [root@ai-therm API]# uwsgi --ini /root/projects/therm/API/uwsgi.ini
[uWSGI] getting INI configuration from /root/projects/therm/API/uwsgi.ini
之后再nginx配置中加入下面的location匹配规则
location / {
include /etc/nginx/uwsgi_params;
uwsgi_pass 127.0.0.1:9999;
}
我这里因为nginx和uwsgi在同一台机器上所以采用127.0.0.1
,如果是分布式部署,需要采用外网ip。
重新载入配置
(therm) (base) [root@ai-therm API]# nginx -s reload
采用访问nginx机器的80端口看看
这样就成功从nginx返回了django的结果。以后修改了django项目的内容,记住重启uwsgi来生效。
总结
只需要分三步进行配置
- 首先确保django的runserver能正常访问
- 然后确保uwsgi能成功连接到django,也就是uwsgi的配置没问题
- 最后确保nginx能成功连接到uwsgi,也就是nginx的配置没问题
逐步确认,最后完成整体配置。
到了这里,django项目部署到nginx就算基本完成了。但是随着网络安全得到越来越重视,我们最好是将http请求都改为https请求,而这在nginx配置也非常容易,下一节我们一起来看看。