LF模式是个坑,ZeroIce中间件让你体会这个痛

LF模式是个坑,一个小小的失误就可能使你的网络处理瘫痪,Ice就很好地展现了出来,换句话说,Ice中间件或是LF模式就是一个坑,如果你一不小心。

LF模式的官方论文中,论述了此模式用于高性能网络并发模式,使用的是系统的隐式队列,也就是Reactor复用多路IO,(如果是select的话,还是会将事件收集到一个显式队列),每次只有一条线程可以有一次机会成为leader访问这个队列,从队列取出事件后放弃leader,同时唤醒另一线程(如果还有follower线程的话);注意这时的线程既不是leader也不是follower,它就可以处理事件,一般就是同步非阻塞读写,然后处理这个请求(通常来说就是dispatchFromThisThread)。当上面的工作结束就,才会作为follower等待成为leader,如果没有leader的话就会马上成为leader。在这种模式中,称为LF模式有点误导,因为实际上是三种状态,LPF,Leader,Process,Follower,状态机为 L->P->F->L->...。Follower状态的线程阻塞等待着Leader离开Leader状态去Process,从而唤醒可能的Follower状态的线程。被唤醒的Follower线程状态变为Leader,成为线程池中唯一当前有权操作队列的线程,要么阻塞在空队列,要么取出队列一个事件离开Leader状态去Process。线程池线程当Process完事件后才会状态变为Follower,或者阻塞等待Leader的唤醒,或者自动成为Leader。状态机就为 L(block on event queue)->P->F->(block on followers queue)->L ...。在这种模式下的线程池中,最多只有一个线程在Leader状态,并且只有这个Leader线程可以阻塞在IO事件队列,其它线程要么在Process状态处理事件,要么就是在Follower状态等待成为下一个Leader。当没有IO事件的时候,就只有一个线程在Leader状态阻塞在IO事件队列,其它线程都结事了事件的处理,并在Follower状态阻塞等待Leader线程释放信号。

通常用来衬托LF模式的,就是sync/async模式,并且都会举例Manager-Workers线程池。Manager负责将队列的事件指派到空闲Worker线程进行处理。Worker线程被唤醒处理完事件后再次阻塞等待Manager唤醒。当没有事件的时候,Manager阻塞在事件队列,Worker线程阻塞等待Manager线程唤醒。这种线程池有一个固定线程去阻塞在事件队列。并且每次Manager唤醒Worker都要通过堆来传递事件。(Manager从事件队列取出一个事件写入到堆内存,Worker从堆内存读到自己的栈,然后处理栈上的这个事件;而Leader从事件队列将一个事件读到自己的栈,再就唤醒其它Follower,然后处理栈上的这个事件。)当Manager线程不负责Reactor复用多路IO的情况,在空闲时发生了一次IO事件必须跨线程写入Manager线程的事件队列,并唤醒Manager线程,然后Manager线程唤醒Worker线程去处理事件。而LF模式线程池,Leader从系统的多路IO复用分离函数中返回,唤醒一个Follower,然后自己去处理事件。这样一比较就是Manager-Workers线程池进行了两次线程唤醒,而LF模式线程池只有一个线程唤醒(这里必须要公正,Leader是之前就被唤醒经历消耗了一次切换),事件在Manager-Workers线程池需要多次拷贝。

那么为什么LF模式不心就会踩坑,而Ice的设计就让体会这个坑。

