thrift解读(三)——TNonblockingServer 内的 IO线程 和 work线程之间数据流处理逻辑

         一言概之   IO线程 负责跟客户端 通讯,IO线程读取一个完整的请求后,任务封装成(class TNonblockingServer::TConnection::Task)投递给work线程,work线程读取解析数据,处理业务逻辑完成后,把结果notify给IO线程,后者负责返回结果给客户端。TNonblockingServer内 N个IO thread、N个work thread都不止一个。

        呃,我们只考虑TNonblockingServer架构,因其性能较其他模式最高。

       名词: TNonblockingIOThread  ==   iothread 

TNonblockingServer逻辑图:

源码分块说明一:

1. TNonblockingIOThread 会使用libevent,如使用event_base_loop等函数。上层task要添加event,也得下到io thread的event_base上。io thread 0的listenSocket为服务器侦听套接字,只有它注册了listenHandler,所以也只有thread 0会侦听。

TNonblockingIOThread::run()

  if (listenSocket_ >= 0) {
        // 当新的连接请求进来的时候,TNonblockingIOThread::listenHandler 函数被触发,
        // 在 TNonblockingIOThread::listenHandler 里主要负责 accept 新连接。
    event_set(&serverEvent_,
              listenSocket_,
              EV_READ | EV_PERSIST,
              TNonblockingIOThread::listenHandler,
              server_);

    static void listenHandler(evutil_socket_t fd, short which, void* v) {
    ((TNonblockingServer*)v)->handleEvent(fd, which);
  }

在thrift0.9.3里,io thread 0也是thrift服务器主线程。如果只有一个io thread(即io thread 0)则此io thread 负责所有io

    // 当0号iothread 监听到accept事件时, 创建connection 并交给相应的iothread处理数据收发(通过管道方式通知相应的iothread)
    if (clientConnection->getIOThreadNumber() == 0) {
      clientConnection->transition();
    } else {// 如其名,就是通知iothread,具体是给该线程的pipefd发送this(connectionPtr)指针.
      clientConnection->notifyIOThread();
    }

2.  void TNonblockingServer::handleEvent(THRIFT_SOCKET fd, short which)

     -->createConnection()

     io thread 0接收一个连接,创建一个connection,同时分配某个io thread给这个connection。io thread主要负责io(socket的read和write),具体的task(用来处理Ttransport收上来的数据,做计算用)用thread manager里头的thread来完成。

除了listen socket外,其他connection(对应到一个io thread)都注册 TConnection::eventHandler和TNonblockingIOThread::notifyHandler,注册到iothread的event_base上头。

event_set(&event_, tSocket_->getSocketFD(), eventFlags_, TConnection::eventHandler, this);             eventFlags被设成read/write来控制io

TConnection::eventHandler()

        ->TConnection::workSocket()

             ->TConnection::transition()

                 ->TNonblockingServer::addTask(TNonblockingServer::TConnection::Task)

                    ->ThreadManager::add()

3. Worker Thread

worker是thread manager创建的线程实体,即用于计算的thread pool。worker的多少可以通过newSimpleThreadManager的参数count来指定。

worker::run()

        -->ThreadManager::Task::run()

          -->TNonblockingServer::TConnection::Task::run()  -->processor_->process(input_, output_, connectionContext_)

源码分块说明二:

1.   server 创建 多个 iothread 和  工作线程池 workpool  thread (给iothread发消息的方式主要通过管道的方式进行 )
2.   传递 listenfd 给 iothread 的 number 为0的线程,该线程监听listen socket的accept事件

3.  当0号 iothread 监听到accept事件时,创建 connection 并交给相应的 iothread 处理数据收发(通过管道方式通知相应的iothread)

4. iothread收到新的connection 根据 connection的状态 进行数据收发等处理 ,该逻辑由conection的
transition()函数完成, 第一部肯定是请求报文的read操作

5.当connection的一个请求数据read完成时, 封装成任务task交由workpool  thread 的线程池处理

6. workpool  thread 任务线程处理完成后会调用notifyIOThread通知connection对应的iothead来发送结果给客户端

7. iothread将处理完成结果发送给客户端, 一个请求处理完成.
 

serve()是它的入口方法。首先,sock bind listen常规过程,优先绑定IPV6地址。然后,构造TNonblockingIOThread线程池,不过默认只有1个线程。如果事先定义了preServe方法,则在这里调用。如果不是仅1个线程,建立PlatformThreadFactory对象装入1号和以上的线程。1号以上的线程是调用start进行启动,而0号就运行在当前线程中,直接调用run()方法。这样,一个TNonBlockingServer就启动了。

createConnection和returnConnection这一对方法,前者从TConnection栈中取出一个实例,并且轮询的从IO线程池取出一个线程关联到一起。后者将连接归还到栈中,或者销毁。这两个方法共同协调server的工作,而工作触发者是handleEvent方法。

handleEvent的核心是一个while循环,不停的accept请求,然后createConnection,调用目标连接的transition(不在同一个线程的话,要通过notifyIOThread的方式触发)。期间,会根据overload发生时候设置的策略,采取无操作、关闭连接还是清空任务队列行为。默认是无操作。而handleEvent的触发,在TNonblockingIOThread中则有

static void listenHandler(evutil_socket_t fd, short which, void* v) {
  ((TNonblockingServer*)v)->handleEvent(fd, which);
}

恰好是之前注册的套接字事件的回调函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值