天天看點

[技術部落格]伺服器部署

q2l

目錄

  • 0x0 了解uWSGI*
  • 0x1 部署uWSGI
  • 0x2 了解NGINX
  • 0x3 部署NGINX
  • 0x4 NGINX和uWSGI建立連接配接
  • Reference

​ 可能有的同學對UWSGI比較陌生,更多是知道NGINX,但是我們的伺服器一開始的時候是先使用了uWSGI,後來才加上NGINX的。

​ uWSGI,是一個對WSGI協定的實作的應用,是以我們先來了解一下什麼是WSGI。

​ WSGI,Web Server Gateway Interface,也叫做the Python Web Server Gateway Interface,顯然是為Python所準備的web伺服器網關接口,作用是在協定之間進行轉換。目前很多架構都自帶了uWSGI的實作,如Flash、Django、webPy等,但是自帶的實作性能不敢恭維,多用作測試,釋出的話需要自己重新配置。

​ 簡單點說,WSGI就是web伺服器和web應用之間的橋梁:

[技術部落格]伺服器部署

​ 其作用還可以用一副漫畫說明:

[技術部落格]伺服器部署
[技術部落格]伺服器部署
[技術部落格]伺服器部署

​ WSGI的作用此時應該已經了解了,總結一下:

  • WSGI有兩方:“伺服器”或“網關”一方,以及“應用程式”或“應用架構”一方。服務方調用應用方,提供環境資訊,以及一個回調函數(提供給應用程式用來将消息頭傳遞給伺服器方),并接收Web内容作為傳回值。
  • 所謂的 WSGI中間件同時實作了API的兩方,是以可以在WSGI服務和WSGI應用之間起調解作用:從WSGI伺服器的角度來說,中間件扮演應用程式;而從應用程式的角度來說,中間件扮演伺服器。
  • “中間件”元件可以執行以下功能:
    • 重寫環境變量後,根據目标URL,将請求消息路由到不同的應用對象。
    • 允許在一個程序中同時運作多個應用程式或應用架構。
    • 負載均衡和遠端處理,通過在網絡上轉發請求和響應消息。
    • 進行内容後處理,例如應用XSLT樣式表。

​ 差不多說完WSGI,接下來引入一下uwsgi,可能這時候有人迷惑了,一下大寫一下小寫,實際上這兩個是不同的:uwsgi與WSGI一樣是一種通信協定,是uWSGI伺服器的獨占協定,用于定義傳輸資訊的類型(type of information),每一個uwsgi packet前4byte為傳輸資訊類型的描述,與WSGI協定是兩種東西,據說該協定是fcgi協定的10倍快。我們的主角uWSGI是一個web伺服器,實作了WSGI協定、uwsgi協定、http協定等。

​ uWSGI的部署非常簡單,直接在python環境下安裝即可:

pip install uwsgi

​ 建立 test.py:

def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    return [b"Hello World"]
           

​ 運作uWSGI:

uwsgi --http :8001 --wsgi-file test.py

​ 此時在 http://127.0.0.1:8001 應該已經有Hello World的輸出了,說明安裝成功。

​ uWSGI可以配置多程序多線程,這個在後面一起講。

​ 其實一開始的時候,我們并不想部署NGINX,覺得直接用python的runserver+uWSGI跑足以,但是随着通路數量的增多,甚至我們組内的測試使用都會出現卡頓,這時我們覺得是應該學習一下了。

​ NGINX大家非常熟悉,但是對于更多JAVA後端的同學來說,APACHE應該是早有耳聞,APACHE和NGINX一樣是一種WEB伺服器,找到一張對比圖:

web服務功能 NGINX APACHE
方向代理 支援反向代理
Rewrite 非常好
fastCHI(網關接口)
熱部署 支援 不支援
系統壓力比較 很小
穩定性
安全性 一般
靜态檔案處理
動态檔案處理
虛拟主機
記憶體消耗 非常小 很大
擴充資料 很少 非常多

兩者最核心的差別在于:

APACHE是同步多程序模型,一個連接配接對應一個程序,而NGINX是異步的,多個連接配接(上萬級别)可以對應一個程序。

是以一般來說,需要性能的WEB服務,大多使用NGINX,而需要穩定的更考慮APACHE,後者的各種功能子產品實作都比前者更加完善,配置更多。更加通用的方案是:前端NGINX抗并發,後端APACHE叢集,組成配合。

像是淘寶、支付寶、迅雷、新浪部落格等高并發的網站,都是用的是NGINX作為WEB伺服器。

[技術部落格]伺服器部署
[技術部落格]伺服器部署

考慮到我們的實際情況:

  1. 伺服器配置低:2C4G
  2. 靜态資源請求多:加載登陸界面和個别界面需要加載背景圖檔
  3. 需要頻繁啟動:網站版本疊代更新快
  4. 對同時連接配接數量要求高
  5. 可能需要反向代理

根據上面幾個特點,我們選擇了NGINX作為web伺服器。

​ 接下來以我們運作CentOS的aliyun的2C4G的ECS伺服器為環境進行介紹。

​ 首先,需要安裝NGINX,在CentOS下直接

yum install -y nginx

即可。

​ NGINX的配置需要在

/etc/nginx/nginx.conf

中修改,這個等下一起說。

