gevent 使用踩坑
简单介绍
- gevent 基本概念:
调度器: hub
上下文切换管理: switch
主循环: loop
协程: greenlet - gevent 特性:
优点:
高效,实现简单,易维护
缺点:
和go不一样,并不是python原生支持的功能,所以使用起来难免会踩一些坑,但是由于并不是实现方式有问题,所以存在着点弊病并没有什么问题。
开始使用
- 什么情况下可以使用:
足够了解自己服务所使用的io, 写的代码足够规范,否则会出现出了问题都不知道那里有问题。
需要并行化的代码不能阻塞时间过长,否则没有意义。
存在大量的io, 前提是可以变成非阻塞的,否则不能满足条件2。 由于发现api的代码满足以上三条,所以开始进行优化:
第一版代码如下:classParallelTask(object):def__init__(self, timeout=5):# 覆盖python原生的socketgevent.monkey.patch_socket()self.timeout=timeoutself.task=[]deftaskAppend(self, task,*args):self.task.append(gevent.spawn(task,*args))defrun(self):errno, err_msg=get_error(AwemeStatus.SUCCESS)try:gevent.joinall(self.task, timeout=self.timeout)returnerrno, err_msgexceptException, ex:logger.exception("[ParallelTask] run task fail error=%s"%ex)errno, err_msg=get_error(AwemeStatus.REE_PARALLEL_TASK)returnerrno, err_msg# handlerdef__getAwemeList(self, category_id, req_type):pass# 创建一个并行处理的任务paralle_obj=ParallelTask()paralle_obj.taskAppend(self.__getAwemeList, category_id, req_type)errno, err_msg=paralle_obj.run()代码看似没有问题,自测也没发现什么问题。
- 上线观察:
果不其然,出问题了。。。
错误发生在 challengeDetail 接口, 也是奇怪,上的明明是category 接口。
不过看错误知道应该是掉RPC没有成功, 查看RPC的日志可以看到全是fail。 - 分析问题:
首先RPC失败肯定是由于使用gevent 引起的。但是我在这category使用gevent 为啥会影响challengeDetail 呢。
观察最上面的 ParallelTask 代码,里面使用了monkey patch , 没错就是这个东西,重写了python原生socket ,使其支持了非阻塞io。
所以在没有并行化的代码里使用RPC调用,里面使用的socket变成了非阻塞的,而这些调用不受hup控制,所以肯定会出现调用失败的情况。 解决:
解决办法很简单,在用完monkey patch 之后恢复原生的socket不久好了。 gevent 没有提供接口恢复,所以自己实现了下。defrepatching(item):try:# 需要重新写回的modulemodule=__import__(item)# 需要重写的属性saved=gevent.monkey.savedmapper=saved.get(item, {})forattrinmapper:old_value=mapper.get(attr)ifnotold_value:continuesetattr(module, attr, old_value)exceptException, ex:logger.exception("[gevent] repatching fail error=%s"%ex)classParallelTask(object):def__init__(self, timeout=5):# 覆盖python原生的socket, 使用完记得repatching 不然会有未知错误gevent.monkey.patch_socket()self.timeout=timeoutself.task=[]deftaskAppend(self, task,*args):self.task.append(gevent.spawn(task,*args))defrun(self):errno, err_msg=get_error(AwemeStatus.SUCCESS)try:gevent.joinall(self.task, timeout=self.timeout)returnerrno, err_msgexceptException, ex:logger.exception("[ParallelTask] run task fail error=%s"%ex)errno, err_msg=get_error(AwemeStatus.REE_PARALLEL_TASK)returnerrno, err_msgfinally:# 使用完非阻塞的网络io之后一定要改回来repatching('socket')- 线上观察:
bug 修复之后线上没有新的问题爆出来,至今稳定运行着, 本来打算用go优化的接口看样子也不需要了, 并行化之后接口的时延由3s 降低到了300ms, 降低的幅度也符合预期 (30个rpc并行)
gevent 使用踩坑的更多相关文章
- Spark踩坑记——Spark Streaming+Kafka
[TOC] 前言 在WeTest舆情项目中,需要对每天千万级的游戏评论信息进行词频统计,在生产者一端,我们将数据按照每天的拉取时间存入了Kafka当中,而在消费者一端,我们利用了spark strea ...
- Spark踩坑记——数据库(Hbase+Mysql)
[TOC] 前言 在使用Spark Streaming的过程中对于计算产生结果的进行持久化时,我们往往需要操作数据库,去统计或者改变一些值.最近一个实时消费者处理任务,在使用spark streami ...
- 【踩坑速记】二次依赖?android studio编译运行各种踩坑解决方案,杜绝弯路,总有你想要的~
这篇博客,只是把自己在开发中经常遇到的打包编译问题以及解决方案给大家稍微分享一下,不求吸睛,但求有用. 1.大家都知道我们常常会遇到dex超出方法数的问题,所以很多人都会采用android.suppo ...
- NPOI导出Excel (C#) 踩坑 之--The maximum column width for an individual cell is 255 charaters
/******************************************************************* * 版权所有: * 类 名 称:ExcelHelper * 作 ...
- 我的微信小程序入门踩坑之旅
前言 更好的阅读体验请:我的微信小程序入门踩坑之旅 小程序出来也有一段日子了,刚出来时也留意了一下.不过赶上生病,加上公司里也有别的事,主要是自己犯懒,就一直没做.这星期一,赶紧趁着这股热乎劲,也不是 ...
- router路由去掉#!的踩坑记
项目中在研究去掉router#!的过程中的踩坑过程.
- vue+ vue-router + webpack 踩坑之旅
说是踩坑之旅 其实是最近在思考一些问题 然后想实现方案的时候,就慢慢的查到这些方案 老司机可以忽略下面的内容了 1)起因 考虑到数据分离的问题 因为server是express搭的 自然少 ...
- 记jQuery.fn.show的一次踩坑和问题排查
最近很少已经很少用jQuery,因为主攻移动端,常用Zepto,其实很多细节和jQuery并不一样.最近又无意中接触到了PC的需求和IE6, 使用了jQuery,刚好踩坑了,特意记录一下. 本文内容如 ...
- WebForm路由踩坑 ajax请求多次
WebForm路由踩坑 再次接触Asp.Net WebForm已是4年后的今天,源起新入职的公司,一个老的项目. Web接触的少,那就多动手写写. WebForm1.aspx <body> ...
随机推荐
- MySQL的information_schema的介绍(转)
转自:http://www.cnblogs.com/hzhida/archive/2012/08/08/2628826.html, 大家在安装或使用MYSQL时,会发现除了自己安装的数据库以外,还有一 ...
- Spring Boot: Spring Starter Project
好久没有创建过新项目,楼主发现Spring Boot项目创建失败了!!! 其中有两处错误: [图一不知道是哪里错,果断删掉重输入一次.成功进入下一步 其余步骤也没有错误,然而 最后一步失败了,如图 ...
- hihoCoder #1079 : 离散化 (线段树,数据离散化)
题意:有一块宣传栏,高一定,给出长度,再给出多张海报的张贴位置,问还能见到几张海报(哪怕有一点被看到)?假设海报的高于宣传栏同高. 思路:问题转成“给出x轴上长为L的一条线段,再用n条线段进行覆盖上去 ...
- windows定时任务小注
static class Program { /// <summary> /// 应用程序的主入口点. /// </summary> [STAThread] static vo ...
- caffe的pad的报错
CHECK((!conv_param.has_stride() && conv_param.has_stride_h() && conv_param.has_strid ...
- Pacman常用命令 文内搜索吧
列出已经安装的软件包 https://wiki.archlinux.org/index.php/Pacman_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87) 维基 pa ...
- Python基础篇 -- 运算符和编码
运算符 记熟 ! ! ! 2**1=2 2**2=4 2**3=8 2**4=16 2**5=32 2**6=64 2**7=128 2**8=256 2**9=512 2**10=1024 运算符 ...
- jExcelAPI导入导出excel
MS的电子表格(Excel)是Office的重要成员,是保存统计数据的一种常用格式.作为办公文档,势必要涉及到的电子文档的交换,Excel是一种在企业中非常通用的文件格式,打印和管理也比较方便.在 ...
- Core Animation演示
相关代码展示: - (IBAction)toggleRoundCorners:(id)sender { [CATransaction setDisableActions:![_enableAnimat ...
- 随机生成一份试卷,试卷的种类分为单选、多选、判断三种题型。nodejs6.0 mysql
背景:从数据库中,随机生成一份试卷,试卷的种类分为单选.多选.判断三种题型. 首先我需要生成随机数id(在这之前我需要知道数据库中各个题型的题数,这样我才能设置随机数),并依据生成的随机数id,去查找 ...