1. 程式人生 > >網站架構--WSGI,Gunicorn,Nginx,資料庫快取

網站架構--WSGI,Gunicorn,Nginx,資料庫快取

python的web框架比如Flask,Django自帶的伺服器的目的是用於開發的,那麼在生產環境下我們使用什麼樣的伺服器呢?

WSGI協議:

web框架和web伺服器之間需要進行通訊,WSGI規定了一種在web伺服器與web應用程式/框架之間推薦的標準介面。

WSGI容器:

  1. Gunicorn
    易於配置,相容性好,CPU消耗少,支援多種worker模式。
pip install gunicorn
gunicorn --worker=3 project.app:app -b 0.0.0.0:9000
# 這是啟動應用的方式,第一個app是模組檔案的名字,第二個是檔案中flask例項的名字。
# 這裡worker推薦值是CPUx2+1,
python -c 'import multiprocessing; pring multiprocessing.cpu_count()'
# 虛擬機器只有一個CPU,所以使用3
  1. uWSGI
    使用C編寫,實現了自有的uwsgi協議的web伺服器
pip install uwsgi
uwsgi --http 0.0.0.0:9000 .....

uwsgi的啟動命令會複雜許多,如果需要使用可以仔細的閱讀官網!

web伺服器和應用伺服器的區別:

上面說的就是應用伺服器!!!!!
使用python開發的站點使用的主流web伺服器有Nginx,Apache,Tengine。

  • web伺服器主要負責處理HTTP協議,應用伺服器還能處理其他協議
  • web伺服器用於處理靜態頁面,對於動態內容,它通過WSGI藉口交給應用伺服器來處理
  • 一般應用伺服器集成了web伺服器,雖然集成了web伺服器,但是隻是為了除錯方便,處於效能和穩定性的考慮,生產環境中不使用應用伺服器。

選擇Nginx

Nginx是一個開源高效能的HTTP伺服器和反向代理。
sudo apt-get install nginx -yq 安裝完後就啟動了

部署Flask應用,通常都是使用一種WSGI應用伺服器配合Nginx作為反向代理!!!!

正向代理: 作為一個媒介在網際網路上獲取資源然後返回給相關聯的客戶端,代理和客戶端在一個區域網內,對於伺服器是透明的。
反向代理: 根據客戶端的需求,從後端的伺服器上獲取資源,再將資源返回給客戶端,代理和伺服器在一個區域網內,對客戶端是透明的。Nginx是反向代理的最佳選擇,反向代理的優點有:提高動態語言的IO處理能力,加密和SSL加速,安全,負載均衡,快取靜態內容,支援壓縮。

Nginx的配置檔案是block形式的,主要有6個:

block meaning
main 全域性設定,基本控制功能,包含events和http兩個block
events 事件設定,控制nginx處理連線的方式
http Http設定,下面包含了server和upstream兩個block
server 主機設定
upstream 負載均衡設定
location URL模式設定,在server下面,可有多個

適用於Nginx和Gunicorn模式的Nginx配置,.conf檔案

user  ubuntu ubuntu;
worker_processes  1;
worker_cpu_affinity auto;
worker_rlimit_nofile 65536;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  65536;
    accept_mutex off;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    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;

    keepalive_timeout  75 20;
    proxy_read_timeout 200;
    keepalive_requests 100000;

    client_header_timeout 10m;
    client_body_timeout 10m;
    client_max_body_size 20m;
    send_timeout 10m;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;

    gzip on;
    gzip_min_length 1000;
    gzip_proxied any;
    gzip_types text/plain text/css
               application/x-javascript application/xml
               application/atom+xml text/javascript;

    upstream frontends {
        server 127.0.0.1:8000;
        server 127.0.0.1:8001;
        server 127.0.0.1:8002;
        # server unix:/tmp/gunicorn.sock;
    }

    server {
        listen 80;
        server_name localhost;
        keepalive_timeout 5;

        location ^~ /static/ {
            root /home/ubuntu/web_develop/static;
        }

        location ~* \.(woff|eot|ttf|svg|mp4|webm|jpg|jpeg|png|gif|ico|css|js)$ {
            expires 30d;
        }

        location / {
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Scheme $scheme;
            proxy_redirect off;
            proxy_pass http://frontends;

            # 如果開啟keepalive需要指定如下2項
            # proxy_http_version 1.1;
            # proxy_set_header Connection "";
        }
    }
}

替換預設的Nginx配置:

sudo cp .../nginx_gunicorn.conf  /etc/nginx/nginx.conf
sudo /etc/init.d/nginx reload
# 上面的重啟之前是可以來驗證配置檔案的語法
sudo /etc/init.d/nginx configtest

Nginx的負載均衡演算法:

  • round-robin:輪詢演算法,按時間順序逐一分配到不同的後端伺服器。
  • least_conn:請求傳送到活躍連結數最少的伺服器
  • ip_hash:按訪問IP的雜湊結果表分配結果
  • hash:按某個鍵的雜湊結果分配

