目录

目录 1

1. 工作线程和IO线程 1

2. TNonblockingServer::TConnection::transition() 2

3. RPC函数被调用过程 3

4. 管道和任务队列 4

5. 对象间关系 5

6. 相关代码摘要 6

1. 工作线程和IO线程

启动Thrift时,可启动两类线程,一是TNonblockingIOThread,另一是Worker:

TNonblockingIOThread负责接受连接,和收发数据;而Worker负责回调服务端的用户函数。

TNonblockingIOThread::registerEvents主要做了两件事:

1) 注册TNonblockingIOThread::listenHandler(),这个是用来接受连接请求的;

2) 注册TNonblockingIOThread::notifyHandler(),这个是用来监听管道的。

TNonblockingIOThread和Worker两类线程间通过队列进行通讯,队列类型为std::queue<boost::shared_ptr<ThreadManager::Task> >。

class ThreadManager::Task: public Runnable

{

public:

void run()

{

// runnable_实际为TNonblockingServer::TConnection::Task

runnable_->run();

}

private:

// 这里的Runnable实际为TNonblockingServer::TConnection::Task

// 在TNonblockingServer::TConnection::transition()中被push进来

boost::shared_ptr<Runnable> runnable_;

};

2. TNonblockingServer::TConnection::transition()

transition()为状态切换函数,状态有两种:一是socket的状态,另一是rpc会话的状态。APP开头的是rpc会话的状态,SOCKET开头的是socket的状态。

在APP_READ_REQUEST状态发生在IO线程中,addTask()会将任务转交给或工作线程,然后由工作线程回调服务端的函数。

TNonblockingServer::TConnection::Task

{

public:

void run()

{

// 回调

processor_->process(input_, output_, connectionContext_);

// 回调完后通知,

// 从工作线程重回到IO线程

connection_->notifyIOThread(); // ioThread_->notify(this);

// 这个将触发TNonblockingIOThread::notifyHandler()

}

};

TNonblockingIOThread::notifyHandler()

{

// 从管道中取出connection的指针地址

TNonblockingServer::TConnection* connection = NULL;

int nBytes = recv(fd, cast_sockopt(&connection), kSize, 0);

connection->transition(); // 进入状态转换函数

}

3. RPC函数被调用过程

IO线程收到完整的RPC请求包时,以任务方式转给工作线程,然后由工作线程回调用户写的RPC函数。

完成的调用过程如下图所示:

任务从IO线程进入工作线程:

4. 管道和任务队列

IO线程以Task方式将连接交给工作线程,而工作线程在回调完后,以管道方式还回给IO线程。连接从IO线程进入到或工作线程后,会从libevent中删除,返回后再进入libevent。

5. 对象间关系

class TNonblockingServer: public TServer

{

public:

void serve() // 用户可以直接调用server(),但直接调用run()是更好的做法

{

// 创建socket监听

// 创建TNonblockingIOThread

// 通过Thread启动TNonblockingIOThread

}

};

class TServer: public concurrency::Runnable

{

public:

virtual void serve() = 0;

virtual void run() // 用户也可以直接调用run()

{

serve();

}

};

6. 相关代码摘要

// 线程

// thrift支持原生posix线程和boost线程

void PthreadThread::start()

{

// PthreadThread是一个Posix线程类

pthread_create(&pthread_, &thread_attr, threadMain, (void*)selfRef);

}

static void* PthreadThread::threadMain(void* arg)

{

thread->runnable()->run();

}

// 以下为IO线程

/// Three states for sockets: recv frame size, recv data, and send mode

enum TSocketState

{

SOCKET_RECV_FRAMING,

SOCKET_RECV,

SOCKET_SEND

};

/**

* Five states for the nonblocking server:

*  1) initialize

*  2) read 4 byte frame size

*  3) read frame of data

*  4) send back data (if any)

*  5) force immediate connection close

*/

enum TAppState

{

APP_INIT,            // 初始化

APP_READ_FRAME_SIZE, // 接收包大小

APP_READ_REQUEST,    // 接收包数据

APP_WAIT_TASK,

APP_SEND_RESULT,     // 发送数据

APP_CLOSE_CONNECTION // 关闭连接

};

// 启动监听和IO线程

void TNonblockingServer::serve()

