添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

平时的工作用到了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上收发请求的一些细节。

目录1.往server里添加Service(业务代码)2.设置服务器参数3.启动服务器平时的工作用到了baidu-rpc搭建rpc服务,作为戈君大神的大作,在没有开源的时候,这个c++ 的rpc框架在厂内就已经好评颇多,无论是性能、文档、还是代码注释都很优秀,内部使用范围特别广,17年开源,开源版本叫做brpc,开源后不少大厂都有使用,目前已经进入Apache孵化器,源码以及文档的地址如下:ht...
一.项目简介: b rpc 又称为 baidu - rpc ,是百度开发一款“远程 过程 调用”网络框架。目前该项目已在github上开源——https://github.com/b rpc /b rpc 。 据目前公开的资料,我们发现百度内部从2010年开始,开发过若干 rpc 框架:ub系列 rpc (ub rpc ,nova_pb rpc 、public_pb rpc ),hulu-pb rpc 、sofa-pb rpc 和本文介绍的 baidu - rpc 。从命名来看,我们并不太清楚ub、hulu和sofa是啥,但是可以确认的是我们...
在上一家公司工作的时候,涉及过 RPC 的开发,但仅仅是协作方制定好接口文档,我按照对应的格式去返回数据,对于 RPC 的概念、功能、实现以及各种版本框架的差异几乎没有了解。随着对进程间通信探究的不断深入,对深入了解 RPC 的渴望也愈加浓烈。本文开始,我将对大名鼎鼎的BPRC展开一系列的学习。 首先,我将简要的描述一下我对 RPC 的理解, RPC ,全称Remote Procedure Call,中文是“远程 过程 调用”,想要了解一个陌生的东西,可以先了解一下它的由来——即在什么背景下产生了这个东西,否则就 《Spark2.1.0之内置 RPC 框架》 《spark2.1.0之 源码 分析—— RPC 配置TransportConf》 《spark2.1.0之 源码 分析—— RPC 客户端工厂TransportClientFactory》        TransportServer是 RPC 框架的 服务端 ,可提供高效的、低级别的流 服务 。在说明《Spark2.1.0之内置 RPC 框架》一文... 《Spark2.1.0之内置 RPC 框架》 《spark2.1.0之 源码 分析—— RPC 配置TransportConf》 《spark2.1.0之 源码 分析—— RPC 客户端工厂TransportClientFactory》 《spark2.1.0之 源码 分析—— RPC 服务器 TransportServer》 《spark2.1.0之 源码 分析—— RPC 管道初始化》
使用的工业级 RPC 框架,具有1,000,000多个实例(不计算客户端)和数千种 服务 ,在百度内部称为“ baidu - rpc ”。 现在只有C ++实现是开源的。 您可以使用它来: 构建可以使用多种协议(在同一端口上)进行对话或访问各种 服务 服务器 宁静的http / https,h2 / h2c(与兼容,将开源)。 在b rpc 中使用http比更友好。 和 ,线程安全,比官方客户端更友好和性能更高。 / / ,用于构建。 hadoop_ rpc (可能是开源的) 支持(将开源) 支持,线程安全,比正式客户更友好,性能更高。 百度使用的各种协议: , streaming_ rpc ,hulu_pb rpc , sofa_pb rpc ,nova_pb rpc ,public_pb rpc ,ub rpc 和基于nshead的协议。 使用HTTP + json访问基于协议的协议,可能是另一种语言
b rpc 数据包处理 过程 前面我们提到b rpc 会在Server::Start中将listened_fd加入众多EventDispatcher之一,让epoll监听其EPOLLIN事件,我们将从listened_fd的可读事件触发来讲解一个数据包如何被接收 + 处理 + 响应。 OnNewConnections 我们知道Socket::ProcessEvent会调用listened_fd的回调事件:s->_on_edge_triggered_events,此回调函数在Acceptor::StartAcc
2021SC@SDUSC B RPC 源码 分析(一) 项目综述 2021SC@SDUSC B RPC 源码 分析(一) 项目综述 目录2021SC@SDUSC B RPC 源码 分析(一) 项目综述一、B RPC 介绍1.1 RPC 概述1.2 B RPC 概述1.3 B RPC 可以做什么?二、编译2.1 编译前置知识2.2 **Ubuntu的依赖准备**2.3 使用config_b rpc .sh编译b rpc 三、项目分工 一、B RPC 介绍 1.1 RPC 概述 RPC 是远程 过程 调用(Remote Procedure Call)的缩写形式
文章目录一、成员变量二、构造函数和析构函数2.1 构造函数2.2 析构函数三、内部类3.1 tls锁及用户数据Wrapper3.1 读辅助类ScopedPtr3.3 修改所用的Functor四、内部调用函数4.1 直接读取函数4.2 Wrapper增删函数五、外部调用函数5.1 读函数5.2 写函数六、总结 在 服务端 开发中,我们经常会碰到需要热加载的情况,需要在不影响持续请求的情况下更新数据,双buffer是很常见的一种手段,具体概念这里不过多展开,相关资料很多,在b rpc 里,有一个叫DoublyBuffe
关于C++11原子操作相关的知识,着实有点晦涩难懂,但这又是看懂B rpc 源码 必备的知识点之一。在网上查找了很多前人关于这块的解读文章,不同文章之间的解读确有些许出入。本文仅对自己了解和认可的部分做解释和梳理,形成自己的理解。日后发现有错误不足的地方,再做修正补充。 一. 原子性,可见性,内存序的区分 我们以一个最简单的语句x.store(1, memory_order_relaxed);为例,这条...
RPC (Remote Procedure Call)远程 过程 调用,是一种通过网络从远程计算机程序上请求 服务 ,而不需要了解底层网络技术的协议。 RPC 服务器 是提供远程 过程 调用 服务 服务器 ,主站是指 主要 服务器 或者 主要 的站点。在 启动 中, RPC 服务器 是指正在 启动 或者已经 启动 的提供远程 过程 调用 服务 服务器 。下面是主站和 RPC 服务器 启动 的步骤: 1. 启动 主站 ```shell # 启动 httpd 服务 [root@leqingserver ~]# systemctl start httpd 2. 启动 RPC 服务器 ```shell # 启动 CM RPC 服务 [root@leqingserver ~]# systemctl start cm rpc