上個學期,給學校寫了一個數據服務,主要從oracle裏面讀取一些數據供查詢使用,很是快速的用web.py搭建了起來。調試順利,測試正常,上線!接下來就是捱罵了,我鐵定知道會卡,可是沒想到會那麼卡。在線10幾我的就已經沒法訪問了。我本身這裏調試仍是能夠正常訪問的,那就是負載量不夠唄。上nginx,起8個進程。好了很多喂,可是仍是有學生抱怨,時而正常,時而不正常。我就知道,快速完成的東西,大量用戶的東西,此次web.py有些頂不住了,期間還不死心上了一些組件來優化進程訪問,不一一細說,由於都沒有明顯好轉,啥獨角獸,啥uwsgi,啥fastCGI,通通效果不明顯。確定也是我水平不夠。這時候不得再也不拿出幾年前用來解決異步請求的tornado來。html
以web.py爲例,通常性開發管理系統因爲使用的用戶比較少,幾乎能夠忽略這個問題,或者經過增長負載用多進程來解決這個問題,由於一個簡單的小系統同時又8~10人在線使用就很不錯了。web.py在單個進程服務的時候,若是一個請求消耗的時間很長,另外的請求就會被阻塞,等待第一個請求獲得響應完成後纔會被響應,這就是阻塞問題,解決阻塞問題的方法就是啓用異步請求。原本在其餘開發語言裏這是個簡單的問題,可是在python裏,由於Python自身的設計就是單進程的,稍微麻煩了一些,仔細研究還有不少好玩的事情。python
第一步是換一個支持異步的tornado,第二步是在tornado中啓用異步。tornado的異步也有很多的方法,可是從應用角度來看,我以爲最終我選擇的這個方法對於原有系統結構的衝擊比較小。nginx
#coding=utf-8 __author__ = 'jy@cjlu.edu.cn' from concurrent.futures import ThreadPoolExecutor from tornado.web import RequestHandler from web.utils import storage opt_users = d_users() class WxBaseView(RequestHandler): executor = ThreadPoolExecutor(100)
#coding=utf-8 from tornado.concurrent import run_on_executor class List(WxBaseView): @run_on_executor def get(self): self.set_header("Content-Type", "text/html; charset=UTF-8") self.set_header("Access-Control-Allow-Origin", "*") self.write("hello tornado!") @run_on_executor def post(self): self.write("hello tornado!")
這裏注意一個要點,就是在響應函數get和post前增長@run_on_executor這個裝飾器,而這個裝飾器其實調用的是咱們在基類裏設置的ThreadPoolExecutor,這裏咱們設置了這個線程池是100個。web
這個的修訂方法對於解決用web.py快速開發的業務系統來講,代價很是的小,並且上線效果立刻見效,比啥優化都有效。由於你不再用由於一個耗時請求卡住整個進程了。100個線程池已經足以對付300個以上的在線用戶了。oracle