转:brpc的研发经历
转载自:https://www.jianshu.com/p/124dc2c7d9d3
RPC是个老概念,五花八门的实现非常多。在14年我刚转到基础架构部时,其实是不想做RPC框架的。我的想法可能和很多工程师一样:之前做了那么多系统,现在就让我来搞个编程框架?而且这能做出什么花头?但事实很快证明我错了,编程上的事真的需要实践,否则看问题就很浅。像搞深度学习,vgg rcnn gan嘴上可以说得不停,但只要没在真正严肃的项目中调过参数,你就是门外汉。
RPC的深度在于现代的互联网公司中几乎所有服务都是使用RPC的,大部分工程师和它打交道。如果你能看到其中的痛点,提高了效率,那么整个公司的开发效率都会有明显的提升。大家都是从学生时代过来的,心里清楚一个东西在正确的条件下正确运行很容易,但要在所有情况下能正确运行就非常困难。前两天我修了个问题:brpc在fedora 26下一个weak function莫名其妙地没有被tcmalloc中的对应版本覆盖,导致heap profiler启用不了,ubuntu,centos下都是好的。这种问题往往和系统或ld有关,要精确定位很麻烦,最后我找到了一个workaround。但这个事情耗了我几个小时,因为需要在很多系统上验证没有regression。RPC里大量此类东西,虽然麻烦但能提高用户体验。那个问题其实和brpc对tcmalloc的支持方式有关,brpc默认不链接tcmalloc,但用户在程序中链接tcmalloc后,我们希望cpu和heap profiler要自动开启(这两个功能依赖tcmalloc的API),同时用户不用重编brpc。所以我们得在brpc中动态判定是否链接了tcmalloc,这就没那么容易了。对我们很麻烦,但用户的体验更好了,甚至用户会觉得理所当然。
知识是需要大量实践的,你也许可以在正确的条件下用dlsym有效地覆盖一个glibc中的函数,但你可能不知道dlsym在有多版本符号存在时可能无效,或dlsym和一些库合用时(比如用于展开栈的libunwind)会死锁,或dlsym对静态链接是无效的除非编译加了-rdynamic。你也许可以基于一些上下文切换库三下五除二搞出个libcoroutine,但你可能不知道的是JNI会检查stack layout而不能使用自定义栈,或程序运行在valgrind中需要注册栈地址才不会报错,或一个栈跑到另一个LWP上展开时会触发gcc4以上版本的thread-local误优化。这些知识,成千上万条这种知识,通过实践才会深深地刻画在脑中,构成一个工程师真正的竞争力。
我一直坚信所有的用户体验都是端到端的,只有站在用户的角度,把整个流程以既高效又不失扩展性的方式走通,才是最好的选择。良好的文档正是这种理念的体现:给新用户铺好路能快速上手,让老用户知其所以然更上一层楼。这种想法也体现在代码中的方方面面:每个选项都有合理的默认值,用户不设也能用;在注释中提示best practice,避免用户走弯路;用户界面、日志内容不啰嗦,让用户一眼看清楚问题的全貌。不做并不意味着我们没能力做,而是早已被事实证明可能出现非常subtle的bug而被淘汰掉的选择。知道的越多,你就越会有一种责任感,需要帮助用户修一条好路,避免陷到你已经踩过的成百上千个坑中。
说到性能,RPC的性能评估其实很像VC投资初创公司:每家都在说自己的东西好,并能拿出数据,可真的好不好天晓得。所以VC只能看团队,查背景,凭感觉,这钱花出去了能不能拿回来心里都慌的很。RPC其实也这样,每个实现都有大量独特的设计和接口,用户不太可能轻易地从一个RPC切换到另一个RPC,并在完全相同的环境下进行对比。每个RPC实现都在说自己高性能,轻量级。这是个自卖自夸的游戏,用户只能看脸。但就像我们奇怪古人连那么简单的东西都不知道一样,人的认知就是这样,内行的常识可能对外行非常困难,甚至这个常识非常简单。在很多年以前,我们对“高性能”的认识还停留在“极限QPS”和“延时”两个维度的时候,被一个复杂系统中的拥塞问题搞的焦头烂额,大家就觉得莫名其妙啊,每个环节都很快,这延时怎么就哗哗哗地涨上去了。最后在反反复复的思考和分析后才发现,QPS和延时的乘积与程序的最大服务能力紧密相连。我们搞了个概念叫volume,发现串行系统的volume可以相加,并行系统的volume可以求min,然后一层层地迭代上去从而计算出复杂系统同时能处理的最大请求数,并解决了拥塞问题。
不过就是个乘法。
今天我们知道这个原理是little's law,tcp中的BDP也是类似的道理。我们在文档中描述了相关的知识。但即使是这样,根据我们在百度内的支持经验(没人会否认百度研发的整体素质吧),大部分RPC的用户对这个乘法理解还是有困难的,更别提理解串行相加,并行求min,在系统设计中活学活用了。一个乘法尚且同此,更深入的可想而知。普通用户是很难看明白性能测试的道道的。我们团队里有个老梗:“处处是热点,处处不是瓶颈”。这说的是如果整个程序写的都很粗暴,不考虑性能,最后用profiler一跑,发现每个点都只有1%,2%,然后得出结论,“性能非常好,优化空间已经不大”。但实际上你去分析下hot path,会发现有太多可以大幅提高的点了。性能就是这样,设计确保了流程是最优化的,但实现也非常重要,细节全靠抠。brpc上关键路径上的代码多一次new都需要讨论,最热的路径上甚至不允许出现申明一个可能无用的空std::string,因为老版本glibc中的空string是要加引用计数的,对cache有影响。
抠细节的背后需要工程师对性能的深入理解。一个函数的性能是可以估算出来的,测试只是验证。如果不符合预期,你就要深入地去看,最终理解背后的原因。为什么一次激烈的cacheline同步大约是700ns?或是一次调度延时至少是3us,99%以内是20us?或是linux下的timed condition有60us的延时?或是一次上下文切换可以在200ns内做完?或是无竞争的mutex可以实现为两条20ns左右wait-free的原子指令?掌握了这些知识,你才能抓大放小,把精力放在最关键的事情上,并把它做到世界上最好的水平。
但即使到现在,brpc中仍然有一些极具挑战性的问题,比如bthread的调度如何能更好地保持cache locality,如何在NUMA机器上跑得更好,如何尽量消除内核调度的延时,如何更高效率地重用栈...如此种种。我们把brpc开源出来,正是为了让感兴趣的伙伴一起加入进来,做出一个更上一层楼的RPC框架。与大家共勉。
转:brpc的研发经历的更多相关文章
- paper 59:招聘
借Valse宝地发条招聘广告:D[腾讯优图]技术大咖招聘 欢迎各位技术大咖尤其应届优秀毕业生投递简历.简历投递:youtu@tencent.com简历投递,邮件标题请按照以下格式:[腾讯_上海_招聘 ...
- 25.创业真的需要app吗?真的需要外包吗?
两个星期前,一名亲戚的朋友打算投入自己的二十多万元去搞个摄影社交app,问我有没有靠谱的外包推荐,我赶紧劝住他,现在app的成本已经非常高了,初期的研发就要十几万,加上后期的推广(每个用户成本大概2元 ...
- 我们正在招聘java工程师,想来美团工作吗?
我们希望你有? 1.3年以上Java服务器开发经验,精通Java及面向对象设计开发,熟悉主流web框架 2.熟悉网络编程,熟悉TCP/IP协议,熟悉互联网应用协议 3.有大规模分布式系统设计与开发经验 ...
- [Kingdom Rush]团队分享:如何做塔防手游
转自:http://www.gamelook.com.cn/2015/03/207324 GameLook报道/2014年11月,乌拉圭开发商Ironhide Studios发布的<Kingdo ...
- 一文读懂NodeJS全栈开发利器:CabloyJS(万字长文)
目录 0 修订 0.1 修订说明 0.2 修订历史 1 基本概念 1.1 CabloyJS是什么 1.2 CabloyJS核心解决什么问题 1.3 CabloyJS的开发历程 2 数据版本与开发流程 ...
- 关于nlp的一些探索
深度学习,知识图谱,nlp学习经历 获取信息来源:英文paper研读,吴恩达公开课,Hiton公开课,北大nlp教材,英文最新学术论文,中科院院士技术 ...
- DataPipeline CTO 陈肃:我们花了3年时间,重新定义数据集成
目前,中国企业在大数据流通.交换.利用等方面仍处于起步阶段,但是企业应用数据集成市场却是庞大的.根据 Forrester 数据看来,2017 年全球数据应用集成市场纯软件规模是 320 亿美元,如果包 ...
- 嵌入式开发—C语言面试题
嵌入式开发—C语言面试题 源地址:http://blog.csdn.net/xdx2ct1314/article/details/7358929 1. 用预处理指令#define 声明一个常数,用 ...
- software engineer's resume(帮助你写程序员简历)
关键词 参考 简历模板 参考 下面开始是正文(关键词原文) 介绍 本项目由海外兔 (https://osjobs.net) 维护,海外兔团队由一线互联网面试官组成,提供海内外公司一对一入职套餐以及算法 ...
随机推荐
- 1、Java 开发环境配置
Java 开发环境配置 在本章节中我们将为大家介绍如何搭建Java开发环境. Windows 上安装开发环境 Linux 上安装开发环境 安装 Eclipse 运行 Java window系统安装ja ...
- Nginx配置SSL证书,提高网络安全性
首先区别Http与Https HTTP:是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高 ...
- 小白入门Web前端开发学习一周小结
说之前还是先说点其他的,简单介绍下自己为何选择web前端开发: 本人之前在一家国企单位从事质检工作,干了3年,工资和待遇还算不错,但由于其工作的流动性导致知识的脱轨以及精神上的空缺,最后还是打算在25 ...
- Mac开发工具
便捷管理你的Mac App Homebrew:https://brew.sh/index_zh-cn 强大的文本编辑器 Sublime Text:http://www.sublimetext.com ...
- 掌握提高 Web 应用的性能的方法 之 优化 PHP 和 Laravel
Laravel 有很多东西.但是快不是其中之一.让我们学习一些优化技巧,以加快运行速度! 自从 Laravel 诞生以来,没有一个 PHP 开发人员不受她的影响.他们是喜欢 Laravel 提供的快速 ...
- [netty4][netty-transport]netty之nio传输层
[netty4][netty-transport]netty之nio传输层 nio基本处理逻辑 查看这里 Selector的处理 Selector实例构建 NioEventLoop.openSelec ...
- SVN的基本使用
2020年7月6日 为什么需要版本控制? 需要清晰地保存某些文件的不同修订版本 控制文件的发屐过程,找出导致 BUG 的原因 轻松将项目或文件恢复到指定版本 极大方便团队之间协同开发,防止出现混乱 在 ...
- Wireshark中的Checksum: 0x90c5 [validation disabled]问题
Wireshark中的Checksum: 0x90c5 [validation disabled]问题 废话不多说先上问题图: 这是我在做关于DNS协议PPT的时候出现的协议树第五项展开结果,可以发现 ...
- Jmeter 常用函数(2)- 详解 __RandomDate
如果你想查看更多 Jmeter 常用函数可以在这篇文章找找哦 https://www.cnblogs.com/poloyy/p/13291704.html 作用 产生一个随机日期 语法格式 ${__R ...
- 算法-利用队列实现逐行打印杨辉三角形的前n行
分别打印二项式(a+b)^n展开项的系数,在程序中利用了一个队列,在输出上一行系数时,将下一行的系数预先放入队列中.在各行系数间插入0. void YANGVI(int n){ Queue q(n+) ...