学习Golang之服务器框架编写 – CS网络通信

概况

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

Leave a Comment

Your email address will not be published.

鄂公网安备42018502003990号