thrift non blocking server 源码浅析

来源:互联网 发布:c语言开发的开源项目 编辑:程序博客网 时间:2024/06/06 02:07

thrift 是一个开源是rpc服务框架,支持各种主流的开发语言,性能高效稳定。前段时间由于需要排查线上服务的问题,把thrift non blocking server的源码看了好几遍,发现其服务设计得很简洁,所以做了个总结。

一般情况下,后台开发服务都是用C/C++开发,个别情况下用python,server模式无非是用threadpool或者nonblocking server模式,相比threadpool,nonblocking server要更加常用一些。因为 threadpool 模式是一个客户端连接服务端就单独用一个线程来处理它的请求,这种情况适合一些客户端数量固定且处理请求的时间较长的场景;而nonblocking server更加适合维护大量活跃连接,每个请求处理时间较短的场景。


注:本文用的thrift版本是最新的版本:0.10.0


一般情况我们在main函数中是这样去写我们的启动程序的:


int main(int argc, char **argv) {  FLAGS_max_log_size = 200;  FLAGS_logbuflevel  = 0;  google::ParseCommandLineFlags(&argc, &argv, true);  google::InitGoogleLogging(argv[0]);  installQuitSignalHandler();  shared_ptr handler(new SecurityServiceHandler());  shared_ptr processor(new SecurityServiceProcessor(handler));  shared_ptr threadManager =  ThreadManager::newSimpleThreadManager(FLAGS_num_of_io_threads);  shared_ptr threadFactory = shared_ptr(new PosixThreadFactory());  threadManager->threadFactory(threadFactory);  threadManager->start();  TNonblockingServer server(    processor,    // boost::make_shared(boost::make_shared()),    boost::make_shared(),    boost::make_shared(),    boost::make_shared(),    boost::make_shared(),    FLAGS_port,    threadManager);  //::apache::thrift::server::TOverloadAction overloadAction = T_OVERLOAD_NO_ACTION;  //server.setOverloadAction(overloadAction);  std::cout << "default overload action: " << server.getOverloadAction() << std::endl;  server.serve();  std::cout << "server shutdown." << std::endl;  return 0;}

注释:

1、通过 ThreadManager::newSimpleThreadManager 去创建我们的工作线程。

2、::apache::thrift::server::TOverloadAction overloadAction = T_OVERLOAD_NO_ACTION;  server.setOverloadAction(overloadAction); 这个可以设置服务端的过载保护机制,默认是不处理的,也就是说server是不会拒绝大量客户端连接哪怕它现在非常忙碌。

另外的两种方式是:T_OVERLOAD_NO_ACTION 和 T_OVERLOAD_DRAIN_TASK_QUEUE。

T_OVERLOAD_NO_ACTION : 当server内部维护的连接数达到一个限制值的时候,新建的连接会被里面断开;

T_OVERLOAD_DRAIN_TASK_QUEUE : 这种方式稍微优雅点,server会去清除内部那些任务处于等待状态的连接(大部分情况下是延时较长的请求)。

3、nonblocking server 依赖 libevent 2 库。

4、在我们的启动代码看出,我们是通过创建一个server对象来运行服务的。


server 在启动之后只创建一个监听线程开始接收客户端连接,如下图

工作线程不会在服务run起来之后里面创建,而是当客户端开始发送请求的时候动态创建。也就是说。工作线程池里的线程数是随着请求量的增加而增加的,上限就是我们在启动代码中设置的那个值:ThreadManager::newSimpleThreadManager(FLAGS_num_of_io_threads);

注:FLAGS_num_of_io_threads 是用 gflags 定义的一个参数。


如下图所示,thrift nonblocking server 的模式,无法也就是依靠 libevent 的事件通知机制来接收客户端请求数据然后push到请求队列中,一个线程池的线程不断的轮询这个个请求队列,然后调用我们自己编写的处理器来消费请求数据。


所以,我们在编写我们的processor的时候要注意各种并发问题,如线程间共享数据的读写,避免死锁,代码的执行效率。




注:一般情况下服务端不会主动关闭客户端连接,除非客户端连接出现异常。