thrift0.7源码浅析

最近读了一下thrift0.7 noblocking server 的部分源码,稍微做下记录。

thrift 使用libevent库做IO多路,

TNonblockingServer 负责初始化event, 增加监听端口,运行loop, 主线程有两个监听端口,一个是tcp listen,用来accept链接,

 一个是notify event , 使用socketpair 实现,一个端口用来读,一个端口用来写, 用在多线程完成读数据,执行任务后执行写操作,会通知到主线程将event_flag 设置成写操作,libevent就会选择合适的时候发送数据。server在一开始运行的时候会将notify event 的回调函数设置为:

926   static void taskHandler(evutil_socket_t fd, short /* which */, void* /* v */) {

927     TConnection* connection;

928     ssize_t nBytes;

929     while ((nBytes = recv(fd, cast_sockopt(&connection), sizeof(TConnection*), 0))

930         == sizeof(TConnection*)) {                                                                                                                       

931       connection->transition();

932     }

933     if (nBytes > 0) {

934       throw TException("TConnection::taskHandler unexpected partial read");

935     }

936     if (errno && errno != EWOULDBLOCK && errno != EAGAIN) {

937       GlobalOutput.perror("TConnection::taskHandler read failed, resource leak", errno);

938     }

939   }

940 

这个函数回去读socket的值,取回connection, 并按照connection之前设置的状态进行设置event flag。

线程安全:

nonblocking采用一个队列,主线程操作io, 所以io操作等没有锁,多线程去读队列,当一个线程在处理task时,会把该task对应的fd在主线程上关掉 event_del,无法处理新的数据,任务完成后把event_add回去。

每一个task最小单位是connection.void TConnection::transition()负责每个连接状态的改变以及把task push进队列。

TTransport 负责发送,接收数据

TProtocol 负责解包,压包

TProcess 负责协议包的分发执行。

connection有imput output buff, 负责读取数据之后放进input, ,然后push进task queue, task queue 执行run函数, processor_ process:

69   void run() {

 70     try {

 71       for (;;) {

 72         if (serverEventHandler_ != NULL) {

 73           serverEventHandler_->processContext(connectionContext_, connection_->getTSocket());

 74         }

 75         if (!processor_->process(input_, output_, connectionContext_) ||

 76             !input_->getTransport()->peek()) {

 77           break;

 78         }

 79       }



你可能感兴趣的:(thrift0.7源码浅析)