網站架構--WSGI,Gunicorn,Nginx,資料庫快取
python的web框架比如Flask,Django自帶的伺服器的目的是用於開發的,那麼在生產環境下我們使用什麼樣的伺服器呢?
WSGI協議:
web框架和web伺服器之間需要進行通訊,WSGI規定了一種在web伺服器與web應用程式/框架之間推薦的標準介面。
WSGI容器:
- 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
- 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
大型網站架構經驗
快取:
通常使用者訪問的熱點資料只集中在一小部分資料上,這部分資料應該儲存在快取中,這樣就減輕了後端應用的負擔。一共有四種快取方式:
- 本地快取:在應用伺服器內快取熱點資料,當請求訪問這些熱點資料的時候,可以直接從本機的記憶體裡面獲取熱點資料,而不用去訪問資料庫
- 分散式快取: 其實還是本地快取,但是當資料量特別大的時候,單機無法承受,所以需要分散式快取叢集,即應用程式通過網路來訪問快取。
- 反向代理: 代理伺服器是位於網站的機房之內的,所以使用者訪問的網站地址其實是代理伺服器地址,代理伺服器會決定是從後端返回資料還是從快取返回資料,還可以使用varnish來加速。
- CDN: 內容釋出網路快取,即釋出商出售快取伺服器給需要的網站,這些網站不用維護環從工作,只需要把內容提交到CDN釋出商就行,所以在CDN上快取網站的一些靜態資源可以有效提升頁面的載入速度。
負載均衡:
後端伺服器的各種效能可能都不一樣,所以較好的伺服器理應負擔更大的訪問量,較差的伺服器理應負擔較小的訪問量。通過負載均衡可以把使用者的請求分發到多臺後端裝置上,這樣就均衡了伺服器的負擔。
常見的負載均衡工具有LVS,HAProxy,Nginx:
- Nginx僅僅能支援HTTP,HTTPS,還有email等協議,使用場景最少,而且僅有它不能支援MySQL進行負載均衡。但是對網路的依賴非常小。
- LVS不支援正則
- HAProxy配置選項很多,最靈活,使用場景也多。
高可用:
現在單個節點已經無法滿足我們的業務要求,所以需要讓服務執行在多個節點上面,系統要有可用性,即組成系統的某些裝置或者元件失效或者宕機時,並不會中斷服務。
叢集:
使用叢集時解決高併發,海量資料問題的常用手段,當單體伺服器不能負擔的時候,不要盲目想著提高伺服器的效能,而是增加一臺伺服器來分擔原來的壓力。一般大型網站的大部分頁面都不是一個單獨的應用來提供服務,而是被分割成了多個部分,每個部分都由獨立部署的一個伺服器叢集來提供服務。
不同用途的伺服器對硬體資源的要求是不一樣的:
應用伺服器需要處理大量的業務邏輯,所以需要更快的CPU
檔案伺服器需要儲存大量使用者的檔案,所以需要更大的硬碟
資料庫伺服器需要快速的寫入資料和檢索到要查詢的資料快取,所以需要更快的硬碟和更大的記憶體