Nginx+uwsgi+Django服务器部署

本文主要介绍使用Django框架编写的服务器部署方式,采用Nginx+uwsgi,建议去理解每一个部件的具体作用,而不是去遵循教程一步步设置。

Nginx+uwsgi+Django其主要原理是:Nginx负责接收所有访问服务器的请求,静态资源(css、js、images等)等内容直接由Nginx进行返回,动态资源通过uwsgi去请求。

Nginx(engine X)

Nginx is a web server, which can also be used as a reverse proxy, load balancer and HTTP cache. Nginx can be deployed to serve dynamic HTTP content on the network using FastCGI, SCGI handlers for scripts, WSGI application servers or Phusion Passenger modules, and it can serve as a software load balancer.Nginx uses an asynchronous event-driven approach to handling requests. Nginx’s modular event-driven architecture can provide more predictable performance under high loads.

在Linux操作系统下,nginx使用epoll事件模型,得益于此,nginx在Linux操作系统下效率相当高。同时Nginx在OpenBSD或FreeBSD操作系统上采用类似于epoll的高效事件模型kqueue。

HTTP proxy and Web server features

  • Ability to handle more than 10,000 simultaneous connections with a low memory footprint (~2.5 MB per 10k inactive HTTP keep-alive connections)
  • Handling of static files, index files and auto-indexing
  • Reverse proxy with caching
  • Load balancing with in-band health checks
  • TLS/SSL with SNI and OCSP stapling support, via OpenSSL.
  • FastCGI, SCGI, uWSGI support with caching
  • Name- and IP address-based virtual servers
  • IPv6-compatible
  • WebSockets and HTTP/1.1 Upgrade

Mail proxy features

  • TLS/SSL support
  • STARTTLS support
  • SMTP, POP3, and IMAP proxy
  • Authentication using an external HTTP server

上述是比较精简的Nginx介绍及主要特性,来源于维基百科Nginx,写的还是不错的。Nginx在本实例中负责监听某个端口的所有请求,然后由自己去响应静态资源动态资源请求发给uwsgi去进一步处理。 下面介绍Nginx的使用。

Nginx安装

Mac下:

1
brew install nginx

Linux下:

1
sudo apt-get install nginx

安装是非常容易的,需要明白两个路径,一个是Nginx运行路径,一个是Nginx配置路径

Mac下:

1
2
运行路径 可直接使用 nginx [-s stop]
配置路径 /usr/local/etc/nginx/

Linux下:

1
2
运行路径 /etc/init.d/nginx (start | restart | stop)
配置路径 /etc/nginx/

忘记配置路径的时候可以使用nginx -t,他会测试conf文件,会显示conf的路径在哪里。

Nginx配置

Linux系统下的配置为主,Mac下与linux下区别主要是:server配置mac下默认也在nginx.conf文件中,而linux下会以include的方式进行调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# 定义Nginx运行的用户和用户组
user www-data;
# nginx进程数,建议设置为等于CPU总核心数
worker_processes auto;
# 全局错误日志定义类型,[ debug | info | notice | warn | error | crit ]
# 不设置的话日志在/var/log/nginx/error.log
# error_log [error.log path] info;
# 进程pid(进程标识符)文件
pid /run/nginx.pid;
# 工作模式及连接数上限
events {
# 单个后台worker process进程的最大并发链接数
worker_connections 768;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Gzip Settings
##
# 开启gzip压缩
gzip on;
gzip_disable "msie6";
# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
##
# Virtual Host Configs
##
# 引用server 配置
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
mail {
# See sample authentication script at:
# http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
# auth_http localhost/auth.php;
# pop3_capabilities "TOP" "USER";
# imap_capabilities "IMAP4rev1" "UIDPLUS";
server {
listen localhost:110;
protocol pop3;
proxy on;
}
server {
listen localhost:143;
protocol imap;
proxy on;
}
}

可以看到在虚拟主机配置时,引用了两个目录下的文件,一个是conf.d,一个是sites-enabled,一般我们只修改后者。
我们在配置路径下会看到两个文件夹都以sites-为前缀:

  • sites-enabled
  • sites-available

这两个的关系:

If you are coming from Apache, the “sites-available” and “sites-enabled” directories will be familiar.

These directories are used to define configurations for your websites.Files are generally created in the “sites-available” directory, and then symbolically linked to the “sites-enabled” directory when they are readyto go live.

也就是说在sites-available中进行修改或者新增配置,之后在sites-enabled中增加一个sites-available相应配置文件的链接,也就是配置文件在sites-enabled中激活。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
server {
# 侦听80端口
listen 80;
# 服务器IP地址或域名
server_name [address];
# 设定本虚拟主机的访问日志
access_log logs/nginx.access.log main;
# 定义错误提示页面
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
# 默认请求
location / {
root [index path];
#定义首页索引文件的名称
index index.html index.htm;
}
#静态文件,nginx自己处理
location /static/ {
alias [static path];
}
}

uwsgi

uWSGI是一个Web服务器,它实现了WSGI协议、uwsgi、http等协议。Nginx中HttpUwsgiModule的作用是与uWSGI服务器进行交换。WSGI是一种Web服务器网关接口。它是一个Web服务器(如nginx,uWSGI等服务器)与web应用(如用Flask框架写的程序)通信的一种规范。

要注意 WSGI / uwsgi / uWSGI 这三个概念的区分。

  • WSGI是一种通信协议。
  • uwsgi是一种线路协议而不是通信协议,在此常用于在uWSGI服务器与其他网络服务器的数据通信。
  • 而uWSGI是实现了uwsgi和WSGI两种协议的Web服务器。

安装

1
pip install uwsgi

配置

uwsgi 有两种设置参数的方式,一种是--field value的参数形式加载uwsgi后面,还有一种以uwsgi.ini的格式作为配置文件,然后使用uwsgi -ini uwsgi.ini的方式运行,其输出结果会存在uwsgi.log文件中。下面介绍常用的字段(--field value在配置文件中均以field = value的格式呈现):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[uwsgi]
# Django-related settings
http = :8001 #如果使用nginx+uwsgi 必须使用socket = :8001
# the base directory (full path)
chdir = [dirname]
# Django s wsgi file
module = [projectname].wsgi
# process-related settings
# master
master = true
# ... with appropriate permissions - may be needed
# chmod-socket = 664
# clear environment on exit
vacuum = true
plugin python = true
# set log file path
daemonize = [uwsgi.log path]
# the virtualenv
home = [env path]

记得在uwsgi.ini中添加plugin python = true,不然可能会有问题

Django

django部分就不再多说,将uwsginginx启动起来之后,就可以访问了,这里提醒两点:

  1. django静态资源使用python manage.py collectstatic集中起来,存放的路径会根据settings.py中的配置。
  2. 记得修改settings.py中的ALLOWED_HOSTS字段,例如运行所有IP地址访问:ALLOWED_HOSTS = ['*']