uWSGI+Nginx 实现Django部署
详情参见:uWSGI+django+nginx的工作原理流程与部署历程
整个项目流程
教程都只教方法,但为什么这样部署,这样部署有什么好处,每个组件都起什么作用却只字不提。致使只要部署稍微有那么一点不同,就无可是从了。 所以说,项目流程和每个组件的用途才是此次部署最重要的部分。
首先客户端请求服务资源, nginx作为直接对外的服务接口,接收到客户端发送过来的http请求,会解包、分析, 如果是静态文件请求就根据nginx配置的静态文件目录,返回请求的资源, 如果是动态的请求,nginx就通过配置文件,将请求传递给uWSGI;uWSGI 将接收到的包进行处理,并转发给wsgi, wsgi根据请求调用django工程的某个文件或函数,处理完后django将返回值交给wsgi, wsgi将返回值进行打包,转发给uWSGI, uWSGI接收后转发给nginx,nginx最终将返回值返回给客户端(如浏览器)。 *注:不同的组件之间传递信息涉及到数据格式和协议的转换
作用:
1. 第一级的nginx并不是必须的,uwsgi完全可以完成整个的和浏览器交互的流程;
2. 在nginx上加上安全性或其他的限制,可以达到保护程序的作用;
3. uWSGI本身是内网接口,开启多个work和processes可能也不够用,而nginx可以代理多台uWSGI完成uWSGI的负载均衡;
4. django在debug=False下对静态文件的处理能力不是很好,而用nginx来处理更加高效。
前提条件+简单部署应用
1、有服务器,有公网IP,有域名;把域名和IP绑定,例如:www.pythonav.com <--> 192.168.15.132 2、创建Django项目,编写代码 3、拷贝代码到服务器[服务器安装环境:python,Django,pymysql,sqllite] 4、settings配置文件中,修改配置信息。ALLOWED_HOSTS = ['服务器的IP地址/*',] 5、简单应用:运行 python manage.py runserver 0.0.0.0:8001 浏览器通过IP:8001访问。
注意:简单部署,性能处理较低。我们提高性能就需要使用uwsgi。
uwsgi
uwsgi可以运行所有遵循wsgi协议相关的软件!
安装:pip3 install uwsgi
简单应用:
创建py文件:app.py 内部代码: def application(env, start_response): start_response('200 OK', [('Content-Type','text/html')]) return [b"Hello World"]
利用uwsgi运行:
uwsgi --http :9001 --wsgi-file app.py # 通过http协议开启9001端口,执行app.py文件 uwsgi --http :9002 --wsgi-file app.py --master --processes 4 --threads 2 # 前面意思一样,后面是要开启4个进程每个进程中有2个线程
利用uwsgi启动Django程序:
uwsgi --http :9005 --chdir /data/deploy/ --wsgi-file deploy/wsgi.py --master --processes 4 --threads 2 --static-map /static=/data/deploy/sssss # --chdir 指定程序目录 # --wsgi-file 指定程序下的socket文件,django是wsgi.py文件 # --master 表示要开启多进程和线程 # --processes 4 开启进程数 # --threads 2 开启线程数 # --static-map /static=静态文件路径 指定静态文件路径 # /static 表示静态文件的前缀是/static
注意:线上部署,就需要把所有的静态文件拿取到一个地址上,如果还是通过之前的配置方法进行配置,就需要把每个静态文件路径进行绝对指定。
Django settings.py 文件下 # 测试用配置静态文件信息,线上部署不会使用 # STATICFILES_DIRS = ( # os.path.join(BASE_DIR,'static'), # ) #线上部署,针对静态文件使用的配置信息,目的:收集所有的静态文件到staticFiles文件夹下 STATIC_ROOT = os.path.join(BASE_DIR,'staticFiles') # 执行命令,把所有的静态文件收集到一个文件下 python manage.py collectstatic # 注意,两种静态文件的配置信息不能共存,否则就会报错! # 静态文件收集完毕,完事之后一定要注释静态配置
也可以把所有的操作,写成配置文件:
# 写一个配置文件 wsgi_http.ini [uwsgi] http = 0.0.0.0:9004 # IP+端口 chdir = /data/deploy # 程序目录路径 (路径写到项目名即可) wsgi-file = deploy/wsgi.py # 指定项目下的wsgi.py # processes = 4 # threads = 2 static-map = /static=/data/deploy/staticFiles # 静态文件的地址 # 运行 uwsgi wsgi_http.ini
进阶:Nginx + uwsgi
以上操作,完全可以跑起来一个Django项目,但是我们是追求最NB的处理方式。
关于静态文件交给牛逼的nginx处理;对于动态请求就通过uwsgi让Django去处理,然后把处理之后的结果最终交给nginx返回给请求。
Nginx + uwsgi 请求过来都要先经过Nginx(接收所有发送过来的请求,相当于挡在服务前面的第一个大门),然后内部判断,把动态请求交给uwsgi去处理。
安装nginx yum install nginx 执行: /etc/init.d/nginx start/stop/restart 配置文件: /etc/nginx/nginx.conf 修改nginx的配置文件:nginx.conf
针对HTTP请求,nginx是通过监听80端口去处理;对于访问的动态请求,nginx会把数据请求通过8001端口交给uwsgi去处理,然后再把数据通过8001端口去返回。所以外部HTTP请求直接通过80端口(nginx下)进行访问来获取数据,而不再是直接访问Django。并且nginx与uwsgi之间通过socket进行连接!
# ========================================== nginx.conf ====================================================== # For more information on configuration, see: # * Official English Documentation: http://nginx.org/en/docs/ # * Official Russian Documentation: http://nginx.org/ru/docs/ user root; worker_processes 4; error_log /var/log/nginx/error.log; pid /var/run/nginx.pid; events { worker_connections 1024; } http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; #types_hash_max_size 2048; include /etc/nginx/mime.types; default_type application/octet-stream; upstream django { # server unix:///path/to/your/mysite/mysite.sock; # for a file socket server 127.0.0.1:8001; # for a web port socket (we'll use this first) } server { listen 80; #server_name ; charset utf-8; # max upload size client_max_body_size 75M; # adjust to taste # 关于静态文件,直接处理 location /static { alias /data/deploy/staticFiles; # your Django project's static files - amend as required } # 关于Django的动态请求,交给Django去处理 # Finally, send all non-media requests to the Django server. location / { uwsgi_pass django; # 执行Django server下的服务器 include uwsgi_params; # the uwsgi_params file you installed } } }
# ========================================== uwsgi ====================================================== # 写一个uwsgi socket请求的配置文件 wsgi_socket.ini [uwsgi] socket = 127.0.0.1:8001 # socket请求的IP+端口 chdir = /data/deploy # 程序目录路径 (路径写到项目名即可) wsgi-file = deploy/wsgi.py # 指定项目下的wsgi.py # processes = 4 # threads = 2 static-map = /static=/data/deploy/staticFiles # 静态文件的地址 # 运行 uwsgi wsgi_socket.ini
运行的时候,需要nginx和uwsgi全部运行起来!
注意:若是静态文件一直加载失败,执行vim /etc/selinux/config,查看sellinux的配置信息是否是disabled。
以下是摘自其他文章的方法:
目录
/data/admin/webserver/ django项目 /data/admin/script/ 脚本目录
安装uwsgi
pip install uwsgi
配置文件
#在脚本目录 vim uwsgi.ini文件 [uwsgi] chdir=/data/admin/webserver#项目路径 module=webserver.wsgi:application socket=/data/admin/script/uwsgi.sock wsgi-file=/data/admin/webserver/webserver/wsgi.py socket=/data/admin/script/uwsgi.sock workers=5 pidfile=/data_new/admin/script/uwsgi.pid http=10.0.0.2:8000 # 注意必须是服务器内网IP地址:端口 static-map=/static=/data/admin/webserver/status/ uid=root gid=root master=true vacuum=true thunder-lock=true enable-threads=true harakiri=30 post-buffering=4096 # daemonize=/opt/project_gitcadmin/script/uwsgi.log
启动uwsgi
uwsgi --ini uwsgi.ini
nginx配置
server { # 这个server标识我要配置了 listen 80; # 我要监听那个端口 server_name www.XXXXXX.com ; # 你访问的路径前面的url名称 access_log /var/log/nginx/access.log main; # Nginx日志配置 charset utf-8; # Nginx编码 gzip on; # 启用压缩,这个的作用就是给用户一个网页,比如3M压缩后1M这样传输速度就会提高很多 gzip_types text/plain application/x-javascript text/css text/javascript application/x-httpd-php application/json text/json image/jpeg image/gif image/png application/octet-stream; # 支持压缩的类型 error_page 404 /404.html; # 错误页面 error_page 500 502 503 504 /50x.html; # 错误页面 # 指定项目路径uwsgi location / { # 这个location就和咱们Django的url(r'^admin/', admin.site.urls), include uwsgi_params; # 导入一个Nginx模块他是用来和uWSGI进行通讯的 uwsgi_connect_timeout 30; # 设置连接uWSGI超时时间 uwsgi_pass unix:/opt/project_teacher/script/uwsgi.sock; # 指定uwsgi的sock文件所有动态请求就会直接丢给他 } # 指定静态文件路径 location /static/ { alias /opt/project_teacher/teacher/static/; index index.html index.htm; } }