大体的流程是:nginx作为服务器最前端,负责接收client的所有请求,统一管理。静态请求由Nginx自己处理。非静态请求通过uwsgi传递给Django,由Django来进行处理,从而完成一次WEB请求。
通信原理是:
the web client <-> the web server(nginx) <-> the socket <-> uwsgi <-> Django
1. 安装nginx
sudo apt-get install nginx
2. 安装uwsgi
pip install uwsgi
3. 测试uwsgi
进入django项目根目录
uwsgi --http :8001 --plugin python3 --module blog.wsgi
然后访问127.0.0.1:8001检验uwsgi是否正常运行,注意这时项目的静态文件是不会被加载的,需要用nginx做静态文件代理。
或者(可用)
uwsgi --http 0.0.0.0:8888 --file mysite/wsgi.py --static-map=/static=static
或者(可用)
uwsgi --http :8000 --module TestDemo.wsgi
4. 配置nginx
vim /etc/nginx/site-enabled/default
添加以下代码
server {
listen 80;
server_name 域名; # 如果没有域名就写ip地址 charset UTF-8; access_log /var/log/nginx/myweb_access.log; error_log /var/log/nginx/myweb_error.log; location / { include uwsgi_params; uwsgi_pass 127.0.0.1:8003; proxy_read_timeout 600; } location /static { alias static路径; } }
5. 启动服务
sudo /etc/init.d/nginx restart # 重启nginx uwsgi --socket :8003 --plugin python3 --module blog.wsgi # 启动uwsgi,注意这里是socket而不是http
6. 出现问题
- 504 Gateway Time-out
刚开始客户端请求时总是出现504 Gateway Time-out
,查看日志发现connect() failed (111: Connection refused) while connecting to upstream
。网上搜了很多说配置proxy_read_timeout
,试了都不行,最后终于找到了原因[3],把uwsgi启动时的参数http改成socket就好了,意思是如果nginx配置如果使用了uwsgi_pass指令,则uwsgi协议就只能用socket,具体如下:通常我们不会让浏览器直接与uWSGI通信。那是web服务器的工作,这是个穿针引线的活。
4、写uwsgi.ini配置文件
1 #uwsgi.ini file
2 [uwsgi]
3
4 # Django-related settings 5 # the base directory (full path) 6 chdir = /home/myself 7 # Django's wsgi file 8 module = myself.wsgi:application 9 # the virtualenv (full path) 10 #home = /path/to/virtualenv 11 12 # process-related settings 13 # master 14 master = true 15 # maximum number of worker processes 16 processes = 3 17 # the socket (use the full path to be safe) 18 #socket = /home/myself/myself.sock 19 socket = 127.0.0.1:8001 20 # ... with appropriate permissions - may be needed 21 chmod-socket = 666 22 chown-socket = nginx:nginx 23 # clear environment on exit 24 vacuum = true 25 enable-threads = true
修改nginx配置文件
1 vim /etc/nginx/nginx/conf
1 # For more information on configuration, see:
2 # * Official English Documentation: http://nginx.org/en/docs/ 3 # * Official Russian Documentation: http://nginx.org/ru/docs/ 4 5 user nginx; 6 worker_processes auto; 7 error_log /var/log/nginx/error.log; 8 pid /run/nginx.pid; 9 10 # Load dynamic modules. See /usr/share/nginx/README.dynamic. 11 include /usr/share/nginx/modules/*.conf; 12 13 events { 14 worker_connections 1024; 15 } 16 17 http { 18 log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 19 '$status $body_bytes_sent "$http_referer" ' 20 '"$http_user_agent" "$http_x_forwarded_for"'; 21 22 access_log /var/log/nginx/access.log main; 23 24 sendfile on; 25 tcp_nopush on; 26 tcp_nodelay on; 27 keepalive_timeout 65; 28 types_hash_max_size 2048; 29 30 include /etc/nginx/mime.types; 31 default_type application/octet-stream; 32 33 # Load modular configuration files from the /etc/nginx/conf.d directory. 34 # See http://nginx.org/en/docs/ngx_core_module.html#include 35 # for more information. 36 include /etc/nginx/conf.d/*.conf; 37 38 upstream django { 39 #server unix:/home/myself/myself.sock; # for a file socket 40 server 127.0.0.1:8001; # for a web port socket (we'll use this first) ---socket 41 } 42 43 server { 44 listen 80 default_server; 45 listen [::]:80 default_server; 46 server_name _; 47 root /usr/share/nginx/html; 48 49 # Load configuration files for the default server block. 50 include /etc/nginx/default.d/*.conf; 51 52 location /static/ { 53 root /home/myself; ----project地址 54 } 55 56 location / { 57 include uwsgi_params; 58 uwsgi_pass django; ----上面修改socket的位置 59 } 60 61 error_page 404 /404.html; 62 location = /40x.html { 63 } 64 65 error_page 500 502 503 504 /50x.html; 66 location = /50x.html { 67 } 68 } 69 70 # Settings for a TLS enabled server. 71 # 72 # server { 73 # listen 443 ssl http2 default_server; 74 # listen [::]:443 ssl http2 default_server; 75 # server_name _; 76 # root /usr/share/nginx/html; 77 # 78 # ssl_certificate "/etc/pki/nginx/server.crt"; 79 # ssl_certificate_key "/etc/pki/nginx/private/server.key"; 80 # ssl_session_cache shared:SSL:1m; 81 # ssl_session_timeout 10m; 82 # ssl_ciphers HIGH:!aNULL:!MD5; 83 # ssl_prefer_server_ciphers on; 84 # 85 # # Load configuration files for the default server block. 86 # include /etc/nginx/default.d/*.conf; 87 # 88 # location / { 89 # } 90 # 91 # error_page 404 /404.html; 92 # location = /40x.html { 93 # } 94 # 95 # error_page 500 502 503 504 /50x.html; 96 # location = /50x.html { 97 # } 98 # } 99 100 }
采用Systemd管理uwsgi
1 mkdir -p /etc/uwsgi/ini
2 mv /home/myself/uwsgi.ini /etc/uwsgi/ini/
1 vim /etc/systemd/system/uwsgi.service
2
3
4 [Unit] 5 Description=uWSGI Emperor 6 After=syslog.target 7 8 [Service] 9 ExecStart=/root/uwsgi/uwsgi --emperor /etc/uwsgi/ini 10 Restart=always 11 KillSignal=SIGQUIT 12 Type=notify 13 StandardError=syslog 14 NotifyAccess=all 15 16 [Install] 17 WantedBy=multi-user.target
nginx uwsgi_pass方式传递真实IP
经过nginx反向代理后报文的源IP会改变,如果想要让后端的程序获取真实IP的话,需要修改NGINX配置,但是网上的方式都是使用proxy_pass的代理方式来修改的配置。对于uwsgi_pass方式来代理的并不生效。如果你的代理方式是proxy_pass的话,可以查看其它文章,随便一搜就可以搜到。
如果使用uwsgi_pass代理的话,需要把你的nginx配置文件修改为以下内容(include和uwsgi_pass字段根据自己的情况填写):
location /{
uwsgi_param X-Real-IP $remote_addr;
uwsgi_param X-Forwarded-For $proxy_add_x_forwarded_for;
uwsgi_param X-Forwarded-Proto $http_x_forwarded_proto;
include /usr/local/nginx/uwsgi_params;
uwsgi_pass $uwsgicluster:8001;
}
在Django的后端程序中,如果获取真实IP,使用下面的字段去获取:
request.META['X-Real-IP']
如果获取不到的话,也可以先打印request.META所有内容,查看其它Key值是否有想要的内容。
访问静态文件
注意:如果你的项目为前后端分离的项目,也就是说前端是前端工程师来完成的,他们可能用了前端专有的一些框架,所以如果按前面那样进行操作的时候,会出现界面内容不显示的问题,这个问题主要是网页静态文件没有加载成功的原因,具体的操作办法为:
(先关掉第三步中启动的服务)进入项目的setting.py文件中,添加如下内容:
#setting.py文件中添加
STATIC_ROOT = os.path.join(BASE_DIR, "static/")
然后在之前的项目目录下执行:
python manage.py collectstatic
再重新启动uwsgi的命令,应该就可以成功访问页面了~
关闭与开启服务:
ps ax | grep uwsgi
uwsgi --stop <uwsgi pid file>
sudo /etc/init.d/nginx stop
sudo /etc/init.d/nginx start