此内容接上一篇文章 才能看懂。
或判断是否收到30001(ECI_push_recvData)数据包,这个就要厂商协议组包解包了。
如下图数据框框的数据流。·
微信在2016年发布了一个RPC框架phxrpc,github地址是:。号称微信后台很多地方都使用到了,看了下,代码总体来说比较简单,但是其中有一些很有意思的地方,后面慢慢讲。
可以见微信文档[可能是phcrpc仅有的文档:)]:。
PhxRPC必须依赖的第三方库只有Protobuf。在编译前,在third_party目录放置好protobuf目录,或者通过软链的形式。这个third_party目录是没有的,需要自己创建,并且将protobuf代码放进去,。
所以如果想要生成的worker是使用协程方式执行,需要在sample下重新生成,或者你直接修改sample中的Makefile文件就OK:
后面的-c是server的配置文件。
这个search_tool_main是封装了client的可执行文件,上面的-f代表需要调用server中的哪个函数,-s代表这个函数需要什么参数。
如果需要使用方法,直接执行:
会有usage的提示。
下面着重讲一下phxrpc的整体的实现思路。
1).phxrpc的网络框架使用的epoll来进行调度的,你会看到各种各样的epoll,还有很多让我自己都觉得自己“无知”的写法:)。
2).phx并没有使用常规的“异步+回调”的方式,转而使用“协程”来处理线程中的阻塞问题。这个还是蛮有意思的,后面慢慢讲。
其他的就没什么特别的trick了。
phxrpc中主要的对象有以下几种:
这些对象的生成过程(流程)如下图,结合下图慢慢讲:
上面代码可知每个worker是一个独立的线程。
用于存储所有的resp和req数据。
至此:每个对象基本的功能都基本清楚了。
本小节讲一下基本的流程。
左侧主线程负责监听client请求:
需要设置SO_REUSEADDR标志。
作用:假设server在某种情况下进程被杀死,但是这个时候server的端口是没有被释放的,一般会内核保存一段时间,这个时候重启server的时候没法使用之前的地址,这样显然是不行的,如果换了地址,client就找不到了,所以这个时候设置SO_REUSEADDR表示重启后可以直接使用,无需等待2MSL时间。
// 意思是:如果在4ms内有事件被触发,那么执行下面的代码 // 如果超时了,那么会强制执行一次,此时是没有socket事件的,但是 // 可以处理下面轮询的工作啊,Orz... // 下面都是属于轮询(最迟4ms一次轮询)的工作 // 这些超时时间其实是一个heap(小根堆)进行管理的
上面的代码简直了,事件触发和轮询融合的“天衣无缝”…叼叼叼…
2).data flow
这个结构其实超级简单,就是两个队列:
3).worker流程
worker的流程比较简单,每个worker都是run在独立的线程中的,如果是协程模式,那么每个线程中有多个协程,使用epoll进行调度。
基本就是下面简单的循环完事:
上图中的1~7个子模块,简单细讲一下:
1).处理socket事件读写
这个比较简单,epoll对于管理的套接字进行,没什么好说的。
所以说到底,就是读取队列数据,注意多线程之间的互斥读取。此处的互斥使用的就是简单的加锁操作。
3).处理新到来的client fd
这个过程是比较重要的过程,从server主线程接收到client到最后,差不多分成三大步如下:
// 对于当前的task,创建一个协程
// swap到创建的协程执行
看上面的注释基本就清楚了新的client和server的交互流程。但是总体看来,代码的耦合性太强了,差点绕晕。。。
4).处理超时事件
此处所有的超时事件都是被管理在一个heap(小根堆)中,每次epoll轮询的时候都会判断哪些事件已经超时了,如果已经超时,那么执行相应的协程代码。
OK,至此phxrpc的整体流程和部分复杂流程讲完了,哎,代码看下来,感觉耦合性挺强的,所以有点晕。。。后面几篇会写一些关键点的实现。