brpc源码解析(一)—— rpc服务添加以及服务器启动主要过程
目录
- 1.往Server里添加Service(业务代码)
- 2.设置服务器参数
- 3.启动服务器
平时的工作用到了baidu-rpc搭建rpc服务,作为戈君大神的大作,在没有开源的时候,这个c++ 的rpc框架在厂内就已经好评颇多,无论是性能、文档、还是代码注释都很优秀,内部使用范围特别广,17年开源,开源版本叫做brpc,开源后不少大厂都有使用,目前已经进入Apache孵化器,源码以及文档的地址如下:https://github.com/apache/incubator-brpc。
个人对底层的东西比较感兴趣,因此有结合文档和源码深入学习下这个rpc框架的想法,整个brpc代码量不小,很早就开始看了,实话说一开始看其实挺费劲的,不过越往后看越觉得这个框架的博大精深,所以准备把看过的部分总结成文章,今天整理了一部分先发第一篇,算是看源码的随笔吧,第一次写博客,如有错误,还望指正。
brpc作为一个完整的rpc框架,自然同时支持作为Server和作为Client,这篇文章聊的是作为Server的使用方式以及启动Server、开启相应服务的内部处理过程。bprc面向用户的接口还是挺友好的,调用很简单,这里贴一个官方http的demo:
搭建一个rpc Server,概括起来就是新建一个Server对象,设置好参数,往里面添加自己的Service,然后启动,Server可以包含多个Service,而Service又可以包含多个method,具体的某次请求就是针对某个method的,这个demo里的Server有三个Service。
具体怎么使用bprc这里不多说,官方文档有详细说明。因为是从业务使用开始接触这个框架的,所以我打算首先从和实际应用场景最接近的添加服务、启动服务器这块开始入手看源码。brpc里有个Server类,作为服务器的话均是通过这个类作为入口,从rpc服务器的构造过程来说,主要是如下三个过程:
1.往Server里添加Service(业务代码)
这里所说的Service,指的是继承自proto文件描述的Service的用户Service,brpc是基于protobuf的,protobuf不包含RPC的实现,但却有RPC的相关定义,比如Service,brpc就用到了这个,即便是用不到protobuf消息的http服务,服务接口也得定义在proto文件中,是为了确保所有的服务声明集中在proto文件中。
Addservice函数有多个重载,比如上面官方demo调用的第三个是基于restful mapping字符串的,如下:
各个不同的Addservice重载调用的都是AddServiceInternal这个内部具体实现。总的来说Addservice就是指定哪些服务去处理哪里来的请求。
参数有三个,protofuf Service类型的服务,是否是内部服务(brpc提供了监控之类的内部服务)的标识,以及添加的service的选项。
google::protobuf::Service是一个公共的基类,用户定义在proto文件里的Service会被预处理成继承自这个基类的一个类,用户需要继承这个类去写真正的业务代码(实现method对应的虚函数),框架层面上统一按父类google::protobuf::Service处理。AddServiceInternal就是把Service里的method拿出来映射到指定地址上,首先会调用InitializeOnce() 实现server的初始化(只会初始化一次,用pthread_once调用GlobalInitializeOrDieImpl,保证只执行一次),如下:
brpc是支持多协议的,而且是同一个端口,会有一个协议解析机制来保证相对高的效率,本身内置了各种协议,用户也可以很方便地自己新增协议支持,GlobalInitializeOrDieImpl函数里面,最重要的就是注册了包括http在内的各种各样的协议支持,简单来说就是指定了各协议的消息解析函数、server端用到的request处理函数、client端用到的response处理函数,比如request处理函数,以下图中http协议为例,ProcessHttpRequest就负责处理接收到的http request,这个函数里会处理request后交给用户自定义函数去处理。这里暂时不详细展开,后面的文章再详细说明。
2.设置服务器参数
brpc提供了丰富的参数设置,包括最大并发,是否开启ssl、关闭闲置连接时间等,具体的可以参考官方文档,这里不再赘述,主要是通过Serveroption类型指定参数和直接调用set_xxx来直接设置。
3.启动服务器
调用Start函数来启动服务器,和Addservice一样,start也有多种调用方式的重载,最终都是调用的StartInternal
在StartInternal函数里,首先是一些准备工作,根据option进行了一些设置,包括ssl设置以及是否创建tls数据、提前启动好需要的bthread(brpc用到的m:n线程库的线程,bthread也是bprc性能优异的关键之一,后面的文章再具体介绍)等。然后就是在指定的ip和端口范围(在范围内不断尝试,成功了就停止继续尝试)上启动监听,一个server也只支持监听一个端口。主要代码如下:
Acceptor顾名思义就是消息的接收器,BuildAcceptor也就是构建接收器,如果为NULL则调用BuildAcceptor
在BuildAcceptor里面,最重要的如下:
首先通过ListProtocols拿到所有注册支持的协议,然后遍历这些协议,通过AddHandler添加,handler是处理message的,注意到这里handler.process都是protocols[i]里面的process_request,也就是对应协议在服务端使用用来处理过接收到的请求的,对应的如果是客户端用的则是process_response。
StartAccept核心内容如下:
brpc是采用epoll来处理事件的,用的是边缘触发,options.on_edge_triggered_events是epoll边缘触发事件到来后的处理函数,也就是OnNewConnections作为事件的处理函数,顾名思义也就是新连接到来后使用的处理函数,这里不展开讲OnNewConnections的具体实现,后面的文章再详细介绍。
关于Socket类型,就是对fd等资源的的封装方便再多线程环境下使用,官方介绍是这样的:
和fd相关的数据均在Socket中,是rpc最复杂的结构之一,这个结构的独特之处在于用64位的SocketId指代Socket对象以方便在多线程环境下使用fd。
Socket::Create函数是根据options新建socket并把id存入第二个参数中,内部最重要的操作就是用options.on_edge_triggered_event所指代的函数进行epoll add,在当前服务端start的场景下,也就是在监听fd上用OnNewConnections注册epoll事件处理新过来的连接,至此启动完成,后续等待epoll事件进行相应处理。
负责第一步处理epoll事件的则是EventDispatcher,是分发epoll event的模块,负责把fd上边缘触发的事件分发给消费者(具体的业务处理函数),可以有多个,分别运行在不同的bthread上,具体的数量取决于参数,它所做的事情就是启动后不断去epoll_wait,获得epoll事件后交由相应函数处理,如果是epoll_in事件,调用Socket::StartInputEvent,如果是epoll_out,调用Socket::HandleEpollOut,简化后的核心代码如下:
StartAccept后,服务器基本就启动完成了。再回到最开始的实例里,最后会调用server.RunUntilAskedToQuit()
RegisterQuitSignalOrDie里主要是用signal函数注册了退出信号,一旦有退出信号s_signal_quit会为true,从而跳出循环并停止server。
brpc作为服务端整个启动过程基本就是这样,后面再写文章继续介绍一下brpc里一些关键的机制和类,以及在fd上收发请求的一些细节。
brpc源码解析(一)—— rpc服务添加以及服务器启动主要过程相关推荐
- (Nacos源码解析五)Nacos服务事件变动源码解析
Nacos源码解析系列目录 Nacos 源码编译运行 (Nacos源码解析一)Nacos 注册实例源码解析 (Nacos源码解析二)Nacos 服务发现源码解析 (Nacos源码解析三)Nacos 心 ...
- Myth源码解析系列之五- 服务启动源码解析
通过前面几篇文章,我们搭建了环境,也进行了分布式事务服务的体验,相信大家对myth也有了一个大体直观的了解,接下来我们将正式步入源码解析之旅~~ order服务启动源码解析(myth-demo-spr ...
- Flink源码解析 | 从Example出发:理解Flink启动流程
从<Apache Flink本地部署>这篇文章中可以看到,我们启动集群都是通过脚本start-cluster.sh开始执行. 我们的源码解析之路就从flink的bash脚本入手. star ...
- brpc源码解析(二)—— brpc收到请求的处理过程
文章目录 一.基本设计思路 二.实现细节 三.总结 作为rpc服务器,在启动过后,最主要的一个过程就是收到请求后的处理,而这就牵涉到一个网络编程相关最基本的部分:如何有效地处理socket传过来地数据 ...
- brpc源码解析(四)—— Bthread机制
目录 一.概述 二.启动入口函数 三.内部启动函数 四.worker工作入口 五.总结 Bthread是brpc用到的一个线程库,也是brpc的核心之一,默认情况下,包括用户代码在内的绝大部分代码都是 ...
- brpc源码解析(七)—— worker基于ParkingLot的bthread调度
前面已经介绍过了bthread的主要机制,但对于具体的调度细节没有过多涉及,本篇将在着重介绍下bhtread在各个worker(taskgroup)之间的调度方式. 在brpc里,有个和调度相关的重要 ...
- dubbo源码解析(二)
大家好,我是烤鸭: dubbo 源码解析: 1.服务导出 介绍: Dubbo 服务导出过程始于 Spring 容器发布刷新事件,Dubbo 在接收到事件后,会立即执行服务导出逻辑.整个逻辑大致可分为三 ...
- Dubbo 实现原理与源码解析系列 —— 精品合集
摘要: 原创出处 http://www.iocoder.cn/Dubbo/good-collection/ 「芋道源码」欢迎转载,保留摘要,谢谢! 1.[芋艿]精尽 Dubbo 原理与源码专栏 2.[ ...
- Spring源码解析:自定义标签的解析过程
2019独角兽企业重金招聘Python工程师标准>>> spring version : 4.3.x Spring 中的标签分为默认标签和自定义标签两类,上一篇我们探究了默认标签的解 ...
最新文章
- How to attack a windows domain
- Windows系统调用学习笔记(三)—— 保存现场
- SOP,TSSOP,PLCC,BGA这些封装的中英文解释
- CSDN博客文章阅读模式插件(附源码)
- 获取指定存储过程的参数定义
- 多元统计分析matlab,matlab与应用多元统计分析..doc
- UE编辑器中的快捷键(一)
- 企业使用邮箱的重要性
- CSP 201903-2 二十四点 python (python有如神助)
- Effective Java 2.0_中英文对照_Item 6
- SDN南向接口和北向接口
- Mac安装clion教程
- android移动日记代码,Android开源项目-小熊日记源码
- 设计模式之代理模式(第二篇)
- 单片机开发不可避免会遇到很多头疼的问题
- 手机上最简单的计算机,怎么把手机文件传到电脑,才最简单又快速?
- 用批处理删除N天前或指定日期时间(前后)创建(或修改)的文件
- Artemis集群(18)
- 04 数据控制语言DCL
- unity网络实战开发(丛林战争)-前期知识准备(012-UI框架开发)
热门文章
- MIT博士研发绘画机器人Utensil,精通绘画和激光切割
- ElasticSearch的安装以及与springboot的集成
- ROMP:Monocular, One-stage, Regression of Multiple 3D People
- 【松岩论道】一个道理说明股市人的发展不是靠江湖式的随机跳跃分析!
- laravel tcg/voyager 安装问题记录
- TCP/IP前端面试
- 5个超经典实验,老杨带你高效进阶OSPF
- 【安全狗高危安全通告】OpenSSL存在远程代码执行漏洞和拒绝服务漏洞
- 不安分的管家——Jenkins
- 生成带有红黄绿码的二维码,并转base64