问题在于如果LF模式线程池的线程进行Process阻塞等待IO响应,而所有的线程都在Process过程中阻塞等待IO响应,更重要这些被等待的IO应用在这个线程池的Reactor,就会再也没有线程成为Leader去多路IO分离函数中读取IO事件。这时候这个LF线程池就会瘫痪不工作。Ice中间件会让你深深体会这种痛。Ice采用ActiveObject模式进行OBR对象代理请求。控制线程调用proxy请求返回一个future,阻塞等待future。Communicator的clientThreadPool负责Reactor,收到请求的response后就向future发信号,从而唤醒这个response对应的future阻塞住的控制线程。这种情况下使用ORB对象代理请求的线程与网络Reactor线程池独立,负责Reactor的LF线程池不会被其它逻辑影响。但是在LF线程池中进行ORB对象代理请求呢?问题就来了。你的LF线程池随时都可能瘫痪掉,只要你不小心。极端地,LF线程池只有一个线程,这个线程在Process事件时,进行了ORB对象代理请求,阻塞等待future。Good Job!! 这个线程池中唯一的线程就永远不会再有机会成为Leader去取出远端的response的IO事件,去唤醒这个阻塞住线程的future了。这还不容易解决,都说是线程池,那会只有一个线程的呢。我们让这个LF线程池添加到两个线程,第一个线程取出事件唤醒第二个线程,然后自己处理事件时,进行了ORB对象代理请求,阻塞等待future;第二个线程成为Leader阻塞在多路IO分离函数,并在远端response到来时,从分离函数返回,得以唤醒了阻塞第一个线程的future。但是很不幸,第二个线程在等待到response到来之前,收到其它IO事件,而处理这个事件却进行了ORB对象代理请求,阻塞等待future。汗,LF线程池都被阻塞在future,future又等待IO事件。再往下演绎,不论LF线程池有多少线程,只要你的处理逻辑中进行了同步阻塞的ORB对象代理请求,都会使你的Ice网络处理瘫痪,瘫痪的原因是LF线程池瘫痪了。Ice的Server端线程池默认就在当前线程进行请求的dispatch,如果你在实现你的服务的时候必须依赖其它ORB对象代理请求时,你就要小心了,你可能因为这样而阻塞掉所有Communicator的Server端LF线程池,至使网络Reactor瘫痪。如果你使用了bidirection connection来提供callback的饲服,要是你在callback的实现中依赖了其它ORB对象代理请求时,你同样也要小心了,你可能因为这样而阻塞掉所有Communicator的Client端LF线程池,至使网络Reactor瘫痪。Ice为了避免,会默认为每个连接加上一个计时器,让连接自动断开。但是我们还是有应用场合希望连接长九不断开,关闭这种机制,这时就要小心了。再者就是,即使你所有的ORB对象请求代理都用异步方式(ami,amd)进行编程,但是悲剧的是你无法干涉到你依赖的其它人函数没有进行同步阻塞的ORB对象代理请求。

时间: 2024-08-25 02:57:32

LF模式是个坑,ZeroIce中间件让你体会这个痛的相关文章

LF模式解决的问题

一说起Leader/Followers并发模式,都会与Half-Async/Half-Sync并发模式进行比较,说LF模式更加高性能,成了一个高性能名词标签 符号,相反HA/HS仿佛成了一个低性能的名词标签,如果你的线程池不使用LF模式就谈论不上高效,要是你还在使用HA/HS模式,马上笼 统地建议换成LF模式,一切的问题会归根于HA/HS模式.那么为什么LF模式没有成一个标准的默认的并发模式呢,彻底取代其它并发模 式呢.因为Leader/Followers并发模式是设计用来解决Half-Asyn

Vmware虚拟机配置LVS/NAT模式遇到的坑。

这两天在研究LVS的负载均衡,先从最简单的LVS/NAT模式开始入手. 最后配置完之后能够相互之间Ping通,并且能够直接访问real服务器提供的web服务,而且防火墙也已经关闭了. 但是通过访问LVS服务器死活访问不了Real服务器,利用tcpdump和iftop监控软件查看了一下,发现握手出现的问题! 先说一下用于测试LVS/NAT模式的一些配置信息吧. [真实] PC的网络: 外网IP:xxx.xxx.xxx.xxx这个是运营商动态分配给我的一个公网IP. 内网IP:192.168.123

弹幕游戏子弹模式(占坑待续)

