brpc源码学习(六)- brpc server 端整体流程

article/2025/8/29 19:54:15

brpc的使用比较容易上手,以官方demo为例,因为brpc的数据序列化依赖protobuf,所以首先需要定义个proto

然后继承EchoService并实现Echo方法

然后是整体流程

启动还是比较简单的,定义server,AddService,然后Start即可

首先放一张官网的图,陷入细节前先有个大概印象

然后看下AddService

然后是AddServiceInternal

首先判断注册的service中是否有method,如果没有则直接返回;然后调用InitializeOnce()只进行一次初始化,该函数实际调用的是GlobalInitializeOrDieImpl

在GlobalInitializeOrDieImpl内首先忽略掉SIGPIPE,然后初始化SSL,注册NamingService,LoadBalancer,CompressHandler;然后开始注册协议,brpc server一个端口支持多种协议,这里的协议都是指的是应用层协议,如baidu_std协议是基于tcp,以注册baidu_std协议为例

协议Protocol类是一个包含了多个函数指针的结构体,例如:

Parse负责将消息从source上切割下来,client和server均会使用。

ProcessRequest处理serverparse返回的消息,只有server端会调用。

注册完协议之后,遍历协议,将含有process_response的协议加入到clientInputMessengerhandler中。

然后回来到AddServiceInternal,接着判断当前注册的service是否注册过,没注册的话则注册service的所有method

然后在demo中使用默认的ServerOption调用server.Start(),首先还是调用InitializeOnce,这里会直接返回。然后中间的逻辑在默认的option不会调用,直接到初始化bthread

然后从min_port开始遍历到max_port直到找到一个可用的port,然后创建Acceptor

AcceptorInputMessenger的子类,主要的工作就是处理指定的port来的消息,然后看下BuildAcceptor,遍历所有的协议,如果协议指定了process_request,那么就加到acceptorhandler

然后调用acceptorStartAccept,核心代码如下,初始化SocketOptions,设置fd为监听的端口,user为当前acceptoron_edge_triggered_eventsOnNewConnectionsOnNewConnections是一个函数指针,表示当前fd发生事件后的回调函数

然后调用SocketCreate,摘一段官网介绍:

和fd相关的数据均在Socket中,是rpc最复杂的结构之一,这个结构的独特之处在于用64位的SocketId指代Socket对象以方便在多线程环境下使用fd

这里主要逻辑就是根据SocketOption去初始化Socket,然后ResetFileDescriptor

这里其实还是对socket的初始化工作

因为brpc使用的是epoll的边缘触发,所以将fd设置为非阻塞,然后设置socketsendrecv buffer大小,然后将当前fd加入到event_dispatcher

GetGlobalEventDispatcher中,会只进行一次初始化dispatcher的工作,会创建FLAGS_event_dispatcher_numdispatcher,默认为1,构造函数中会创建epoll fd,然后调用Start

Start中会启动一个bthread,执行RunThisRunThis会执行dispatcherRun

Run中就是循环进行epoll_wait

然后对判断事件,如果是EPOLLIN事件,那么执行StartInputEvent,如果是EPOLLOUT,则执行HandleEpollOut

到现在为止,dispatcherStart就执行结束了,然后回到SocketResetFileDescriptor,会执行AddConsumer,将socket_id存到epoll_eventdata中,然后注册EPOLLIN事件,到这里,server端初始化过程就完成了,接下来就坐等请求到来。

 

然后回到epoll_wait,当有新请求到来时,epoll_wait返回,遍历每一个事件,执行Socket::StartInputEvent;注册epoll事件时将socketid注册在了epoll_datau64中,所以首先通过SocketId addressSocket,为了保证一个fd上只有一个bthread在处理,这里引入了一个atomic变量_nevent,通过_nevent判断当前socket是否有bthread正在处理,如果有的话就什么都不做,因为正在处理的线程执行完后会执行新事件,如果没有的话就使用bthread_start_urgent启动一个bthread执行ProcessEvent来处理新消息,此时epoll bthread让出当前worker的处理,worker执行新建的ProcessEvent bthread,而epoll bthread则被steal到另一个worker线程执行。这里就是官网中所说,brpc不区分io线程和worker线程,epoll bthread不负责数据的读取,IO线程的问题在于一个线程同时只能读一个fd,当多个繁忙的fd聚集在一个IO线程中时,一些读取就被延迟了;另外epoll bthread让出当前workerProcessEvent bthread,这样使其有更好的cache locality,可以尽快地读取fd上的数据。