通過Gunicorn啟動flask應用:

上面的Nginx配置設定了8000-8002三個後端埠,為了演示,啟動8000埠的Gunicorn例項:
gunicorn -w 3 project.app:app -b :8000
然後通過Nginx訪問flask應用;
http http://localhost



快取

快取系統Memcached

頻繁通過直接訪問資料庫獲得資料的方式對資料庫造成很大的負擔Memcached是一個高效能的分散式記憶體物件快取系統,它通過在記憶體中快取資料來減少讀取資料庫的次數。目前最好用的Python客戶端是Libmc
首先安裝Memcached:
sudo apt-get install memcached 安裝後就直接啟動了,這是預設的啟動方式
下面使用Memcached分散式處理快取:
/usr/bin/memcached -m 64 -p 11212 -u memcache -l 127.0.0.1 -d

下面再安裝libmc:
pip install libmc
Libmc的配置:

# coding=utf-8
from libmc import (
    Client, MC_HASH_MD5, MC_POLL_TIMEOUT, MC_CONNECT_TIMEOUT, MC_RETRY_TIMEOUT
)
from mc_decorator import create_decorators

mc = Client(
    [
        'localhost',  # 預設埠為11211, 所以和下面的一個是等價的
        'localhost:11212',
        'localhost:11213 mc_213'
    ],  # 第一個引數為Memcached伺服器列表
    do_split=True,  # 預設值為false, 不接受大於1MB,設定為True,小於10MB的會被切片分段,但是不能儲存大於10MB的資料
    comp_threshold=0,
    noreply=False,
    prefix=None,
    hash_fn=MC_HASH_MD5,
    failover=False
)

mc.config(MC_POLL_TIMEOUT, 100)  # 100 ms
mc.config(MC_CONNECT_TIMEOUT, 300)  # 300 ms
mc.config(MC_RETRY_TIMEOUT, 5)  # 5 s

globals().update(create_decorators(mc))

使用Memcached例項:
首先實現一個裝飾器,可以在方法上定義快取鍵和快取時間。
具體方法省略,網上自行查詢,我們重點介紹Redis

鍵值對資料庫Redis

Redis詳解



大型網站架構經驗

快取:
通常使用者訪問的熱點資料只集中在一小部分資料上,這部分資料應該儲存在快取中,這樣就減輕了後端應用的負擔。一共有四種快取方式:

  • 本地快取:在應用伺服器內快取熱點資料,當請求訪問這些熱點資料的時候,可以直接從本機的記憶體裡面獲取熱點資料,而不用去訪問資料庫
  • 分散式快取: 其實還是本地快取,但是當資料量特別大的時候,單機無法承受,所以需要分散式快取叢集,即應用程式通過網路來訪問快取。
  • 反向代理: 代理伺服器是位於網站的機房之內的,所以使用者訪問的網站地址其實是代理伺服器地址,代理伺服器會決定是從後端返回資料還是從快取返回資料,還可以使用varnish來加速。
  • CDN: 內容釋出網路快取,即釋出商出售快取伺服器給需要的網站,這些網站不用維護環從工作,只需要把內容提交到CDN釋出商就行,所以在CDN上快取網站的一些靜態資源可以有效提升頁面的載入速度。

負載均衡:
後端伺服器的各種效能可能都不一樣,所以較好的伺服器理應負擔更大的訪問量,較差的伺服器理應負擔較小的訪問量。通過負載均衡可以把使用者的請求分發到多臺後端裝置上,這樣就均衡了伺服器的負擔。
常見的負載均衡工具有LVS,HAProxy,Nginx:

  • Nginx僅僅能支援HTTP,HTTPS,還有email等協議,使用場景最少,而且僅有它不能支援MySQL進行負載均衡。但是對網路的依賴非常小。
  • LVS不支援正則
  • HAProxy配置選項很多,最靈活,使用場景也多。

高可用:
現在單個節點已經無法滿足我們的業務要求,所以需要讓服務執行在多個節點上面,系統要有可用性,即組成系統的某些裝置或者元件失效或者宕機時,並不會中斷服務。

叢集:
使用叢集時解決高併發,海量資料問題的常用手段,當單體伺服器不能負擔的時候,不要盲目想著提高伺服器的效能,而是增加一臺伺服器來分擔原來的壓力。一般大型網站的大部分頁面都不是一個單獨的應用來提供服務,而是被分割成了多個部分,每個部分都由獨立部署的一個伺服器叢集來提供服務。

不同用途的伺服器對硬體資源的要求是不一樣的:
應用伺服器需要處理大量的業務邏輯,所以需要更快的CPU
檔案伺服器需要儲存大量使用者的檔案,所以需要更大的硬碟
資料庫伺服器需要快速的寫入資料和檢索到要查詢的資料快取,所以需要更快的硬碟和更大的記憶體