本文先占坑,我后续还会逐渐加入各种子弹模式. 首先,感谢UniBulletHell帮助我做了一些前期工作,这样可以更快的进入节奏.推荐想要使用unity制作弹幕类的同学,可以研究一下. UniBulletHell,它提供了很多基本的pattern和基本技术. 对于弹幕类游戏的制作,我也刚刚接触,我这几天还了解以下技术,BulletML,Danmaku Engine,DanmakU,DanmakX,CrazyStorm. 我不在此一一分析,诸位找到适合自己的就可以了. 上述gif给出的子弹模式均为

koa入坑及其中间件原理(1)

看见了吧,刚入坑koa总是会看见一张洋葱图(后面再说吧) 刚入坑一个东西的时候,我们总会问这个东西是什么?这个东西是用来做什么的?这个东西包括了哪些内容以及它的原理? 那好,我们先来解决第一个问题,koa.js是什么东西? koa.js是一个框架. 哈哈哈哈,第二个问题,koa.js用来做什么的? ① 对于 HTTP 服务 当前端 UI 向服务器发起了一个 HTTP 请求时,koa.js 能够在 HTTP 请求发送后 (要搞清楚,是已经发送出去的请求,并不是像 axios 一样拦截 reques

webpack集成vue单文件模式的很多坑(研究了1个星期)

1.一开始不知道局部安装webpack后,如何调用webpack. 后来看说明文档(webpack中文网)才知道,有个npx可以启动本地安装的webpack. 我估计:全局安装webpack,全局的webpack无法调用我的本地安装的很多包,以至于总是编译失败. 因此卸载全局包:npm uninstall -g webpack    ; npm uninstall -g webpack-cli npm安装模块 [npm install xxx]利用 npm 安装xxx模块到当前命令行所在目录:

Unity3d Android SDK接入解析(四)通用的Android SDK接入中间件

一.前言 接入Android SDK正式告一段落,在这段时间里面,依次接入了华为.应用宝.小米.360等等大大小小十来个SDK,也算对Unity接入渠道SDK有了较为全面的理解,对各个渠道的坑也算深有体会....在接入过程中时间比较紧张,没办法抽空来进行总结深思.今天正好有空,便对之前的接入SDK的代码进行了一次重构,写了一个比较通用的Unity接入Android SDK的中间件,前人栽树,后人乘凉. 进入正题 如果有对一些只是有疑问的,可以看看我之前的三篇文章: 传送门: Unity3d An

Android 开发中踩过的坑之六:几个关于View的tips

这几个点, 不算是坑, 但是也确实浪费了我一些时间 1.ScrollView的高设置成"wrap_content"会缩的很小,  ScrollView内只允许嵌套一个View, 并且不要将他的高度设置为"wrap_content", 否则它会缩小到很短的样子. ListView也是一样. 2.ListView中的Item如果有不同的样式,最好使用getItemViewType()来区别 事实上, 在ListView的Item完全可以用一种View布局来控制Visia

F2eTest和UI Recorder自动化测试环境部署填坑记录

坑1:尝试部署的时候只在opennode.bat里面填写了两个浏览器,测试通过后再增加其他浏览器,页面上一直不显示.需要清空数据库里的`wd_browsers`和`wd_nodes`表,然后重启2008,数据库会重新加载新的节点信息.(此坑的解决方法在视频教程里,无文字版) 坑2:远程连接问题:在2008启动之后,node暂未启动前,f2etestweb页面可以打开3个浏览器页面.当webdriver云上显示node已经启动之后,f2etestweb页面只能可以打开1个浏览器页面,再多就会报连接

什么是中间件

1. 由来 因为工作的原因,我从金蝶集团调入金蝶中间件公司工作以来,经常遇到一个问题就是中间件公司是个什么公司,中间件是什么?,金蝶不是做ERP的吗?怎么也做中间件?.这是我以前在金蝶集团时无法想象的问题.因为金蝶,金蝶ERP的品牌以及大众对ERP的了解,是无需我解析什么是ERP,什么是财务软件一类的问题的. 毕竟,中间件在实际的应用过程中,是对应用软件起到支撑作用,最终用户并不直接使用中间件,中间件不是大众消费类软件产品.因此,除非是一个行业专业人士,一般不大可能与中间件打交道,不太了解什么是