poolboy是Erlang中运用非常广泛的进程池库,它有很多优点,使用简单,在很多项目中都能看到它的身影。不过,它也有一些坑,使用时候需要注意。(本文对poolboy的分析基于1.5.1版本)

worker创建不能失败

poolboy初始化的时候,或者当前进程池的worker数量超过默认值,都会新建worker。我们看一下新建worker的代码:

new_worker(Sup) ->
{ok, Pid} = supervisor:start_child(Sup, []),
true = link(Pid),
Pid.

可以看到,supervisor:start_child的时候是不能失败的,也就是说worker创建如果失败,会导致poolboy这个gen_server挂掉,导致整个进程池崩溃。

这会有什么影响呢,我们看一下用poolboy管理eredis的例子,参考其中的一个实现eredis_pool

创建worker失败,pool无法启动

eredis初始化代码,如果连接失败,eredis直接退出。如果用eredis_pool的话,当redis没有起来,或者某些其它原因导致eredis初始化失败(只要一次失败),会导致eredis_pool无法正常启动。

当然,如果redis无法正常工作,eredis_pool是不应该启动成功。但是如果进程池有100个worker,创建成功99个,第100个失败了,结果导致整个进程池退出,似乎有点太严格了。

所以有人对eredis提了个 issue,应该就是针对这个问题的。

创建worker失败,pool异常退出

具体可以看 create_pool的代码。

假如现在连接池配置有100个eredis client,当超过100个client时,poolboy会尝试启用overflow,新建eredis client。如果这时候因为某些原因,创建失败,结果也是一样,eredis_pool 异常退出。

观察网络连接,就会发现,这时候已有的redis client全部断链。当poolboy被重新拉起来的话,又会重新尝试建链。

根据上面分析可以看到,poolboy管理的worker有非常严格的规定,worker创建不能失败。如果失败,可能导致进程池无法正常启动,或者正常运行的进程池异常退出。

解决方法,加代理进程

在poolboy和进程之间加一个proxy process,proxy创建时不会去尝试建链,只做一些很简单的工作,确保进程初始化可以成功。在进行具体操作时,再去尝试建链。这样可以避免前面的问题,可以看 epgsql_pool或者 phoenix,或者我们自己fork的eredis_pool

proxy代理进程的问题

但是proxy有一个问题,那就是proxy进程里面的client不一定是正常的。看epgsql_pool和phoenix代码可以知道,proxy只保证自己创建的时候不会失败,至于它管理的client是不是正常的,只有在进行具体工作的时候,才可以知道。

这个大部分情况也没有什么问题,当新建worker,如果client连接有问题时,只会影响本次的poolboy调用,但是不会导致进程池崩溃。

当然可以在proxy进程里面加个定时器,定时去检查client的连接情况,如果失败,尝试重新建链。

但是深入代码时,会发现还是有一个坑。看poolboy checkin代码。当checkin时候,如果这个时候进程池数量大于默认值,已经启用了overflow,那么它会尝试关闭这个worker,dismiss_worker代码如下:

dismiss_worker(Sup, Pid) ->
true = unlink(Pid),
supervisor:terminate_child(Sup, Pid).

这个会有什么影响呢,我们分析一下这种情况。

poolboy默认配置100个worker,当worker超过100时,会启用overflow数量的worker。比如overflow为20,现在已经110个worker了。如果再次新建的client建链不成功,而同时110个worker已经有11个worker在checkin。这会导致10个worker被关闭,而这个不正常的worker checkin时可能没有被关闭。

换句话说,由于下面原因,导致正常的client被关闭,而不正常的client被保留。

  1. worker启动不能失败
  2. proxy不了解它管理的client是否正常
  3. 当进程启用overflow后,poolboy checkin会关闭worker

poolboy是一个简单,高效的进程池库,但是它对管理的worker有很严格的限制。例如管理redis client时,启动redis client不能失败,而且需要redis client自己管理链接,重连等等情况。即使采用proxy进程来管理redis client,仍然可能导致正常的redis client被关闭,而不正常的redis client存在pool中。

关于作者

微博@liaolinbo,云巴首席工程师。曾于Oracle工作。