{

createAndListenOnSocket();

for (uint32_t id = 0; id < numIOThreads_; ++id)

{

// TNonblockingIOThread是一个Runnable

// 以委托方式被运行在PthreadThread中

thread = new TNonblockingIOThread(this, id, listenFd, useHighPriorityIOThreads_);

ioThreads_.push_back(thread);

}

for (uint32_t i = 1; i < ioThreads_.size(); ++i)

{

// PthreadThread thread;

thread->start();

}

ioThreads_[0]->run(); // 这将阻塞调用线程

for (uint32_t i = 0; i < ioThreads_.size(); ++i)

{

ioThreads_[i]->join();

}

}

void TNonblockingIOThread::run()

{

eventBase_ = event_base_new();

// IO线程在启动时会调用registerEvents()

// 在registerEvents()中完成两个回调函数的注册:listenHandler和notifyHandler

// listenHandler回调负责接受请求,并创建连接对象

registerEvents();

event_base_loop(eventBase_, 0); // libevent

}

void TNonblockingIOThread::registerEvents()

{

// listenHandler和socket关联

event_set(&serverEvent_, listenSocket_, EV_READ | EV_PERSIST,

TNonblockingIOThread::listenHandler, server_);

// notifyHandler和pipe关联

event_set(¬ificationEvent_, getNotificationRecvFD(), EV_READ | EV_PERSIST,

TNonblockingIOThread::notifyHandler, this);

}

static void listenHandler(evutil_socket_t fd, short which, void* v)

{

((TNonblockingServer*)v)->handleEvent(fd, which);

}

void TNonblockingServer::handleEvent(int fd, short which)

{

accept();

createConnection();

}

TNonblockingServer::TConnection* TNonblockingServer::createConnection()

{

// 会将自己绑定到一个线程

// 采用轮询的方式选择线程

// int selectedThreadIdx = nextIOThread_;

// nextIOThread_ = (nextIOThread_ + 1) % ioThreads_.size();

// std::stack<TConnection*> connectionStack_;

// 使用了内存池connectionStack_

// App状态:APP_INIT

// Socket状态:SOCKET_RECV_FRAMING

}

static void eventHandler(evutil_socket_t fd, short /* which */, void* v)

{

assert(fd == ((TConnection*)v)->getTSocket()->getSocketFD());

((TConnection*)v)->workSocket();

}

void TNonblockingServer::TConnection::setFlags(short eventFlags)

{

event_set(&event_, tSocket_->getSocketFD(), eventFlags_, TConnection::eventHandler, this);

}

void TNonblockingServer::TConnection::setRead()

{

setFlags(EV_READ | EV_PERSIST);

}

void TNonblockingServer::TConnection::setWrite()

{

setFlags(EV_WRITE | EV_PERSIST);

}

void TNonblockingServer::TConnection::setIdle()

{

setFlags(0);

}

void TNonblockingServer::TConnection::workSocket()

{

case SOCKET_RECV_FRAMING:

TSocket::read(); // 接收包大小

transition();

case SOCKET_RECV:

TSocket::read(); // 接收包数据

transition();

case SOCKET_SEND:

TSocket::write_partial(); // 发送数据(非阻塞的)

transition();

}

void TNonblockingIOThread::notifyHandler(evutil_socket_t fd, short which, void* v)

{

recv();

connection->transition();

}

// transition()为状态迁移函数

void TNonblockingServer::TConnection::transition()

{

case APP_INIT:

setRead();

case APP_WAIT_TASK:

setWrite();

case APP_READ_REQUEST:

setIdle();

}

TNonblockingServer::TConnection::Task

{

public:

void run()

{

// 回调

processor_->process(input_, output_, connectionContext_);

// 回调完后通知,

// 从工作线程重回到IO线程

// connection_的指针地址将通过管道传给工作线程

connection_->notifyIOThread(); // ioThread_->notify(this);

}

};

TNonblockingIOThread::notifyHandler()

{

// 从管道中取出connection的指针地址

TNonblockingServer::TConnection* connection = NULL;

int nBytes = recv(fd, cast_sockopt(&connection), kSize, 0);

connection->transition(); // 进入状态转换函数

}

// 以下为工作线程

class ThreadManager::Impl : public ThreadManager;

class SimpleThreadManager : public ThreadManager::Impl;