​ uWSGI對于動态資源的處理很好,NGINX對于靜态資源的處理很好,是以通常django應用會結合NGINX和uWSGI一起作為web服務端。NGINX抗高并發,接收所有的請求,對于靜态資源的請求直接自身處理,對于動态資源的請求再轉發給uWSGI處理。接下來詳述我們的NGINX配置:

user root; # 可能要給予NGINX程序以root執行的權限才能對socket之類的檔案進行改寫

worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.

include /usr/share/nginx/modules/*.conf;

# mysite_nginx.conf

events {
  worker_connections  1024;  ## Default: 1024
}

http
{
    server_tokens off;
    autoindex off;
    access_log off;
    include mime.types;
    default_type application/octet-stream;
    proxy_hide_header X-Powered-By;

		# 開啟gzip壓縮更快傳輸靜态資源
    gzip  on;
    gzip_min_length  1k; # 對請求的靜态資源的大小設定門檻值,小于1k的資源經過壓縮反而會變大
    gzip_buffers     4 16k;
    gzip_http_version 1.1;
    gzip_comp_level 9;
    gzip_types       text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php application/javascript application/json;
    gzip_disable "MSIE [1-6]\.";
    gzip_vary on;

		include /etc/nginx/mime.types;

    # the upstream component nginx needs to connect to
		# 在這裡 NGINX 負責連接配接的web服務端是django應用程式,是NGXIN的上遊upstream
    upstream django {
				# for a file socket
				# 這裡的server使用的是sock檔案,代替使用伺服器端口
        server unix:///your/path/to/backend.sock; 
        # server 127.0.0.1:8001; # for a web port socket (we'll use this first, but replace it later)
    }

    # configuration of the server
    server {
        # the port your site will be served on
        listen      80;
        listen      [::]:80;
        # the domain name it will serve for
        server_name your.ip.address; # substitute your machine's IP address or FQDN
        charset     utf_8_sig; # utf_8_sig 對中文的支援最好
        include /etc/nginx/default.d/*.conf;

        # max upload size
        client_max_body_size 75M;   # adjust to taste

        # Django media
        location /media  {
            alias /your/path/to/media;  # your Django project's media files - amend as required
        }

        location /static {
            # 注意這裡我們嘗試使用root來定義,請求的靜态資源是直接拼接在下面的路徑下的,使用root表示所在的根目錄,是以如果網站的靜态資源都存在于/frontend/static中,下面的root路徑應該寫/frontend檔案夾的路徑而不是/static的路徑,比如我們的登陸界面北京的連接配接為:http://website/static/img/bgd.cc940dc6.png,就是将/img/bgd.cc940dc6.png拼接到root後面進行請求
          	# 當然你也可以用上面的alias的别名方式,直接替換請求的路徑
            root /your/path/to/static‘s/parent; # your Django project's static files - amend as required
          	# 另一種寫法
            # alias /your/path/to/static;
          	break; 
        }

        # Finally, send all non-media requests to the Django server.
        location / {
            uwsgi_pass  django; # 設定将除靜态資源外的請求發送給誰,這裡的django是上面的upstream的django
            uwsgi_read_timeout 360s; # 設定逾時
            uwsgi_send_timeout 360s; # 設定逾時
            include /etc/nginx/uwsgi_params; # the uwsgi_params file you installed
          	index index.html;
        }   
}
           

​ 在 upstream django中,我們的server使用了一個套接字,實際上server還可以是伺服器的一個端口,如

:8001

端口,但是套接字socket是直接給予Unix的底層實作的,套接字檔案的讀寫速度非常快,當并發高時,Unix Socket比TCP port要快一些。但是如果要使用複雜均衡,則必須要使用TCP port。

​ 接下來設定負責處理動态資源請求的後端uWSGI,該檔案名為uwsgi.ini,存放在django項目檔案夾内:

[uwsgi]
# Django-related settings
# the base directory (full path)
chdir           = /your/path/to/backend
# Django's wsgi file

# module          = backend.wsgi

env = DJANGO_SETTINGS_MODULE=backend.settings    

# the virtualenv (full path)
home            = /your/path/to/venv 

# where wsgi file locate, normaly in app/wsgi.py
wsgi-file = app/wsgi.py 

# where the log file output
daemonize = nohup.out

# process-related settings
# master
master          = true
# maximum number of worker processes
processes       = 10
# the socket (use the full path to be safe
socket          = /your/path/to/backend.sock
# ... with appropriate permissions - may be needed
chmod-socket    = 664
# clear environment on exit
vacuum          = true

harakiri=360 # harakiri(伺服器響應時間)逾時伺服器停止計算
http-timeout=360 # 前後端斷開連結時間,伺服器繼續計算,單獨uwsgi時使用
socket-timeout=360 # 前後端斷開連結時間,伺服器繼續計算,配合nginx時使用

# python-autoreload=1
# buffer-size=1024

max-requests = 1000
           

​ 接下來看app應用内的wsgi的配置,該檔案存放在django項目的app應用檔案夾内:

"""
WSGI config for backend project.

It exposes the WSGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/3.0/howto/deployment/wsgi/
"""
import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'backend.settings')

application = get_wsgi_application()
           

  1. Python uWSGI 安裝配置
  2. uWSGI詳解
  3. uwsgi、wsgi和nginx的差別和關系
  4. Official | uwsgi WSGI quickStart
  5. Official | NGINX
  6. Python網絡程式設計之wsgi、uwsgi概念及作用