poolboy的坑的更多相关文章

  1. worker_pool的例子

    鉴于poolboy的坑,pooler不支持r18,又有在知乎上看到大神推荐worker_pool这个进程池框架(工作者进程在创建时崩溃,worker_pool不受影响),所以研究了下,贴个小例子 my ...

  2. 如何一步一步用DDD设计一个电商网站(九)—— 小心陷入值对象持久化的坑

    阅读目录 前言 场景1的思考 场景2的思考 避坑方式 实践 结语 一.前言 在上一篇中(如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成),有一行注释的代码: public interfa ...

  3. 多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例

    前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...

  4. Spark踩坑记——Spark Streaming+Kafka

    [TOC] 前言 在WeTest舆情项目中,需要对每天千万级的游戏评论信息进行词频统计,在生产者一端,我们将数据按照每天的拉取时间存入了Kafka当中,而在消费者一端,我们利用了spark strea ...

  5. 多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)

    前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...

  6. 踩石行动:ViewPager无限轮播的坑

    2016-6-19 前言 View轮播效果在app中很常见,一想到左右滑动的效果就很容易想到使用ViewPager来实现.对于像我们常说的banner这样的效果,具备无限滑动的功能是可以用ViewPa ...

  7. 为C# as 类型转换及Assembly.LoadFrom埋坑!

    背景: 不久前,我发布了一个调试工具:发布:.NET开发人员必备的可视化调试工具(你值的拥有) 效果是这样的: 之后,有小部分用户反映,工具用不了(没反应或有异常)~~~ 然后,建议小部分用户换个电脑 ...

  8. 首个threejs项目-前端填坑指南

    第一次使用threejs到实际项目中,开始的时候心情有点小激动,毕竟是第一次嘛,然而做着做着就感受到这玩意水好深,满满的都是坑,填都填不过来.经过老板20天惨无人道的摧残,终于小有成就. 因为第一次搞 ...

  9. dll文件32位64位检测工具以及Windows文件夹SysWow64的坑

    自从操作系统升级到64位以后,就要不断的需要面对32位.64位的问题.相信有很多人并不是很清楚32位程序与64位程序的区别,以及Program Files (x86),Program Files的区别 ...

随机推荐

  1. tensorflow 运行成功!

    折腾了一天安装tensorflow环境,终于可以运行,也记录一下安装中容易犯的错误总结(写给python小白们) 一.win7 双系统 安装ubuntu 16.04 ,参考 http://jingya ...

  2. 开发Android必知的工具

    程序开发有时候非常依赖使用的开发工具,好的完备的开发工具可以让开发人员的工作效率有大幅度的提高.开发Android也是如此,大家可能都离不开Eclipse或Android Studio这些工具,但他们 ...

  3. c++ 访问者模式(visitor pattern)

    概述: 我们去银行柜台办业务,一般情况下会开几个个人业务柜台的,你去其中任何一个柜台办理都是可以的.我们的访问者模式可以很好付诸在这个场景中:对于银行柜 台来说,他们是不用变化的,就是说今天和明天提供 ...

  4. JsonView Tool

  5. pptv破解版程序,能够免费观看所有蓝光和会员影片!

    pptv破解版程序,能够免费观看所有蓝光和会员影片!PPTV网络电视3.4.1.0012绿色版(去广告本地vip版)由Black Hawk精简破解,去掉播放时缓冲.暂停广告.去掉迷你推荐和推荐弹窗.禁 ...

  6. 【转载】 IE/Firefox每次刷新时自动检查网页更新,无需手动清空缓存的设置方法

    [参考了别人的文章]我们做技术,经常在写页面的时候需要多次刷新测试,可是浏览器都有自己的 缓存机制,一般CSS和图片都会被缓存在本地,这样我们修改的CSS就看不到效果 了,每次都去清空缓存,再刷新看效 ...

  7. 【原创】14. MYSQL++之SSQLS(原理解析)

    从之前所介绍的SSQLS的介绍中我们可以感受到,SSQLS的精髓应该在sql_create_#这个宏,他所创建出来的这个结构体将会是突破的关键,所以我将会从以下顺序入手. 1. sql_create_ ...

  8. SpringMVC Controller 返回值的可选类型

    spring mvc 支持如下的返回方式:ModelAndView, Model, ModelMap, Map,View, String, void. ModelAndView @RequestMap ...

  9. webapp项目前端总结

    提纲 整体把握,从设计稿入手——技术选型 并行开发,从实现静态页面开始 前端自动化 前端js逻辑 前后端集成 小问题集合 总结 1.整体把握,从设计稿入手 —— 技术选型 新项目到手,算是运气好,设计 ...

  10. TypeWonder – 在任何网站上实时预览字体效果

    TypeWonder 让网页字体的选择过程变得轻松愉快.它可以帮助您在任何网站上快速测试 Web 字体效果!输入网站网址,就能够即时预览的字体的实际效果,还可以从数百种字体中进行挑选,您还可以得到所需 ...