class ThreadManager::Worker: public Runnable;

class ThreadManager::Task : public Runnable;

void SimpleThreadManager::start()

{

// workerCount_为工作线程数

addWorker(workerCount_);

}

void ThreadManager::Impl::addWorker(size_t value)

{

for (size_t ix = 0; ix < value; ix++)

{

worker = new ThreadManager::Worker(this);

// thread为PthreadThread

// 调用了worker->run();

thread->start();

}

}

void ThreadManager::Worker::run()

{

ThreadManager::Task task;

task->run();

}

class ThreadManager::Task: public Runnable

{

public:

void run()

{

// runnable_实际为TNonblockingServer::TConnection::Task

runnable_->run();

}

private:

// 这里的Runnable实际为TNonblockingServer::TConnection::Task

// 在TNonblockingServer::TConnection::transition()中被push进来

boost::shared_ptr<Runnable> runnable_;

};

void ThreadManager::Impl::add(shared_ptr<Runnable> value)

{

// std::queue<shared_ptr<Task> > tasks_;

task = new ThreadManager::Task(value, expiration);

tasks_.push(task);

}

// 两者关系

class TNonblockingServer: public TServer

{

public:

TNonblockingServer(const boost::shared_ptr<ThreadManager>& threadManager);

private:

// TNonblockingServer关联了ThreadManager

boost::shared_ptr<ThreadManager> threadManager_;

};

// 工作线程将回调TNonblockingServer::TConnection::Task

class TNonblockingServer::TConnection::Task: public Runnable

{

};

// task为TNonblockingServer::TConnection::Task

void TNonblockingServer::addTask(boost::shared_ptr<Runnable> task)

{

// 将任务交给工作线程

// threadManager_为SimpleThreadManager

threadManager_->add(task, 0LL, taskExpireTime_);

}

void TNonblockingServer::TConnection::transition()

{

case APP_READ_REQUEST:

if (server_->isThreadPoolProcessing())

{

boost::shared_ptr<Runnable> task =

new TNonblockingServer::TConnection::Task(

processor_, inputProtocol_, outputProtocol_, this);

// server_为TNonblockingServer

// 回调交给工作线程,IO线程不做这个工作

server_->addTask(task); // server_为TNonblockingServer

}

else

{

// 调用TNonblockingServer的构造函数时,

// 如果没有指定参数ThreadManager,则会走这条分支

// 这种情况下,isThreadPoolProcessing()返回false

processor_->process(inputProtocol_, outputProtocol_, connectionContext_);

}

}

void TNonblockingServer::TConnection::Task::run()

{

// 回调

processor_->process(input_, output_, connectionContext_);

}

内嵌关系:

1) TNonblockingServer内嵌了类TConnection,而TConnection又内嵌了类Task

2) ThreadManager内嵌了类Impl、类Worker和类Task(注意区分于TConnection内嵌的Task),而Impl又是ThreadManager的子类,而Task是对Runnable的实现

class TNonblockingServer: public TServer

{

public:

void serve() // 用户可以直接调用server(),但直接调用run()是更好的做法

{

// 创建socket监听

// 创建TNonblockingIOThread

// 通过Thread启动TNonblockingIOThread

}

};

class TServer: public concurrency::Runnable

{

public:

virtual void serve() = 0;

virtual void run() // 用户也可以直接调用run()

{

serve();

}

};