ProcessEvent则是调用on_edge_triggered_events,在Socket Create的时候将该回调函数设置为了OnNewConnections

这里会通过MoreReadEvents循环判断当前fd上是否还有新的事件,然后执行OnNewConnectionsUntilEAGAIN,这里判断是否有新事件的方法就是上文提到的_nevent

OnNewConnectionsUntilEAGAIN中,首先通过accept拿到一个已完成的连接,然后从监听socket中获取user,即之前的acceptor,然后创建Socket,回调函数设置为OnNewMessages,接下来的过程和之前创建监听Socket过程一样,执行AddConsumer,将socket_id存到epoll_eventdata中,注册EPOLLIN事件,然后这个新连接有数据来了之后会在epoll_wait返回,执行ProcessEvent,调用到OnNewMessages

再粘一个官网的介绍:

InputMessenger负责从fd上切割和处理消息,它通过用户回调函数理解不同的格式。Parse一般是把消息从二进制流上切割下来,运行时间较固定;Process则是进一步解析消息(比如反序列化为protobuf)后调用用户回调,时间不确定。若一次从某个fd读取出n个消息(n > 1)InputMessenger会启动n-1bthread分别处理前n-1个消息,最后一个消息则会在原地被ProcessInputMessenger会逐一尝试多种协议,由于一个连接上往往只有一种消息格式,InputMessenger会记录下上次的选择,而避免每次都重复尝试。

可以看到,fd间和fd内的消息都会在brpc中获得并发,这使brpc非常擅长大消息的读取,在高负载时仍能及时处理不同来源的消息,减少长尾的存在。

这里的handler就是一开始初始化注册的所有server端协议。进入while循环,计算一次读取数据的长度,DoRead会执行_read_buf.append_from_file_descriptor_read_bufIOPortal类型,如上篇博客所讲,这个方法会调用readvfd中的数据读入到iobufblock中。

因为这一次数据读取可能会包含多个消息,因此下面会有另一个while循环,每次调用CutInputMessage尝试从iobuf中切割一条消息,如上文,server端是支持多协议的,所以这里第一次会尝试使用所有的协议进行一次parse,因为大多数情况下一个连接上只有一种协议,因此尝试一遍之后会记录下来执行成功的协议,之后将首先尝试记录的协议。

这里的parse就是上文提到的注册协议中的parse方法,这里以协议baidu_std为例简单介绍一下,baidu_std官方介绍在这里https://github.com/apache/incubator-brpc/blob/master/docs/cn/baidu_std.md,可以看到判断是否是baidu_std的方法就是判断前4 个字节是否为”prpc”,这里的copy_to为显式拷贝,因为在判断是否为baidu_std协议的过程中不能消费数据,否则可能会影响其他协议解析;如果iobuf中的数据不够4个字节且是”prpc”的前缀,那么返回PARSE_ERROR_NOT_ENOUGH_DATA错误,这个表示到目前为止不违反当前协议,但是数据不足一个消息,因此会触发重新DoRead的过程;如果前4个字节就是”prpc”,那么满足baidu_std协议,接下来将解析包体长度和包体中的元数据包长度存入到body_sizemeta_size中,如果iobuf中数据长度不足body_size + 12(4 + 4 + 4),那么同样会触发重读,否则将iobuf中的meta和其他数据切割到msg中并返回,这里是零拷贝。

如果一次DoRead读入了n条消息,那么前n-1条消息会通过QueueMessage后台启动了n-1bthread进行处理,而最后一个消息会被析构函数RunLastMessage执行,原地执行process函数,即协议中的process

