Commit 75d371e7 authored by gejun's avatar gejun

Update overview.md

parent 9a584063
......@@ -23,20 +23,12 @@
RPC框架作为最基本的网络通讯组件,需要具备优秀的稳定性、可维护性和扩展性。在开发本框架前,公司内外主要有如下RPC实现:
- UB
:com组(INF前身)在08年开发的RPC框架,目前仍广泛使用,经历了大量的线上考验,稳定性优秀。UB的主要问题是依赖众多、扩展性不佳,以及缺乏调试工具。用户往往只需要UB中的一部分功能而不得不依赖大量模块,由于百度的代码库不是单根,这带来了复杂的依赖打平问题。UB每个请求都要独占一个连接,在大规模服务中每台机器都需要保持大量的连接,限制了其使用场景(比如INF自己的分布式系统都不用UB)。UB只支持nshead+mcpack协议,也没有太多考虑扩展接口,所以增加新协议和新功能往往要调整大段代码,在实践中大部分人都“知难而退”了。UB也缺乏调试和运维接口,服务的运行状态对用户基本是黑盒,只能靠低效的打日志来追踪问题,产品线服务出现问题时总是要拉上UB的维护同学一起排查,效率很低。UB有多个变种:
- UB: com组(INF前身)在08年开发的RPC框架,目前仍广泛使用,经历了大量的线上考验,稳定性优秀。UB的主要问题是依赖众多、扩展性不佳,以及缺乏调试工具。用户往往只需要UB中的一部分功能而不得不依赖大量模块,由于百度的代码库不是单根,这带来了复杂的依赖打平问题。UB每个请求都要独占一个连接,在大规模服务中每台机器都需要保持大量的连接,限制了其使用场景(比如INF自己的分布式系统都不用UB)。UB只支持nshead+mcpack协议,也没有太多考虑扩展接口,所以增加新协议和新功能往往要调整大段代码,在实践中大部分人都“知难而退”了。UB也缺乏调试和运维接口,服务的运行状态对用户基本是黑盒,只能靠低效的打日志来追踪问题,产品线服务出现问题时总是要拉上UB的维护同学一起排查,效率很低。UB有多个变种:
- ubrpc:INF在10年基于UB开发的RPC框架,用idl文件描述数据的schema,而不是在代码中手动打包。这个RPC有被使用,但不广泛。
- [nova-pbrpc](http://websvn.work.baidu.com/repos/app_ecom_nova/list/trunk/public/pb-rpc):网盟在12年基于UB开发的RPC框架,用protobuf代替mcpack作为序列化方法,协议是nshead
+ user's protobuf。
- [public/pbrpc](http://websvn.work.baidu.com/repos/public/list/trunk/pbrpc):INF在13年初基于UB开发的RPC框架,用protobuf代替mcpack作为序列化方法,但协议与nova-pbrpc不同,大致是nshead
+ meta protobuf。meta protobuf中有个string字段包含user's
protobuf。由于用户数据要序列化两次,这个RPC的性能很差,基本没有被推广开。
- [nova-pbrpc](http://websvn.work.baidu.com/repos/app_ecom_nova/list/trunk/public/pb-rpc):网盟在12年基于UB开发的RPC框架,用protobuf代替mcpack作为序列化方法,协议是nshead + user's protobuf。
- [public/pbrpc](http://websvn.work.baidu.com/repos/public/list/trunk/pbrpc):INF在13年初基于UB开发的RPC框架,用protobuf代替mcpack作为序列化方法,但协议与nova-pbrpc不同,大致是nshead + meta protobuf。meta protobuf中有个string字段包含user's protobuf。由于用户数据要序列化两次,这个RPC的性能很差,基本没有被推广开。
- [hulu-pbrpc](https://svn.baidu.com/public/trunk/hulu/pbrpc/):INF在13年基于saber(kylin变种)和protobuf实现的RPC框架。hulu尝试区分了机制(pbrpc)和策略(huluwa),减轻了依赖问题。但在实现上有较多问题:未封装的引用计数,混乱的生命周期,充斥的多线程问题(race
conditions & ABA
problems),运行质量很不可靠,比如hulu的短链接从来没有能正常运行过。其编程接口强依赖saber,很多功能的划分不够清晰,比如增加新协议就需要同时修改saber和pbrpc,扩展新功能仍然很困难。hulu增加了http协议的内置服务,可以提供一些简单的内部运行状态,但对于排查问题还比较简陋。hulu支持和一个server只保持一个连接,相比UB可以节省连接数,但由于多线程实现粗糙,读写不够并发,hulu的性能反而不如UB。
- [hulu-pbrpc](https://svn.baidu.com/public/trunk/hulu/pbrpc/):INF在13年基于saber(kylin变种)和protobuf实现的RPC框架。hulu尝试区分了机制(pbrpc)和策略(huluwa),减轻了依赖问题。但在实现上有较多问题:未封装的引用计数,混乱的生命周期,充斥的多线程问题(race conditions & ABA problems),运行质量很不可靠,比如hulu的短链接从来没有能正常运行过。其编程接口强依赖saber,很多功能的划分不够清晰,比如增加新协议就需要同时修改saber和pbrpc,扩展新功能仍然很困难。hulu增加了http协议的内置服务,可以提供一些简单的内部运行状态,但对于排查问题还比较简陋。hulu支持和一个server只保持一个连接,相比UB可以节省连接数,但由于多线程实现粗糙,读写不够并发,hulu的性能反而不如UB。
- [sofa-pbrpc](https://svn.baidu.com/public/trunk/sofa-pbrpc/):PS在13年基于boost::asio和protobuf实现的RPC框架,这个库代码工整,接口清晰,支持同步和异步,有非HTTP协议的调试接口(最新版也支持HTTP了)。但sofa-pbrpc也有产品线自研框架的鲜明特点:不支持公司内的其他协议,对名字服务、负载均衡、服务认证、连接方式等多样化的需求的抽象不够一般化。sofa-pbrpc还对外发布了开源版本。
......@@ -64,33 +56,26 @@ problems),运行质量很不可靠,比如hulu的短链接从来没有能正
RPC不是万能的抽象,否则我们也不需要TCP/IP这一层了。但是在我们绝大部分的网络交互中,RPC既能解决问题,又能隔离更底层的网络问题。对于RPC常见的质疑有:
- 我的数据非常大,用protobuf序列化太慢了。首先这可能是个伪命题,你得用[profiler](http://wiki.baidu.com/display/RPC/cpu+profiler)证明慢了才是真的慢,其次一些协议支持附件,你可以在传递protobuf请求时附带二进制数据。
- 我传输的是流数据,RPC表达不了。baidu-rpc支持[Streaming
RPC](http://wiki.baidu.com/pages/viewpage.action?pageId=152229270),这可以表达。
- 我传输的是流数据,RPC表达不了。baidu-rpc支持[Streaming RPC](http://wiki.baidu.com/pages/viewpage.action?pageId=152229270),这可以表达。
- 我的场景不需要回复。简单推理可知,你的场景中请求可丢可不丢,可处理也可不处理,因为client总是无法感知,你真的确认这是OK的?即使场景真的不需要,我们仍然建议用最小的结构体回复,因为这不大会是瓶颈,并且在出问题时让你有一些线索,否则真的是盲人摸象。
# 优势
### 使用更简单的接口
我们只有三个用户类:[Server](https://svn.baidu.com/public/trunk/baidu-rpc/src/baidu/rpc/server.h)[Channel](https://svn.baidu.com/public/trunk/baidu-rpc/src/baidu/rpc/channel.h?revision=HEAD)[Controller](https://svn.baidu.com/public/trunk/baidu-rpc/src/baidu/rpc/controller.h?revision=HEAD),分别对应server端,client端,和调整参数集合。你不需要推敲诸如“Client怎么初始化”,“XXXManager有什么用”,“Context和Controller的关系是什么“之类的问题,你要做的很简单:
我们只有三个用户类:[Server](http://icode.baidu.com/repo/baidu/opensource/baidu-rpc/files/master/blob/src/brpc/server.h)[Channel](http://icode.baidu.com/repo/baidu/opensource/baidu-rpc/files/master/blob/src/brpc/channel.h)[Controller](http://icode.baidu.com/repo/baidu/opensource/baidu-rpc/files/master/blob/src/brpc/controller.h),分别对应server端,client端,和调整参数集合。你不需要推敲诸如“Client怎么初始化”,“XXXManager有什么用”,“Context和Controller的关系是什么“之类的问题,你要做的很简单:
- 建服务就#include
<[baidu/rpc/server.h](https://svn.baidu.com/public/trunk/baidu-rpc/src/baidu/rpc/server.h)>,并按照注释或例子使用Server对象。
- 访问服务就#include
<[baidu/rpc/channel.h](https://svn.baidu.com/public/trunk/baidu-rpc/src/baidu/rpc/channel.h)>,并按照注释或例子使用Channel对象。
- 想控制一次RPC访问的参数,就看看[baidu/rpc/controller.h](https://svn.baidu.com/public/trunk/baidu-rpc/src/baidu/rpc/controller.h)中到底有些什么。请注意,这个类是Server和Channel共用的,其中分成了三段,分别标记为Client-side,
Server-side和Both-side methods。
- 建服务就包含baidu/rpc/server.h,并按照注释或例子使用Server对象。
- 访问服务就包含baidu/rpc/channel.h,并按照注释或例子使用Channel对象。
- 想控制一次RPC访问的参数,就看看baidu/rpc/controller.h中到底有些什么。请注意,这个类是Server和Channel共用的,其中分成了三段,分别标记为Client-side, Server-side和Both-side methods。
我们尝试让事情变得更加简单,以名字服务为例,在其他RPC实现中,你也许需要复制一长段晦涩的代码才可使用,而在baidu-rpc中访问BNS可以这么写"bns://node-name",
本地文件列表可以这么写"file:///home/work/server.list",相信不用我解释,你也能明白这些代表什么,这个字串可以放在配置文件中,方便地载入并使用。
我们尝试让事情变得更加简单,以名字服务为例,在其他RPC实现中,你也许需要复制一长段晦涩的代码才可使用,而在baidu-rpc中访问BNS可以这么写"bns://node-name",本地文件列表可以这么写"file:///home/work/server.list",相信不用我解释,你也能明白这些代表什么,这个字串可以放在配置文件中,方便地载入并使用。
### 访问各种服务,被各种服务访问
baidu-rpc能访问百度内所有基于protobuf的RPC server实现,能[访问ub
server](http://wiki.baidu.com/pages/viewpage.action?pageId=213828700)(idl/mcpack/compack)
baidu-rpc能访问百度内所有基于protobuf的RPC server实现,能[访问ub server](http://wiki.baidu.com/pages/viewpage.action?pageId=213828700)(idl/mcpack/compack)
baidu-rpc能被百度内所有基于protobuf的RPC
client访问,能被HTTP+json访问,通过一些额外代码可以被UB访问。
baidu-rpc能被百度内所有基于protobuf的RPC client访问,能被HTTP+json访问,通过一些额外代码可以被UB访问。
### 使服务更加可靠
......@@ -100,8 +85,7 @@ client访问,能被HTTP+json访问,通过一些额外代码可以被UB访问
- 完整的单元和集成测试:baidu-rpc有完整的单元测试,集成测试,系统测试和性能测试,在我们每次check
in代码后都会运行,这确保我们在开发阶段可以及时规避问题。
- 全面的调试和监控手段:baidu-rpc特别重视开发和运维,你可以使用浏览器或curl[查询服务器内部状态](http://wiki.baidu.com/display/RPC/Builtin+Services),你也可以用pprof[分析在线服务的性能](http://wiki.baidu.com/display/RPC/cpu+profiler)。你可以[用bvar计数](http://wiki.baidu.com/display/RPC/bvar),相比缓慢的ubmonitor几乎没有性能损耗,同时bvar能以/vars访问,这改变了我们监控在线服务的方式
- 新基础库:baidu-rpc依赖的[C++
base](http://wiki.baidu.com/pages/viewpage.action?pageId=38035224)改造自chromium,是百度的新基础库。
- 新基础库:baidu-rpc依赖的[C++ base](http://wiki.baidu.com/pages/viewpage.action?pageId=38035224)改造自chromium,是百度的新基础库。
### 获得更好的延时和吞吐
......@@ -109,7 +93,7 @@ client访问,能被HTTP+json访问,通过一些额外代码可以被UB访问
- **对不同客户端请求的读取和解析是完全并发的,用户也不用区分”IO线程“和”处理线程"**。听上去简单,但几乎没有做到的。大部分实现会区分“IO线程”和“处理线程”,并把[fd](http://en.wikipedia.org/wiki/File_descriptor)(对应一个客户端)散列到IO线程中去。这听上不错,实则很糟糕。首先当一个IO线程在读取其中的fd时,同一个线程中的fd都无法得到处理。有些实现(ubaserver)不扣除关闭的fd,那么在一段时间后,不同IO线程中的fd将很不均匀,一个fd的影响范围将更大。当一些解析变慢时,比如特别大的protobuf
message,同一个IO线程中的其他fd都遭殃了。虽然不同IO线程间的fd是并发的,但由于你不太可能开太多IO线程(这类线程的事情很少,大部分时候都是闲着的),10个就比较多了,所以一个fd能影响到的”其他fd“仍有相当大的比例(10个即10%,在线检索可是要求99.99%的)。将来的RPC框架将广泛地用于多租户(multi-tenacy)环境,一个数据复杂的业务如果严重干扰到其他业务的SLA,将是无法接受的。在baidu-rpc中,对不同fd的读取是完全并发的,对同一个fd中不同消息的解析也是并发的**。**比如一个特别大的protobuf
message在解析时不会影响同一个客户端的其他消息,更不用提其他客户端的消息了。
message在解析时不会影响同一个客户端的其他消息,更不用提其他客户端的消息了。
- **只要cpu和工作线程有剩余,新请求会在O(1)时间内得到处理**。由于大部分业务请求都要花费很多毫秒,即使只有一个任务由于调度的原因而得不到及时的处理,都是无法接受的。以hulu为例,有两种任务分发模式:一种是分发到固定线程,另一种是通过condition。前者没有同步开销,对于大流量效果更好,但无法保证本要求。后者有高强度的同步开销,吞吐不会太高,但可以保证本要求。这让用户很纠结。在baidu-rpc中总是能保证本要求,并且性能好于hulu。
- **对同一fd和不同fd的写出是高度并发的**。当多个线程都要对一个fd写出时(常见于单连接),第一个线程会直接在原线程写出,其他线程会以[wait-free](http://en.wikipedia.org/wiki/Non-blocking_algorithm#Wait-freedom)的方式托付自己的写请求,多个线程在高度竞争下仍可以在1秒内对同一个fd写入500万个16字节的消息,这很可能是目前最高性能的同fd写出实现。对不同fd的写出总是并发的。值得一提的是,我们在未来可能会用类似的技术实现往磁盘写的Channel,以满足一些服务器对超高频率日志的需求。
- **服务器线程数自动调节**。传统的服务器需要根据下游延时的调整自身的线程数,否则吞吐可能会受影响,一般是通过配置。在baidu-rpc中,每个请求均运行在新建立的bthread中,请求结束后线程就结束了,所以天然会根据负载自动调节线程数。
......@@ -120,12 +104,9 @@ baidu-rpc背后的技术和知识请阅读[深入RPC](http://wiki.baidu.com/disp
如果你有任何需求,都可以向我们提:这并不意味着我们会全盘接受,我们也许会提议另一种解决方案,或指出一些理解的误区,不过这终究可以使想法得到更多打磨,产生新的火花。灵活的内部结构使我们可以更快地添加新功能,有一些功能是其他RPC实现很难拥有的,举例来说:
- 编写和访问HTTP server:你写的任何protobuf
server都可以在移动端用HTTP+json访问,你也可以写纯的HTTP/HTTPS server或者访问其他HTTP server。
- 编写和访问HTTP server:你写的任何protobuf server都可以在移动端用HTTP+json访问,你也可以写纯的HTTP/HTTPS server或者访问其他HTTP server。
- backup request: 又称tied requests,是一种降低请求延时的技术。
- [Locality-aware load balancer](http://wiki.baidu.com/display/RPC/Locality-aware+load+balancing) :
这种负载均衡算法会优先选择最近的服务器,即同机 > 同rack > 同机房 >
跨机房,并在近节点发生故障时快速收敛,当节点大量混部时,这可以有效地降低延时,并规避网络抖动。
- [内置服务](http://wiki.baidu.com/display/RPC/Builtin+Services) :
彻底改变开发和调试体验的强大工具!配合[bvar](http://wiki.baidu.com/display/RPC/bvar)更贴心。
- [Locality-aware load balancer](http://wiki.baidu.com/display/RPC/Locality-aware+load+balancing) :这种负载均衡算法会优先选择最近的服务器,即同机 > 同rack > 同机房 >
跨机房,并在近节点发生故障时快速收敛,当节点大量混部时,这可以有效地降低延时,并规避网络抖动。
- [内置服务](http://wiki.baidu.com/display/RPC/Builtin+Services) :彻底改变开发和调试体验的强大工具!配合[bvar](http://wiki.baidu.com/display/RPC/bvar)更贴心。
- [组合访问](http://wiki.baidu.com/pages/viewpage.action?pageId=213828709):并发访问,分库分环,从没有这么简单过。
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment