Nginx+Django+uWSGI部署伺服器詳細解析

weixin_33866037發表於2018-02-07

本文基於: 阿里雲CentOS 7.4.1708, Python 3.6.1, Django 2.0.2, uWSGI 2.0.15, Nginx 1.12.2


知道怎麼樣部署之前我們要先弄清楚為什麼? 為什麼要用Django+uWSGI+Nginx? 所以更首先我們要知道是什麼?

先弄清楚幾點概念, 注意大小寫區別.

  • WSGI - 全稱為Python Web Server Gateway Interface, 即Python伺服器閘道器介面. 是為Python語言定義的Web伺服器Web應用程式Web應用框架之間的一種簡單而通用的介面. WSGI只是一種通訊協議. 更詳細資訊請檢視維基百科WSGI.
    通俗一點說就是寫Python程式時不想花費大量的時間去處理TCP連線、HTTP的請求和響應等等, 於是就把這些都統一成了一個介面(即WSGI). 然後由專門的Web伺服器(uWSGI等)Web應用框架(Django等)去實現. 既降低了開發門檻又節約了時間.

  • uWSGI - uWSGI是一個實現了WSGI協議的Web伺服器, uWSGI處理了HTTP的響應解析等, 並轉成WSGI協議, 這樣我們編寫的Web應用程式或Web應用框架才可以對傳遞過來的資訊進行處理.

  • uwsgi - uwsgi是實現了WSGI協議的伺服器的內部自有協議, 它定義了傳輸資訊的型別, 用於實現了WSGI協議的伺服器與其他網路伺服器的資料通訊.


瞭解了基本的概念之後, 就知道了為什麼要Django+uWSGI. Django是Python的Web應用框架, 他幫我們做了很多基礎工作, 讓開發者可以專心的寫業務程式碼. 而uWSGI是實現了WSGI協議的Web伺服器, 只有這兩者組合在一起, Python的應用程式才可以發揮作用.

理論上, 有了這一套, 就可以部署到伺服器使用了. 而我們還要加上Nginx的原因, 當然是因為Nginx可以做一些uWSGI做不到的事情, 或者把事情做得更好.

Nginx是一款面向效能設計的HTTP伺服器,相較於Apache具有佔有記憶體少,穩定性高等優勢. 可以被用作反向代理負載平衡器HTTP快取. 所以使用Nginx的最大原因之一就是效能問題. 如果只是個小網站, 不會有很大了流量, 當然uWSGI可以滿足要求, 但是在高併發情況下就需要Nginx了, 並且Nginx相比Apache有很大的高併發優勢.

另外, Nginx能帶來更好的安全性. 並且可以直接處理靜態內容, 不需要通過uWSGI, 讓uWSGI專心處理動態內容, 從而提高效能. 更多Nginx內容可以訪問Nginx, epoll, about Nginx.

總結一下各自的任務以及工作原理: Nginx接收到客戶端的請求, 如果請求的是靜態內容就直接返回靜態內容, 如果請求的是動態內容, 就把請求轉發給uWSGI ,uWSGI連線Django進入我們的Python程式進行處理.


