一言概之 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);
}
恰好是之前注册的套接字事件的回调函数。
4687

被折叠的 条评论
为什么被折叠?