还是以baidu_std为例,首先是从iobuf中解析pb格式的meta

然后创建reqresController,然后进行流控,解析req,如果有attachment也解析出来,最后调用CallMethodCallMethod方法在编译protobuf时生成,会调用到用户定义的Echo方法

最后在Echodone_guard析构时会调用doneRun方法,发送responseclient

 


http://chatgpt.dhexx.cn/article/yofE8dW1.shtml

相关文章

brpc源码解析(一)—— rpc服务添加以及服务器启动主要过程

目录 1.往Server里添加Service(业务代码)2.设置服务器参数3.启动服务器 平时的工作用到了baidu-rpc搭建rpc服务,作为戈君大神的大作,在没有开源的时候,这个c 的rpc框架在厂内就已经好评颇多,无论是性能、文…

brpc初步学习

一.BRPC介绍 BRPC百度开源的一个rpc框架,它具有以下特性: 基于protobuf接口的RPC框架,也提供json等其他数据格式的支持囊括baidu内部所有RPC协议,支持多种第三方协议模块化设计,层次清晰,很容易添加自定义…

brpc介绍、编译与使用

brpc又称为baidu-rpc,是百度开发一款“远程过程调用”网络框架。目前该项目已在github上开源——https://github.com/brpc/brpc。(转载请指明出于breaksoftware的csdn博客) 据目前公开的资料,我们发现百度内部从2010年开始&#x…

NB-IOT与物联网

1. 物联网的技术格局 短距离(智能家居/穿戴等) --- zigbee, wifi, BLE 长距离 (LPWA 低功耗广域) --- LORA, NB-IOT 关于LORA大致了解了一下情况 . Lora 其实已经是一个很成熟的技术方案. 国外已经大范围使用,国内也有不少公司在基于LORA运营物联网系统. LORA的系统结构…

lora和nbiot的相同点,它们之间有何区别和联系?

在物联网无线数据传输中,有诸多方式可以选择,包括蓝牙、WIFI、FSK、ASK/OOK、Lora、Zigbee、NB-iot、Z-Wave.等, 其中lora 和NBIot 是自2016年来比较热门的两个无线通讯方式。 我们今天就和大家简单的聊聊Lora 和NBiot。 我是在2016年接触…

NB-IOT开发|nbiot开发教程《三》AT指令类模组驱动-STM32实现AT指令状态机

嵌入式开发中我们要时刻保持代码的高效与整洁看之前,先点赞 好习惯,要养成 一、前言 嵌入式开发中我们要时刻保持代码的高效与整洁。在第一节中“NB-IOT开发|nbiot开发教程《一》AT指令类模组驱动解析”我们说到AT指令模组最好的驱动-状态机。本节我们就…

基于华为云IOT平台实现多节点温度采集(STM32+NBIOT)

一、前言 当前的场景是,在高速公路上部署温度采集设备,在高速路地表安装温度检测传感器,检测当前路段的路面实际温度。一段高速路上有多个地点需要采集温度数据。 采集温度数据需要上传到云平台进行数据存储,并且通过可视化界面展示温度变化曲线,支持查询最近几天的温度信…

NB-IoT的优势是什么?

NB-IoT的优势 : • 强链接:在同一基站的情况下,NB-IoT可以比现有无线技术提供50-100倍的接入数。一个扇区能够支持10万个连接,支持低延时敏感度、超低的设备成本、低设备功耗和优化的网络架构。举例来说,受限于带宽&a…

MN316_OPEN(NBIOT)物联网模块环境搭建

因为项目的需要,这里要使用NBIOT,踩了一些坑,这里总结一下! 编译 官方给的SDK如下: 按照说明,在该目录下直接运行如下指令:".\build.bat dlvs_h0 demo"即可成功编译,但是我编译的时候不成功,报错如下: 最后发现是因为我的目录太深的原因造成的,把"MN316_Op…

stm32毕业设计 NBIOT远程通信系统

