情景描述:
上周,由于产品嫌报告生成太慢,经过使用
profile/gprof2dot
研究后,发现主要时间耗费在接口网络请求上,于是我决定在项目中大量处理I/O网络请求的地方使用gevent
,以缓解报告生成压力。
实现代码:
1 | import gevent |
问题:
上线后发现,代码运行一段时间后,请求一上来,任务数直线上升,一直增加:
但是,pool的数量是正常的:
之后log里报错信息:
1 | File "run.py", line 42, in update_data |
解决办法:
经过分析,解决办法:
monkey.patch_socket()
换为monkey.patch_all()
,或者,在使用完gevent
后使用reload(socket)
将socket初始化。
原因:应该是mongo写数据是阻塞的,请求快于写操作,导致写操作堆积越来越多,最终导致程序抛出Too many open files
错误。
最终代码,如下:
1 | import gevent |
另一个用例:
给传递两个参数,直接后面跟着就行,逗号分开;
返回如是多个情况的,value是一个以tuple为元素的list。
1
2
3
4
5
6
7
8
9
10
11 p = pool.Pool(10)
jobs = []
# date ('2017-07-01', '2017-07-14')
jobs = [p.spawn(self.crawl_a_call_log, date[0], date[1]) for date in dates]
gevent.joinall(jobs)
data_list = [x.value for x in jobs]
print data_list
if None in data_list:
message_list = [x.exception for x in jobs]
self.log('crawler', data_list, message_list)
raise Exception(message_list)
总结
协程(gevent)是把双刃剑,monkey.patch 是一个邪恶的东西;
提升效果不要太好,耗时足足降了60%,而且,请求越多,效果越明显。