菜鸟笔记
提升您的技术认知

brpc 笔记

bthread(一) 前言bthread(二) 线程模型及bthreadbthread(三) bthread数据结构bthread(四) bthread用户接口和代码执行路径bthread(五) 无锁队列rq的代码实现bthread(六) 小结brpc的精华bthread源码剖析brpc介绍、编译与使用brpc源码解析(一)—— rpc服务添加以及服务器启动主要过程brpc源码解析(二)—— brpc收到请求的处理过程brpc源码解析(三)—— 请求其他服务器以及往socket写数据的机制brpc源码解析(四)—— Bthread机制brpc源码解析(五)—— 基础类resource pool详解brpc源码解析(六)—— 基础类socket详解brpc源码解析(七)—— worker基于ParkingLot的bthread调度brpc源码解析(八)—— 基础类EventDispatcher详解brpc源码解析(九)—— 基础类WorkStealingQueue详解brpc源码解析(十)—— 核心组件bvar详解(1)简介和整体架构brpc源码解析(十一)—— Reducer类和Adder类解析brpc源码解析(十二)—— 核心组件bvar详解 AgentGroup类详解brpc源码解析(十三)—— 核心组件bvar详解(4)combiner详解brpc源码解析(十四)—— 核心组件bvar详解 sampler详解brpc源码解析(十五)—— bthread栈创建和切换详解brpc源码解析(十六)—— 作为client的连接建立和处理详解brpc源码解析(十七)—— bthread上的类futex同步组件butex详解brpc源码解析(十八)—— MPSC队列ExecutionQueue详解brpc源码解析(十九)—— 双buffer数据结构DoublyBufferedData详解brpc源码解析(二十)—— 用于访问下游的Channel类详解

brpc源码解析(八)—— 基础类EventDispatcher详解

阅读 : 566

前阵子比较忙,好久没有更新了,后续争取恢复更新频率,这次先更一篇相对简单的,介绍下EventDispatcher类,前面的文章涉及过这个概念, EventDispatcher,顾名思义,就是用来分发事件的,在brpc里面,因为是不区分io线程和用户线程的,这个EventDispatcher,也仅仅是用来做事件分发,不负责具体的数据读取写入,所以本身的吞吐量可以很大。这个类很重要,但是本身比较简单,下面介绍下核心函数和类变量。

1.启动相关函数

(1)void Run()
核心功能函数,调用epoll_wait等待事件并分别调用函数处理,epoll_in事件来后调用Socket:: StartInputEvent,epoll_out事件来后调用Socket::HandleEpollOut,Socket:: StartInputEvent和Socket::HandleEpollOut则是分别去执行对应socket里相应的用户处理函数。核心代码如下:

(2)static void* RunThis(void* arg);
封装了Run,用于在bthread里启动调用Run。

(3)virtual int Start(const bthread_attr_t* consumer_thread_attr);
新建bthread以RunThis为入口启动当前EventDispatcher,开始监听epoll事件并分发。

2.添加epoll_in事件函数

int AddConsumer(SocketId socket_id, int fd)
在fd上添加epoll_in事件(可读事件)进行监听,参数socket_id会保存到添加的事件里,后面事件发生了需要根据这个socket_id address实际的socket,拿到里面的_on_edge_triggered_events等进行实际的处理,总结来说就是调用这个函数来添加需要用socket_id对应的socket来处理的发生在fd上的边缘触发epoll_in事件。事件来后直接调用的是Socket:: StartInputEvent。

3.添加epoll_out事件函数

AddEpollOut(SocketId socket_id, int fd, bool pollin)
添加监听epoll_out事件(可写事件),和添加epollin的方式类似,epoll_out事件,多了一个pollin参数,如果为true会同时监听epoll_in,事件来后直接调用的是Socket::HandleEpollOut,比如以前的文章提到过,brpc里在往某个socket里写数据的情况下,如果还没连接则发起连接并用“继续写入的函数”作为回调注册epollout后直接返回,让回调完成后续的写操作。

4.获取EventDispatcher函数

Brpc支持多个EventDispatcher,具体EventDispatcher数量由参数决定,默认数量是1,每个EventDispatcher负责一部分fd的监听处理。
各个fd都是调用GetGlobalEventDispatcher来获得对应的EventDispatcher,这个函数就在event_dispatcher.cpp里,EventDispatcher类外brpc namespace下的一个函数,如下:

如果没初始化会先初始化并运行,InitializeGlobalDispatchers是具体的初始化函数,由pthread_once保证只执行一次。这里是基于MurmurHash3将fd均匀分配到各EventDispatcher。InitializeGlobalDispatchers函数如下:

5.核心类变量

(1)int _epfd:监听事件的epfd
(2)bthread_t _tid:EventDispatcher当前所在的bthread的id
(3)bthread_attr_t _consumer_thread_attr:epoll_in或者epoll_out事件到来后新建bthread执行用户回调函数所要用到的线程属性