一、概念
Django: 一个MVC架构的Web框架, 自带wsgi和server功能
Uwsgi: 一个高性能的cgi中间件,也提供Web服务器功能
nginx: 一个免费开源并且高性能的HTTP服务器和反向代理
二、为什么要用nginx
Django 和 Uwsgi 都提供服务器功能,的确nginx并不是必须,但是要部署到生产环境,需要考虑到某些情况
1 、安全问题:程序不能直接被浏览器访问到,而是通过nginx,nginx只开放某个接口,uwsgi本身是内网接口,这样运维人员在nginx上加上安全性的限制,可以达到保护程序的作用。
2、负载均衡问题:一个uwsgi很可能不够用,即使开了多个work也是不行,毕竟一台机器的cpu和内存都是有限的,有了nginx做代理,一个nginx可以代理多台uwsgi完成uwsgi的负载均衡。
3、静态文件问题:用django或是uwsgi这种东西来负责静态文件的处理是很浪费的行为,而且他们本身对文件的处理也不如nginx好,所以整个静态文件的处理都直接由nginx完成,静态文件的访问完全不去经过uwsgi以及其后面的东西。
另外,Django虽然自带服务器功能,但性能不佳,仅仅用于测试开发阶段;uWsgi的服务器性功能没研究过,但它主要是一个Web服务器网关接口,服务器性能不是它的强项
三、为什么要用uWsgi
CGI中间件的性能见参考资料3,用uWsgi替换django自带的wsgi,提高服务性能
四、系统架构
五、安装
我是在MAC机上进行部署,使用安装工具HomeBrew,另外需要安装好Python3、pip、virtualenv
1. 安装nginx、启动、验证
# 安装
brew install nginx
# 启动
brew services start nginx
# 验证
http://localhost:8080/
显示Welcome,证明nginx服务正常
注意: mac上nginx的安装目录在/usr/local/etc/nginx; linux上目录为/etc/nginx
2. 安装uWsgi、启动、验证
# 安装
pip install uwsgi
# 新建test.py
def application(env, start_response):
start_response('200 OK', [('Content-Type','text/html')])
return [b"Hello World"] # python3
#return ["Hello World"] # python2
# 启动
uwsgi --http :8000 --wsgi-file test.py
# 验证
http://localhost:8000
显示Hello World,证明安装成功
六、部署应用
1. 部署项目静态资源
# /path/to/your/site/site/settings.py
STATIC_ROOT = os.path.join(BASE_DIR, "static/")
# 打包
python manage.py collectstatic
# 静态资源放到/path/to/your/site/static/
2. 创建Python虚拟环境: 每个Python有独立的运行
# /Users/Jason/Documents/pm-site/.env
cd /Users/Jason/Documents/pm-site
virtualenv
virtualenv --no-site-packages .env
source .env/bin/activate
# 需要为虚拟环境安装django, 否则uwsgi起django项目时,会报错:No moduel "django"
pip install django
3. django 项目新增uwsgi 配置
# 创建your_site.sock文件,nginx与uwsgi通信使用
touch /Users/Jason/Documents/pm-site/pm_site/pm_site.sock
# 创建 /Users/Jason/Documents/pm-site/pm_site/uwsgi_params
# 内容从https://github.com/nginx/nginx/blob/master/conf/uwsgi_params 获取
uwsgi_param QUERY_STRING $query_string;
uwsgi_param REQUEST_METHOD $request_method;
uwsgi_param CONTENT_TYPE $content_type;
uwsgi_param CONTENT_LENGTH $content_length;
uwsgi_param REQUEST_URI $request_uri;
uwsgi_param PATH_INFO $document_uri;
uwsgi_param DOCUMENT_ROOT $document_root;
uwsgi_param SERVER_PROTOCOL $server_protocol;
uwsgi_param REQUEST_SCHEME $scheme;
uwsgi_param HTTPS $https if_not_empty;
uwsgi_param REMOTE_ADDR $remote_addr;
uwsgi_param REMOTE_PORT $remote_port;
uwsgi_param SERVER_PORT $server_port;
uwsgi_param SERVER_NAME $server_name;
#创建/Users/Jason/Documents/pm-site/pm_site/pm_site_uwsgi.ini
[uwsgi]
# Django-related settings
# the base directory (full path)
chdir = /Users/Jason/Documents/pm-site/pm_site
# Django's wsgi file
module = pm_site.wsgi
# the virtualenv (full path) 前面创建的虚拟环境
home = /Users/Jason/Documents/pm-site/.env
# process-related settings
# master
master = true
# maximum number of worker processes
processes = 10
# the socket (use the full path to be safe
socket = /Users/Jason/Documents/pm-site/pm_site/pm_site.sock
# ... with appropriate permissions - may be needed
chmod-socket = 777 # 注意了:这里必须设成777, 否则每次启动uwsgi会创建pm_site.sock(默认权限664), 守护进程启动时,nginx会报错没有权限
# clear environment on exit
vacuum = true
注释:配置使用unix socket进行通信,比TCP socket性能要高(配置如下):
socket =127.0.0.1:8080 #对应nginx配置文件中的转发端口
4. django 项目新增nginx 配置
注释:nginx 配置也可以直接在/usr/local/etc/nginx/nginx.conf中配置,但是不方便部署
# 新建/Users/Jason/Documents/pm-site/pm_site/pm_site_nginx.conf,内容为:
# the upstream component nginx needs to connect to
upstream django {
server unix:///Users/Jason/Documents/pm-site/pm_site/pm_site.sock; # for a file socket
#server 127.0.0.1:8001; # for a web port socket (we'll use this first)
}
# configuration of the server
server {
# the port your site will be served on
listen 8000;
# the domain name it will serve for
server_name 172.25.220.166; # substitute your machine's IP address or FQDN
charset utf-8;
# max upload size
client_max_body_size 75M; # adjust to taste
# Django media
location /media {
alias /Users/Jason/Documents/pm-site/pm_site/media; # your Django project's media files - amend as required
}
location /static {
alias /Users/Jason/Documents/pm-site/pm_site/static; # your Django project's static files - amend as required
}
# Finally, send all non-media requests to the Django server.
location / {
uwsgi_pass django;
include /Users/Jason/Documents/pm-site/pm_site/uwsgi_params; # the uwsgi_params file you installed
}
}
# /usr/local/etc/nginx/nginx.conf 中有一句配置
include servers/*;
# 所以我们需要将项目的nginx配置放到servers/目录,让nginx可以找到
ln -s /Users/Jason/Documents/pm-site/pm_site_nginx.conf /usr/local/etc/nginx/services/
5. 启动服务
# 启动nginx
brew services start nginx
# 用uswgi 拉起django应用
uwsgi --ini /Users/Jason/Documents/pm-site/pm_site_uwsgi.ini
踩坑:修改nginx配置,必须使用nginx -s reload 读取配置才会生效, 我在部署时restart了好多次,都无效,各种排查
6. 自启动
mac 和 linux 有所不同,自行查阅
七、总结
参考下面的资料,自行部署了一套服务,随笔记录踩过的坑
接下来研究一个ngnix 代理多个 django应用的场景
思路1: 1个Nginx + N 个(1个uwsgi + 1个django )
思路2: 1个Nginx + 1个uwsgi + N个django (uwsgi vhost模式)
参考:
1)nginx uwsgi wsgi django 这些东西究竟是什么关系 https://blog.csdn.net/u014761344/article/details/40146597
2)Django为什么用uWSGI+Nginx https://blog.csdn.net/qq_35318838/article/details/61198183
3)CGI中间件性能对比:http://developer.51cto.com/art/201010/229615.htm
4)基于nginx和uWSGI在Ubuntu上部署Django:https://www.jianshu.com/p/e6ff4a28ab5a
5) 使用uWSGI和nginx来设置Django和你的web服务 器: http://uwsgi-docs-zh.readthedocs.io/zh_CN/latest/tutorials/Django_and_nginx.html