Thrift线程和状态机分析的更多相关文章

  1. FS SIP呼叫的消息线程和状态机线程

    THREAD 当收到一次呼叫的时候,FS会在TU层创建两个线程,一个线程为状态机线程,另外一个为消息线程.状态机线程通过switch_core_session_thread_launch创建,顾名思义 ...

  2. JAVA线程池的分析和使用

    1. 引言 合理利用线程池能够带来三个好处.第一:降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗.第二:提高响应速度.当任务到达时,任务可以不需要等到线程创建就能立即执行.第三:提 ...

  3. [转]ThreadPoolExecutor线程池的分析和使用

    1. 引言 合理利用线程池能够带来三个好处. 第一:降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗. 第二:提高响应速度.当任务到达时,任务可以不需要等到线程创建就能立即执行. 第 ...

  4. Java 线程池原理分析

    1.简介 线程池可以简单看做是一组线程的集合,通过使用线程池,我们可以方便的复用线程,避免了频繁创建和销毁线程所带来的开销.在应用上,线程池可应用在后端相关服务中.比如 Web 服务器,数据库服务器等 ...

  5. 线程组ThreadGroup分析详解 多线程中篇(三)

    线程组,顾名思义,就是线程的组,逻辑类似项目组,用于管理项目成员,线程组就是用来管理线程. 每个线程都会有一个线程组,如果没有设置将会有些默认的初始化设置 而在java中线程组则是使用类ThreadG ...

  6. (转)利用CAS算法实现通用线程安全状态机

    在多线程环境下,如果某个类是有状态的,那我们在使用前,需要保证所有该类的实例对象状态一致,否则会出现意向不到的bug.下面是通用线程安全状态机的实现方法. public class ThreadSav ...

  7. ThreadPoolExecutor线程池的分析和使用

    1. 引言 合理利用线程池能够带来三个好处. 第一:降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗. 第二:提高响应速度.当任务到达时,任务可以不需要等到线程创建就能立即执行. 第 ...

  8. Linux 线程实现机制分析 Linux 线程模型的比较:LinuxThreads 和 NPTL

    Linux 线程实现机制分析 Linux 线程实现机制分析  Linux 线程模型的比较:LinuxThreads 和 NPTL http://www.ibm.com/developerworks/c ...

  9. 聊聊并发(三)Java线程池的分析和使用

    1.    引言 合理利用线程池能够带来三个好处.第一:降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗.第二:提高响应速度.当任务到达时,任务可以不需要的等到线程创建就能立即执行. ...

随机推荐

  1. Nginx 服务器伪静态配置不当造成 Access denied

    Nginx 服务器伪静态配置不当造成 Access denied 有群有反馈将 FastAdmin 布署到阿里云后无法打开后台. 出现如下提示,首页是可以打开,点登录链接后出现的.(下是群友的截图) ...

  2. Jquery中的has、find、filter方法区别

    find方法 find返回的是匹配结果集,作用于后代$(‘li’).find(‘.a’).css(‘background-color’, ‘red’);在li下面查找元素是否有class=a的元素,返 ...

  3. hdu 5909 Tree Cutting——点分治(树形DP转为序列DP)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5909 点分治的话,每次要做一次树形DP:但时间应该是 siz*m2 的.可以用 FWT 变成 siz*ml ...

  4. kettle环境变量的设置和获取

    1. 变量的类型Kettle 的早期版本中的变量只有系统环境变量目前版本中(3.1) 变量包括系统环境变量, "Kettle变量" 和内部变量三种 系统环境变量的影响范围很广,凡是 ...

  5. 智能家居入门DIY——【七、添加一个LCD12864吧】

    今天加了一个LCD12864,IC看说明上是ST7567,结果一顿U8g2,发现两个问题: 1.买的时候不知道是卖家写的我理解错了还是怎么了,反正是不出汉字的. 2.U8g2太大了…………占了uno的 ...

  6. 2018 Multi-University Training Contest 6-oval-and-rectangle(hdu 6362)-题解

    一.题意 求椭圆内接矩形周长的期望. 二.推导过程 已知$c$,容易得出矩形弦长$d=4a\sqrt{1-\frac{c^2}{b^2}}$ 接下来,矩形周长$p=4c+d=4c+4a\sqrt{1- ...

  7. C++中的STL中map用法详解(转)

    原文地址: https://www.cnblogs.com/fnlingnzb-learner/p/5833051.html C++中的STL中map用法详解   Map是STL的一个关联容器,它提供 ...

  8. 关于oracle数据库启动报ORA-01122,ORA-01110,ORA-01203错误的解决方法

    ORACLE 数据库空间裸设备出问题了,启动oracle失败,解决方法问题现象:     启动ORACLE的时候报如下的错误:        Database mounted.      ORA-01 ...

  9. django rest_framework 框架的使用

    django 的中间件 csrf Require a present and correct csrfmiddlewaretoken for POST requests that have a CSR ...

  10. React性能优化 PureComponent

    为什么使用? React15.3中新加了一个 PureComponent 类,顾名思义, pure 是纯的意思, PureComponent 也就是纯组件,取代其前身 PureRenderMixin  ...