上个学期,给学校写了一个数据服务,主要从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