概述
在考察是否可以基于node开发下一代CTI平台时,我突然想到是否可以在现阶段修改pangu使其基于libuv。在研究如何使用node实现CTI时,因为必须满足node的事件驱动以及异步特性,所以用到了大量的异步模式。因为二者非常匹配,我指的是node和TSAPI,所以实现方式非常舒适。我又想到之前实现pangu时,尤其实现单请求多响应模型时非常难受。所谓的node和tsapi很匹配,倒不如说libuv和TSAPI很匹配。所以我就想到了基于libuv的pangu改造。
设计比较
pangu被设计成使用三个线程协同工作:收取AES发来的事件或响应数据、处理
AES发来的事件或响应数据和执行TSAPI函数。之前是三个线程,在转换到libuv后使用pangu的应用无需显式构建其他线程即可完成之前三个线程的功能。收取AES发来的事件或响应数据功能和处理AES发来的事件或响应数据功能,这二者可以合并并在主线程内完成,不再在单独的线程内各自执行。执行TSAPI函数的处理过程也将在主线程内完成。
pangu在连接AES成功后,将启动三个关联线程执行批量监视设备。这样做的意图是尽可能地压缩批量监视设备的时间。一次性发出十个或二十个监视设备请求,而不是在监视一个设备成功后再发起下一个监视请求。这样的方案有些类似libuv的设计思想。但他们是显式借助线程来完成的。使用libuv后方法类似,由于libuv框架缺省支持这类操作所以实现更便利。
实际应用环境下,使用pangu的应用还需处理网络请求、与数据库交互和其他异常保护处理过程。上述这些功能也都放置在单独的线程内完成。现在可以将它们全部放置在主线程内完成。
基于libuv的方案
为了描述方便,之后的描述中“收取AES发来的事件或响应数据”称为收取过程,“处理
AES发来的事件或响应数据”称为处理过程。之前之所以将他们分隔在不同线程内执行的目的是担心收取完直接处理会影响收取过程。如果处理过程的时间过长将会减缓收取的速度,一旦速度降到AES认为应用已无力处理更多的事件或响应数据,AES将主动关闭连接。之前的设计考虑到了这种异常情况。在libuv的事件驱动单线程模型下,可以采用其他的方案达到同样的目的。收取过程和处理过程均由libuv内的event loop通过定时器事件来触发。收取过程相关的定时器频率较处理过程相关的定时器高,如此设计的效果就是收取过程将获得更多的处理时间,从而避免上述异常情况出现。
执行TSAPI函数过程不过是一个生成执行对象并将执行对象交给工作线程执行的过程。我们要让所有在主线程内的处理都是无阻塞方式的。调用TSAPI函数的过程是个阻塞过程,因为这是一个发送TCP包的过程。所以
必须在其他线程内调用TSAPI函数,因此我们得使用libuv的uv_queue_worker。向此函数传入执行对象的同时,还需再提供一个回调函数。这个回调函数的作用是在实际的TSAPI函数执行完毕后在主线程内通知调用方调用是否成功。
启动时批量监视设备过程也将采用与执行TSAPI函数过程相同的策略。
libuv的例子中有很多关于网络通信的。libuv在单线程内能够很好的处理高并发量请求。
与数据库交互过程也将采用与执行TSAPI函数过程相同的策略。交互的实际过程将在后台工作线程内完成。
其他异常保护处理也将使用定时器触发执行。只不过它的定时器频率会低很多。
结论
通过上述分析可以得出基于libuv的pangu改造是可行的。但我们也无需将之前的一些设计完全从pangu中去除,只需为pangu增加一些在libuv下使用的接口即可。