知道了Django, uWSGI, Nginx分別是什麼, 並且知道了為什麼要用Django+uWSGI+Nginx之後, 就可以進行伺服器的部署工作了.

  1. 在伺服器部署Python 3.6和Django 2.0.2

  2. 連線阿里雲伺服器. 在Mac終端輸入$ SSH root@xxx.cn, root是使用者名稱xxx.cn是伺服器域名或者IP地址

  3. 安裝Nginx

    # yum install epel-release
    # yum install python-devel nginx
    
  4. 使用pip安裝uwsgi >>> pip3 install uwsgi --upgrade

  5. 配置uWSGI和Nginx配置檔案並直接放在專案根目錄

    • 因為配置檔案只需要在部署時使用一次, 直接在伺服器配置會更合適. 當然你也可以在本地的專案資料夾新建對應的配置檔案並寫入配置. 但是需要注意配置檔案中的路徑都是伺服器端的路徑.

    • uWSGI配置檔案uwsgi.ini. 更多資訊請檢視uWSGI Configuration.

      [uwsgi]
      #使用HTTP訪問的埠號, 使用這個埠號是直接訪問了uWSGI, 繞過了Nginx
      http = :8010
      #與外界連線的埠號, Nginx通過這個埠轉發給uWSGI
      socket = 127.0.0.1:8001
      #是否使用主執行緒
      master = true
      # 專案在伺服器中的目錄(絕對路徑)
      chdir = /project_dir/
      # Django's wsgi 檔案目錄
      wsgi-file = project_name/wsgi.py
      # 最大程式數
      processes = 4
      #每個程式的執行緒數
      threads = 2
      #狀態監聽埠
      stats = 127.0.0.1:9191
      # 退出時自動清理環境配置
      vacuum = true
      #目錄下檔案改動時自動重啟
      touch-reload = /project_dir
      #Python檔案改動時自動重啟
      #py-auto-reload = 1
      #後臺執行並把日誌存到.log檔案
      daemonize = /project_dir/uWSGI.log
      
    • Nginx需要兩個配置檔案. uwsgi_params檔案和project_name.conf檔案

      1. uwsgi_params檔案可以直接在Nginx的git倉庫中可以下載.

      2. project_name.conf通過複製nginx.conf配置檔案並進行修改. 首先查詢nginx.conf檔案的位置:
        # nginx -t
        會列印出類似資訊:

      nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
      nginx: configuration file /etc/nginx/nginx.conf test is successful
      
      1. 新建project_name.conf檔案, 複製nginx.conf檔案的所有資訊到project_name.conf. 並替換掉server部分內容.
        server {
        #把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  nginx;
        worker_processes  auto;
        error_log /var/log/nginx/error.log;
        pid /run/nginx.pid;
        
        # Load dynamic modules. See /usr/share/nginx/README.dynamic.
        include /usr/share/nginx/modules/*.conf;
        
        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;
        
            # Load modular configuration files from the /etc/nginx/conf.d directory.
            # See http://nginx.org/en/docs/ngx_core_module.html#include
            # for more information.
            include /etc/nginx/conf.d/*.conf;
        
        
            #下面的部分是替換之後的配置
            # the upstream component nginx needs to connect to
            upstream django {
                # 連線到Django的埠號, 和uwsgi.ini檔案中埠一致. 127.0.0.1說明只允許本地轉發
                server 127.0.0.1:8001; # for a web port socket (we'll use this first)
            }
        
            # configuration of the server
            server {
                # 埠號, 客戶端通過這個埠連線到Nginx
                listen      80;
                # 伺服器地址
                server_name pefami.cn; # substitute your machine's IP address or FQDN
                # 編碼
                charset     utf-8;
        
                #日誌檔案在伺服器中的路徑
                access_log      /project_dir/nginx_access.log;
                error_log       /project_dir/nginx_error.log;
        
                # 上傳檔案最大體積限制
                client_max_body_size 75M;   # adjust to taste
        
                # Django media檔案路徑
                location /media  {
                    alias /project_dir/media;  # your Django project's media files - amend as                         required
                }
                # Django 靜態檔案路徑
                location /static {
                    alias /project_dir/static; # your Django project's static files - amend as required
                }
        
                # Finally, send all non-media requests to the Django server.
                location / {
                    uwsgi_pass  django;
                    include     /project_dir/uwsgi_params; # the uwsgi_params file you installed
                }
            }
        
        }
        
  6. 配置好了配置檔案以後, 把專案整個上傳到伺服器. 接下來只要在伺服器執行uWSGINginx就可以了. 這個有個需要注意: 在阿里雲伺服器開啟對應埠, 比如上邊配置中使用了的800180埠. 否則客戶端無法連線上伺服器.

  7. 啟動uWSGI
    # uwsgi --ini uwsgi.ini
    也可以不需要配置檔案直接啟動uWSGI, 這時就不需要配置uwsgi.ini檔案. 如下:
    # uwsgi --http :8001 --chdir /project_dir/project_name --home=/path/to/env --module project_name.wsgi
    其中--home指定virtualenv路徑,如果沒有可以去掉.

  8. 啟動Nginx
    # nginx -c /project_dir/static/project_name.conf

  9. 啟動完成之後可以檢視一下網路埠的狀態
    # netstat -nltp
    正常情況下回列印出類似下列資訊. 顯示uwsginginx是處於服務狀態的.

    Active Internet connections (only servers)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
    tcp        0      0 0.0.0.0:6379            0.0.0.0:*               LISTEN      18977/./src/redis-s 
    tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      4752/nginx: master  
    tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1117/sshd           
    tcp        0      0 127.0.0.1:32000         0.0.0.0:*               LISTEN      969/java            
    tcp        0      0 127.0.0.1:8001          0.0.0.0:*               LISTEN      8989/uwsgi          
    tcp        0      0 127.0.0.1:9191          0.0.0.0:*               LISTEN      8989/uwsgi          
    tcp        0      0 0.0.0.0:8010            0.0.0.0:*               LISTEN      8989/uwsgi          
    tcp6       0      0 :::3306                 :::*                    LISTEN      1145/mysqld 
    
  10. 到這裡, 部署的全過程就完成了.

  11. 另外, 修改了檔案之後, Nginx需要重新啟動:
    # nginx -s reload


因筆者知識有限, 如有錯誤, 歡迎指正.
轉載請註明作者出處.

相關文章