文章目录 1 简介2 NBIOT 简介2.1 NBIOT 的特点2.2 NBIOT 的优点2.3 NBIOT能做什么 NBIOT 模块使用4 实现效果5 STM32 驱动NBIOT模块6 最后 1 简介 Hi,大家好,NBIOT是近几年不比较火的远程通信模块,是物联网的重要技术,今天学长向…

NB-IoT技术实战开发 ----- NB-IoT介绍

一.1------初识NB-IoT 1、NB-IoT介绍2、 物联网技术发展2.1有线物联网2.2 无线网络网 3、为什么需要NB-IOT4、NB-IOT优势5、NB-IOT解决方案亮点和价值5.1 广覆盖5.2 低功耗5.3低成本5.4 大连接 6、NB-IOT的应用1.智能抄表2.智能停车3.宠物跟踪4.else 1、NB-IoT介绍 NB-----Na…

【物联网】LoRa vs NBIoT

LoRa (Long Range) VS NB-IoT(Narrow Band Internet of Things) LoRa和NB-IoT是什么 通常物联网设备分为三类: 无需移动性,大数据量,需较宽频段;移动性强&#xff0…

物联网协议之NBIOT

什么是NBIOT 在物联网行业目前常用的网络通信技术主要有以下这些: nbiot属于一种LTE网络,LTE网络是目前主流的通信网络,覆盖完整、技术成熟,未来大量物联网设备都需要在LTE网络中实现通讯功能。Cat.X这个值是用来衡量用户终端设…

浅谈NBIOT

一、什么是NBIOT? 1、概念 窄带物联网(Narrow Band Internet of Things, NB-IoT),NB-IoT构建于蜂窝网络,只消耗大约180KHz的带宽,使用License频段,可采取带内、保护带或独立载波等三种部署方式…

【物联网毕设基础】NBIOT 窄带物联网

文章目录 1 简介2 NBIOT简介3NB的型号介绍3.1 BC95:3.2 BC35:3.3 BC28:3.4 BC26:3.5 BC20:3.6 BC30: 4 NB物联网卡5 OpenCPU6 BC260模块详解6.1 基本性能6.2 引脚介绍6.3 模块供电 7 其他注意点8 最后 1 简介 Hi&…

NB-IoT学习笔记 —— NB-IoT介绍

一、简介 NB-IoT 是指窄带物联网(Narrow Band Internet of Things)技术,是一种低功耗广域(LPWA)网络技术标准,基于蜂窝技术,用于连接使用无线蜂窝网络的各种智能传感器和设备,聚焦于…

淘宝客解析url优惠链接获取商品ID

淘宝客解析商品链接获取PID 优惠链接都有一个e参数,提取e参数,直接解析e参数就可以获取推广链接的商品ID; 这是一个优惠推广链接:https://uland.taobao.com/coupon/edetail?ed4tkoUeRofIN%2BoQUE6FNzDiOaI9VHkxMoEVLjjyR2S%2Bki3b8ti%2Bp7j…

ANSI/CAN/UL 1973:2022 固定和运动辅助电源用电池安规要求-最新的英文2022完整版{135页}

ANSI/CAN/UL 1973:2022 Batteries for Use in Stationary andMotive Auxiliary Power Applications 固定和运动辅助电源用电池 UL1973-2022(February25,2022).pdf-其它文档类资源-CSDN下载UL1973-2022(February25,2022).pdf更多下…

java测试示例-生成ULID

ULID全称Universally Unique Lexicographically Sortable Identifier,直译就是通用唯一按字典排序的标识符,原始仓库是https://github.com/ulid/javascript,由前端开发者alizain发起,基于JavaScript语言。从项目中的commit历史来看…

scrapy_splash简单爬取淘宝页面信息

首先打开淘宝页面,搜索手机: https://uland.taobao.com/sem/tbsearch?refpidmm_26632258_3504122_32538762&clk104511dd93dde330d86022e9ce3a3dc46&keyword手机&page0 # 新建scrapy项目 scrapy startproject taobao # 进入项目目录: cd t…