一个Web服务器面对的是外部世界,它能直接从文件系统提供文件(HTML、图像等)。然而,它无法直接与Django应用通信,它需要借助一些工具的帮助来接收客户端的请求,然后返回响应。

理论篇(一):WSGI与uWSGI

  • WSGI(wsgi)
    全称Web Server Gateway Interface,或 Python Web Server Gateway Interface ,是为 Python 语言定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口。从名字就可以看出来,这东西是一个Gateway,也就是网关。网关的作用就是在协议之间进行转换。
    总结:WSGI(wsgi)只是一种规范,描述web server如何与web application通信的规范
  • uWSGI
    uWSGI是一个Web服务器,它实现了WSGI协议、uwsgi、http等协议。
  • uwsgi
    与WSGI一样是一种通信协议,但与WSGI协议是两种东西,uwsgi协议是uWSGI服务器的独占协议,用于定义传输信息的类型(type of information),每一个uwsgi packet前4byte为传输信息类型的描述。

理论篇(二):Web请求流程

web请求流程如下所示:

the web client <-> the web server <-> the socket <-> uwsgi <-> Django
  • 首先客户端请求服务资源
  • nginx作为直接对外的的服务接口,接收到客户端发送过来的请求会解包、分析
    • 如果是静态文件请求,根据配置直接返回请求的资源
    • 如果是动态的请求,就通过配置文件传递给uWSGI
  • uWSGI将接收到的包进行处理,并转发给wsgi,wsgi根据请求调用Django中的某个文件或函数,处理完后Django将返回值交给wsgi,wsgi将返回值进行打包,转发给uWSGI,uWSGI接收后转发给nginx,nginx最终将返回值返回给客户端

理论篇(三):nginx的作用:

  1. 第一级的nginx并不是必须的,uwsgi完全可以完成整个的和浏览器交互的流程;
  2. 在nginx上加上安全性或其他的限制,可以达到保护程序的作用;
  3. uWSGI本身是内网接口,开启多个work和processes可能也不够用,而nginx可以代理多台uWSGI完成uWSGI的负载均衡;
  4. django在debug=False下对静态文件的处理能力不是很好,而用nginx来处理更加高效。

实践篇(一):基础实验环境介绍

  • 操作系统:CentOS
  • Python:Python3
  • Tools Version:
    • nginx/1.14.
    • uwsgi: 2.0.19.1
  • nginx配置目录:/etc/nginx
  • nginx配置文件:/etc/nginx/nginx.conf

实践篇(二):uWSGI安装与配置

1. uwsgi安装

sudo yum install python3-devel
pip3 install uwsgi

测试方式:使用uWSGI在8000端口运行Django项目

uwsgi --http 127.0.0.1:8000 --chdir /path/to/project/ --wsgi-file /path/to/wsgi.py

2. 配置项

chdirchdirchdir

基本选项:

-processes-threads-stats
--stats
telnetcurl

示例:

uwsgi --http 127.0.0.1:8000 --chdir /path/to/project/ --wsgi-file /path/to/wsgi.py --processes 4 --threads 2 --stats 127.0.0.1:8080
8000127.0.0.1:8080

3. 将配置项写入文件

可以把配置写在配置文件里,执行时只需要一个配置文件做参数:

# conf.ini
[uwsgi]
http = 127.0.0.1:8000
chdir = /path/to/project/
wsgi-file = /path/to/wsgi.py
processes = 4
threads = 2
stats = 127.0.0.1:8080

考虑到安全性,uWSGI 文档中提到,不要使用 root 权限来运行 uWSGI,添加 uid 和 gid 选项指定用户和组。

使用配置文件运行:

uwsgi conf.ini
8000

实践篇(三):Nginx

1. 使用Nginx做基础代理转发

下面只给出最简单的配置示例:

server{
  listen 80;
  # 如果有域名
  server_name example.com;

  location / {
    proxy_pass http://127.0.0.1:8000;
    include uwsgi_params;
  }
}

2. 使用Nginx做SSL代理转发

  • 443端口代理
server {
    #SSL 访问端口号为 443
    listen 443 ssl; 
 #填写绑定证书的域名
    server_name cloud.tencent.com; 
 #证书文件名称
    ssl_certificate 1_cloud.tencent.com_bundle.crt; 
 #私钥文件名称
    ssl_certificate_key 2_cloud.tencent.com.key; 
    ssl_session_timeout 5m;
 #请按照以下协议配置
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 
 #请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; 
    ssl_prefer_server_ciphers on;
    location / {
    #网站主页路径。此路径仅供参考,具体请您按照实际目录操作。
        root html; 
        index  index.html index.htm;
    }
}
  • 其它自定义端口示例
server {
	# 自定义端口
  listen 	2020 ssl;
	# 域名
  server_name www.example.com;

  client_max_body_size 10M;
  ssl on;
  ssl_session_cache	shared:SSL:10m;
  ssl_session_timeout 10s;
	# 证书存放地址
  ssl_certificate /etc/nginx/conf.d/ssl/adminSSl.pem;
  ssl_certificate_key /etc/nginx/conf.d/ssl/adminSSl.key;
 # ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
 # ssl_ciphers  HIGH:!aNULL:!MD5;
 # error_page 497 301 https://$http_host$request_uri;

  access_log /logs/admin.log;
  index index.html;
  root /html/peixun/dist;
  charset utf-8;
  location / {
    try_files $uri $uri/ @router;
           
    index index.html index.htm;
  }
  gzip on;
  gzip_min_length  1k;
  gzip_buffers     4 16k;
  gzip_comp_level 9;
  gzip_types text/plain application/x-javascript application/javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
  gzip_vary off;
  gzip_disable "MSIE [1-6]\.";
  error_page   405 =200 @405;

   location @405{
       root  /opt/htdocs;
   } 
	
  location @router {
    rewrite ^.*$ /index.html last;
  }
  location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|flv|mp4|ico)$ {
    expires 30d;
    access_log on;
  }
}