當你跑通了前面一個demo,博客地址:http://www.cnblogs.com/kangoroo/p/7299920.html,那么你的分布式異步之旅已經起步了。
性能和穩定性是web服務的核心評價指標。下面我們來說,怎么樣部署服務,實現web服務的高並發和高可用。
我們將通過一些工具和部署,提升web服務的性能。
這篇文章我們先講高並發
部署方式:nginx+gunicorn+wsgi
1、django和python的缺陷分析
django作為一個python實現的web服務器,它的性能其實是沒有多大保證的。這是因為python的線程是不能共享機器資源的(因為萬惡的GIL),線程們只是通過頻繁切換控制權,來分享一個core上的時間片,讓你看起來是並發在跑,但是其實同一個時間只有一個線程在跑。那python是不是在自欺欺人?不是的。看你程序的類型:
1)IO密集型
IO密集型程序的耗時基本都在打開文件/打開句柄進行讀寫,也就是消耗在IO上。這種類型的程序,當線程阻塞在IO上時,交出線程控制權,給其他線程運行,當IO完成后再獲得控制權繼續跑,這樣的話,可以在IO的時候跑其他的線程,其實是可以提高代碼運行效率的。
2)計算密集型
你的程序基本就沒有IO,而是在跑一個算法。那么對不起,這種類型的程序,你通過python多線程編程無法提升效率,甚至會再頻繁切換線程控制權時,損失效率。
3)協線程greenlet
python的這種類型的線程(我們姑且叫他線程),只在IO阻塞的情況下進行線程控制權的切換。而gevent就是協線程的一個實現。
2、gunicorn部署
1)安裝gunicorn,並安裝協線程的支持
$ pip install gunicorn $ pip install greenlet # Required for both $ pip install eventlet # For eventlet workers $ pip install gevent # For gevent workers
2)改造你的django工程,讓他變成一個wsgi應用
在工程的settings.py中INSTALLED_APPS中加入gunicorn
INSTALLED_APPS = ( ...'djcelery', 'kombu.transport.django', 'gunicorn', )
然后你就可以這樣啟動了
nohup gunicorn --worker-class=gevent dmonitor.wsgi:application -b 0.0.0.0:8009 -w 4 &
打印如下,你使用了gevent的異步方式綁定本機8009端口啟動了4個進程(其實是5個,后面再說)
[2017-08-28 17:05:16 +0000] [24913] [INFO] Starting gunicorn 19.7.1 [2017-08-28 17:05:16 +0000] [24913] [INFO] Listening at: http://0.0.0.0:8009 (24913) [2017-08-28 17:05:16 +0000] [24913] [INFO] Using worker: gevent [2017-08-28 17:05:16 +0000] [24939] [INFO] Booting worker with pid: 24939 [2017-08-28 17:05:16 +0000] [24940] [INFO] Booting worker with pid: 24940 [2017-08-28 17:05:16 +0000] [24941] [INFO] Booting worker with pid: 24941 [2017-08-28 17:05:16 +0000] [24942] [INFO] Booting worker with pid: 24942
先簡單說明一下:
--worker-class:指定了異步方式,使用的是gevent方式實現的異步,也就是每個worker(進程)中線程之前切換使用的是協線程切換。
dmonitor.wsgi:application:dmonitor是django工程的名稱,你的django工程中要有wsgi.py文件。
-b:你的進程服務綁定哪個ip和端口
-w:啟動幾個worker
其實這樣你就部署完了!
介紹一下gunicorn
1)主從結構
gunicorn其實是個pre-fork的主從結構:一個master進程管理着多個worker進程,之前我們起了4個進程,但是實際上有5個就是因為有一個是master進程。
master進程不對外提供api,只是進行集群的管理,核心就是探活,一旦發現有worker進程掛掉了,那么master會把它拉起來。
2)worker數量的選擇
官方給出的公式是worker_num = (2 x $num_cores) + 1,num_cores是機器核數。
官方又說了,一般配置的數量是4-12個,就能夠支持上萬QPS。當然前提是你的web服務能處理的過來。
3)配置說明
懶得翻譯了,請看這里
4、nginx部署
在說nginx部署之前,先說一些廢話。
可能大家有個疑問,gunicorn和nginx有啥區別?或者說我使用了gunicorn已經啟動了多個實例,並且進行了負載均衡,我為什么要需要nginx呢?
一般來說是需要nginx的,原因有這幾點:
1)你的服務有沒有靜態文件?
2)你需不需要做灰度,需不需要攔截功能等等等?
3)你能保證你的服務能抗的住高峰壓力?
nginx的強大能讓你擁有上述的能力。當然nginx作為一個已經在無數生產環境中驗證過的web容器,還是很省心的。
回到這個系列,我們是想解決高並發異步場景,那么對高並發使用nginx有什么好處呢?
nginx可以做為一個緩沖器,nginx在接收完request之后,才開始轉發,如果nginx后面的服務疲於相應,nginx就會緩存request,等待空閑來到再進行轉發。這樣提高了系統的彈性。
部署nginx其實並沒有什么區別,因為通過gunicorn啟動的服務對外也只有一個ip:port
注意:我們這里是把靜態文件直接通過nginx進行轉發的,而不是通過web服務的模板引擎。這充分利用了nginx的高性能。
nginx配置文件
upstream dmonitor { server 10.93.84.53:8009; } server { listen 8080; server_name 10.93.84.53; access_log /var/log/nginx/dmonitor.log; location / { proxy_pass http://dmonitor; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location /static/ { #靜態文件目錄 root /home/.../static; }
熱加載配置文件你只需要執行如下命令
./nginx -s reload
