概况
blue 的整个CS网络通信设计参考了TarsGo( https://github.com/TarsCloud/TarsGo ),在其基础上做了一些优化与微创新。
目前只提供了基于TCP通信协议的相关接口,后续会加入UDP或者RUDP通信。
代码包里提供了一个简单的TCPClient封装,里面有连接服务器、收发包基本功能。一般来说用不到,因为使用go做客户端的比较少。目前仅仅在blue的样例中使用。
设计细节
Server框架
利用go的语言特性,我们很方便的将Server需要的接口抽象出来,类似于C++的纯虚函数:
type ServerHandler interface { //设置监听地址端口 Listen() error //接受连接的主循环,根据不同协议处理不同 Run() error }
如果你需要自己加入相关的协议监听,上述interface的内容是必须要实现的。
处理收包
对于一个数据包的处理,一般需要先判断合法性(验证、完整……),然后根据内容对合法报文进行处理,同时预留一个超时处理的接口:
type ServerMsgProc interface { //处理一个完整的包 Invoke(ctx context.Context, pkg []byte) []byte //根据判断包的完整与合法性 ParsePackage(buff []byte) (int, int) //处理超时时调用 InvokeTimeout(pkg []byte) []byte }
这里TarsGo沿用了TarsCpp的设计,仅仅设计了传输层TCP/UDP协议报文收发,为了方便扩展,暴露出报文处理接口让用户自行处理。例如:服务端想使用更高层的Http协议交互,只需要在ParsePackage加入Http相关合法验证逻辑即可。
流程图
这里附加一张TCP协议从接受连接到报文处理的流程图,一些细节在图后补上:
整个处理流程都参考了TarsGo:
TarsGo的工作队列处理方式类似于轮询,处理的流程大致是这样:有一个任务队列和一个工人队列,每次从任务队列中取出一个任务,同时从工人队列中取出一个工作,将这个任务加入到工人的工作队列里,再将该工人加入工人队列尾部。
如此可以将负载很自然的均分,但是可能会涉及到一个数据同步的问题,举个例子:A先后下发了两个任务M和N,工人B和C按照次序分别接到了M和N任务,两个任务同时对数据X有读写。这里需要使用者自行保持数据X的一致性。
Blue在工作队列这里做了一点修改:
Blue做的修改是,将轮询改成了Hash,使用连接fd作为key。如此一来,虽然牺牲了一点负载均衡,至少能保证同一客户端的报文任务都能被顺序处理,一定程度上避免了数据一致性问题。(之所以这里措辞“一定程度”,主要原因是存在这种情况:A下发任务M,B下发任务N,工人C和D按照次序分别接到了M和N任务,两个任务同时对数据X有读写,还是需要使用者自行解决一致性问题)
(全文结束)
转载文章请注明出处:漫漫路 - lanindex.com