使用libevent和多线程构建高性能服务器(客户端)

有问题可以联系我[email protected]

    因为开发数据库集群,节点需要通信,必须构建基于socket的C++网络通信系统。多年前使用UPD写过P2P流媒体,但是现在需要TPC,首先使用了Nanomsg作为网络库,但是开发过程中发现其不靠谱(模式太单一,并且出了问题根本找不到解决办法)。于是又掉头回来使用原生的socket编程。发现目前比较流行的(C++)网络编程使用libevent或者libev,通过调研感觉libevent成熟一些,于是选择了libevent。

    下面说一下在我们数据库集群中对网络通信的使用模式:

1. 每个节点既是客户端又是服务器

2. 每个节点互相简历长连接(短连接的话,每次通信都要建立连接代价太高)

3. 节点之间发送消息使用rpc方式,因此选用了google的protobuf

4. 多线程服务模式,即每个消息都由不同的线程处理,这样复杂的消息也不会阻塞后面的消息。

    综上,我使用的是libevent+protobuf+pthread。libevent可以构建基于回调函数的socket网络库,protobuf提供rpc,pthread和libevent一起工作提供多线程方式。也可以使用std::thread,但是libevent默认支持的是pthread,你也可以在libevent中实现支持std::thread的函数,但是保险期间我还是用了pthread。下面举个具体的例子来说一下工作流程:

例如集群有10个节点,每一个节点都会和其他9个节点进行长连接,即每个节点都由9个socket,对应libevent有9个bufferevent,这9个bufferevent放入到一个eventbase里由主线程进行dispatch。每个bufferevent都有一个readcaback函数,主要这个bufferevent有消息到达,readcallback 就会被触发读取相应的消息,在read callback中把该消息丢到线程池中去处理:

    线程池会分配一个线程解析消息内容,然后调用protobuf的rpc方法,rpc方法处理完会产生一个response消息,该线程再把该response消息发送回去。

    客户端接收到response会触发read callback,因为客户端实际上也是服务端,所以处理流程也是一样的,read callback会把response消息丢给线程池,线程池在调用一个线程处理该response。

    具体代码请见github:https://github.com/cmu-db/peloton/tree/master/src/backend/networking

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章