目录html
前提准备:python
Django 项目中会有一些 CSS、JavaScript 等静态文件,为了可以方便地让 Nginx 处理这些静态文件的请求,咱们把项目中的所有静态文件收集到一个统一的目录下,这个目录一般位于 Django 项目的根目录,而且命名为 static。为了完成这些任务,须要在项目的配置文件里作一些必要的配置:linux
settings.py: STATIC_URL = '/static/' # 加入下面的配置 STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATIC_ROOT 指明了静态文件的收集目录,即项目根目录(BASE_DIR)下的 static 文件夹。
若是说咱们的项目是先后端分离的状况,这时候静态文件的目录确定是不同的,这时候可让python自动帮咱们收集一些静态文件,而后帮咱们放到指定的目录里面去,nginx
STATIC_ROOT='/var/www/static/' STATIC_URL='/static/'
收集全部静态文件到static_root指定目录:git
python3 manage.py collectstatic
新建一个基于不一样端口的虚拟主机github
[root@192.168.32.130 /usr/local/webserver/nginx/conf/vhosts]$ cat gunicorn_django.conf upstream mydjangoproject { server unix:/data/app/Library_Management_System/script/gunicorn.sock; } server { listen 10000; server_name 192.168.32.130; location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; if (!-f $request_filename) { proxy_pass http://mydjangoproject; break; } } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } location /static/ { alias /var/www/static/; } }
django项目的站点添加容许访问的主机:web
ALLOWED_HOSTS = ['*']
算法
配置好以后检查一下并启动django
[root@192.168.32.130 /usr/local/webserver/nginx/conf/vhosts]$ /usr/local/webserver/nginx/sbin/nginx -t nginx: the configuration file /usr/local/webserver/nginx/conf/nginx.conf syntax is ok nginx: configuration file /usr/local/webserver/nginx/conf/nginx.conf test is successful [root@192.168.32.130 /usr/local/webserver/nginx/conf/vhosts]$ /usr/local/webserver/nginx/sbin/nginx -s reload
[root@192.168.32.130 ~]$ pip3 install gunicorn
经过gunicorn启动Django项目,在你的django project目录下运行:后端
[root@192.168.32.130 /data/app/Library_Management_System]$ gunicorn Library_Management_System.wsgi:application --bind=unix:/data/app/Library_Management_System/script/gunicorn.sock [2019-12-01 05:56:47 -0800] [119248] [INFO] Starting gunicorn 20.0.4 [2019-12-01 05:56:47 -0800] [119248] [INFO] Listening at: unix:/data/app/Library_Management_System/script/gunicorn.sock (119248) [2019-12-01 05:56:47 -0800] [119248] [INFO] Using worker: sync [2019-12-01 05:56:47 -0800] [119251] [INFO] Booting worker with pid: 119251
启动完成以后,会夯住在这里,说明已经启动了,只要没有报错,访问你的网页,就可以正常访问了
夯住了怎办呢、可使用nohub命令来后台运行。具体不写了,本身百度去。
[线上环境部署Django,nginx+uwsgi 和nginx+gunicorn,这两种方案,应该如何选择?]
Gunicorn是使用Python实现的WSGI服务器, 直接提供了http服务, 而且在woker上提供了多种选择, gevent, eventlet这些都支持, 在多worker最大化里用CPU的同时, 还可使用协程来提供并发支撑, 对于网络IO密集的服务比较有利.
同时Gunicorn也很容易就改形成一个TCP的服务, 好比doge重写worker类, 在针对长链接的服务时, 最好开启reuse_port, 避免worker进程负载不均。
一句话配置简单
不一样于Gunicorn, uWSGI是使用C写的, 它的socket fd建立, worker进程的启动都是使用C语言系统接口来实现的, 在worker进程处理循环中, 解析了http请求后, 使用python的C接口生成environ对象, 再把这个对象做为参数塞到暴露出来的WSGI application函数中调用. 而这一切都是在C程序中进行, 只是在处理请求的时候交给python虚拟机调用application. 彻底使用C语言实现的好处是性能会好一些.
除了支持http协议, uWSGI还实现了uwsgi协议, 通常咱们会在uWSGI服务器前面使用Nginx做为负载均衡, 若是使用http协议, 请求在转发到uWSGI前已经在Nginx这里解析了一遍, 转发到uWSGI又会从新解析一遍. uWSGI为了追求性能, 设计了uwsgi协议, 在Nginx解析完之后直接把解析好的结果经过uwsgi协议转发到uWSGI服务器, uWSGI拿到请求按格式生成environ对象, 不须要重复解析请求. 若是用Nginx配合uWSGI, 最好使用uwsgi协议来转发请求.
除了是一个WSGI服务器, uWSGI仍是一个开发框架, 它提供了缓存, 队列, rpc等等功能, 在github找找就会发现有人用它的缓存写了一个Django cache backend, 用它的队列实现异步任务这些东西, 可是用了这些东西技术栈也就跟uWSGI绑定在一块儿, 因此通常也只是把uWSGI看成WSGI服务器来用。
一句话配置复杂
使用多个进程监听同一端口就绕不开惊群这个话题, fork子进程, 子进程共享listen socket fd, 多个子进程同时accept阻塞, 在请求到达时内核会唤醒全部accept的进程, 然而只有一个进程能accept成功, 其它进程accept失败再次阻塞, 影响系统性能, 这就是惊群. Linux 2.6内核更新之后多个进程accept只有一个进程会被唤醒, 可是若是使用epoll仍是会产生惊群现象.
Nginx为了解决epoll惊群问题, 使用进程间互斥锁, 只有拿到锁的进程才能把listen fd加入到epoll中, 在accept完成后再释放锁.
可是在高并发状况下, 获取锁的开销也会影响性能, 通常会建议把锁配置关掉. 直到Nginx 1.9.1更新支持了socket的SO_REUSEPORT
选项, 惊群问题才算解决, listen socket fd再也不是在master进程中建立, 而是每一个worker进程建立一个经过SO_REUSEPORT
选项来复用端口, 内核会自行选择一个fd来唤醒, 而且有负载均衡算法.
Gunicorn与uWSGI都支持reuse_port选项, 在使用时能够经过压测来评估一下reuse_port是否能提高性能.
通常咱们会在Gunicorn/uWSGI前面再加一层Nginx, 这样作的缘由有一下几点: