上篇介绍了一个简单的UDP服务框架,但是面对海量的请求,同步框架显然有点力不从心。于是在我接手好友系统的接口服务的时候,就采用了一个强大的异步框架——MCP框架。
MCP框架是一个多进程异步框架,支持UDP、TCP和http,结构很灵活,可以根据需要将各组件像搭积木一样组装。下面是MCP最基础的进程结构。分为3种进程:CCD、MCD和DCC。
CCD是面向客户端的进程,是服务的入口,负责处理前端的请求,维护连接,收发数据,并向MCD转发。其内部使用线程池实现对TCP请求的listen和accept。服务器内部进程之间使用flow(实际上是一个数字)来表示连接,因此CCD负责维护前端请求句柄和flow之间的映射关系。CCD一般根据端口和协议设置多个。
DCC是面向后端的进程,负责向其他服务发出请求。使用跟CCD类似实现方法,只是面向的是服务器。在经过协程改造的MCP框架中,DCC被去掉了,因为MCD通过协程就可以实现与后端的交互了。DCC跟后端的连接一般采用长连接,避免频繁创建和释放连接导致大量TIME_WAIT的情况。
MCD是服务器的核心进程,负责处理业务逻辑,通过epoll和回调函数实现异步。
进程之间通过MQ进行通信,MQ采用共享内存队列传输数据,而通过管道传输读写信号。如下图所示,进程首先把数据写入队列,当队列中的数据达到一定长度(避免每个请求都读取数据)时,MQ会通过管道传输一个字符。MQ的使用者只要通过epoll监听管道句柄,就可以及时地获得读写信号。
了解了MCP的基本原理,就可以根据业务的需要进程个性化的定制。例如因为MCD单进程可能有性能瓶颈,我们对其进行了扩展,改造成多MCD进程版本。如图所示,MCD后端派生出多个SUBMCD进程,SUBMCD进程负责处理真正的业务逻辑;而MCD进程退化成一个业务分发的程序,同时负责一些公共的业务逻辑,例如负责管理全局哈希表数据的超时清理(定期扫描超时节点,表太大的情况可以分次扫描,只要保持好扫描位置信息即可)。
SUBMCD直接跟CCD和DCC通信(图中省略了SUBMCD和CCD之间的MQ),通过配置文件设置,在服务初始化的时候就在各个需要通信的进程间创建好共享内存MQ。这样可以避免MCD成为通信瓶颈。
另外还派生出一个MONITOR进程,负责日志的收集和输出,还可以做其他一些耗时的操作,避免业务进程阻塞。
MCP框架兼有功能强大和性能卓越的优点。具体压测数据不太记得,在一个数据包转发服务中,QPS也在30W+。在使用上,有一定的学习成本,但是适用面非常广,可以说一个框架走天下。
原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/tech/aiops/183492.html