供稿 | eBay IE Team
作者 | 许健
编辑 | 顾欣怡
本文13122字,预计阅读时间40分钟
更多干货请关注“eBay技术荟”公众号
本次专栏分享,我们邀请了ebay基础架构部的研发总监许健,就设计高可靠、高扩展、高性能产品的主题分享他多年来的心得。共分为六个模块:稳定性/正确性、扩展性、高性能、过渡和迁移、整体考虑以及未来3-5年的挑战。上期我们探讨了稳定性/正确性及扩展性,本期将着重讲述后四个模块的相关问题。
2016年5月24日,Sami(现任eBay数据基础架构部副总裁)与我们分享了他这些年来做技术的心得,其中一个主题就是 如何设计高可靠、高扩展、高性能的产品 。时至今日,在经历了这四年的各种“风风雨雨”后,我对Sami当年的话有了更多的深刻体会。本文中,我将引用Sami的一些“金句”原话,针对这些点,写写自己现在的理解,算是四年来对于这个主题的一段总结回顾,也希望能对大家有所帮助和启发。
本次专栏分享分为上下两篇, 上篇 探讨主题:稳定性/正确性和扩展性(详情请点击: 分享 | “三高”产品设计的这些坑,你是不是也踩过?(上) );本篇为 下篇 ,探讨主题:高性能、过渡和迁移、整体考虑和未来3-5年的挑战。
跟你的客户敲定SLA。
Define SLA for your service with your customers.
SLA(Service Level Agreement,服务级别协议)的问题一开始就要讲清楚。这事情说起来容易,做起来难,但总比什么都不做要好。
工作多年以后你就会意识到,很多事情都需要辩证看待。若想要达到更高的指标,你就必须知道自己愿意为之付出多大的代价,很多事情没有最好的只有更合适的。我们当然有在更高层次达到双赢的愿望, 但同时也做好了基于数据激烈争论的准备,争论时逻辑一定要清晰。eBay中国研发中心的总经理Vivian曾对她的部下说,她衡量一个人是否优秀的一条重要标准就是看他的逻辑是否清晰。
给每一个模块敲定预算。
Define a budget for every component.
每一个模块,包括吞吐量、延迟等,都要敲定预算。关于这一点,我有两个实际的例子。
第一个例子是我们在Openstack时代对Dev VPC 使用了Nicira 的 SDN方案。那个时候需要在每一个Nova Compute(计算节点)上部署SDN Agent。但后来我们发现,SDN Agent 的内存消耗会逐步增加,最后触发Linux OOM Killer 杀死正常的虚拟机。在Nova Compute上部署Logstash的时候,也发生了类似的问题,由于后端中转日志的模块性能下降而导致Logstash在本地堆积日志内存上升。所以现在我们迁移到Kubernetes 的时候,就吸取了教训,在每一个节点上部署Beats的时候直接设置了CGroup限制。
第二个例子是关于Pronto,就是eBay内部基于Elastic Search的在线分析平台。我们把Pronto部署在云平台后,发现其性能并不稳定,究其原因是 Noisy Neighbor 搞的鬼。这里我主要说的是敲定预算(Budget)以后实施的问题,比如CPU,Memory,IO等等。最近我们部门在研究 CGroup V2 ,要做到IO 隔离真的不容易。由于CGroup 内部有不少统计计算,会消耗资源,要是处理不好就会因为Enable CGroup 导致性能下降。(这里再次强调一下辩证看问题的习惯,当你看中一件事情的好处的时候,一定要想想自己需要付出什么代价,这个世界可没有免费的午餐。)
如果你不限制 CPU/Mem/IO 的使用,那不好的事情一定会发生。马云说,他做翻译社的时候因为疏于监管,导致会计随意拿走公司资金。这说的是人性问题,其实,系统也是一样的。
如果你有某个往数组和HashMap 里面添加元素的操作,你就要想想会不会有人不停地做添加,最后把你的内存全部吃掉;如果你暴露了某个API让人来拿数据,你就要考虑是否做Pagination(分页插件),以避免一下子加载太多数据让服务崩溃;很多API 交互一旦发生客户端等待超时,就会触发客户端重试机制,所以后来所有的控制器都引入了指数重试回退机制。但是如果有大量客户端,那服务器一抖动(有时候其实是网络抖动造成的),你就得想想会不会触发客户端重试风暴压垮服务。
有一次我们的Kubernetes API Server 性能急剧下降,就是某个Controller 触发重试导致的;而且还会形成正反馈,使得情况加速恶化,你越不行我就越重试,于是越多请求…所以后来所有的Controllers 都有超时指数重试回退机制。
还有黑洞效应。我们Keystone 的VIP配置看的是哪个Keystone 实例的响应快,负载均衡器(Load Balancer)就把请求送往哪里。有一次我们把其中一台物理机换成了虚拟机,结果这个虚拟机上Keystone 应用由于内存不够直接就不正常工作了。糟糕的是,它并没有直接崩溃,而是马上返回 HTTP 500,由于负载均衡器的健康检查没有检查HTTP 返回码,这台有问题的Keystone 节点就像黑洞一样吸走了所有流量。试想一下,如果这台Keystone 虚拟机跟其他服务一起部署在同一台Hypervisor上,是不是就相当于一个Noisy Neighbor?
生产环境还有很多难以预见的情况,所以你最好保底设置预算。紫霞仙子在至尊宝心中留下一颗眼泪,这颗眼泪会不时地提醒你,曾经有一个前途似锦的系统摆在我的面前,可是我没有珍惜,结果出了很多事故,如果再给我一次机会,我会限定每一个女孩对我的伤害范围,以免自己伤心过度。
Understand your OS and runtime and how to tune it.
这一点的重要性我就不多强调了,唯品会基础架构的负责人跟我开玩笑说,只有两件东西出问题会出让他“掉脑袋”(位置不保),就是 操作系统(OS)和网络(Network) 。 如果你想培养自己这方面的能力,推荐学习《性能之颠-洞悉系统,企业与云计算》这本书。
Tess(eBay基于Kubernetes的下一代云计算平台)HRT(Host Runtime Special Interest Group)的架构师CY说,他今年会动员我们部门中在该方面有经验的同学,希望能把他们这么多年在线上做性能调优的经验全部做进系统,并考虑开源。对此,我感到非常期待。我曾问CY,希望把eBay的HRT 做到什么程度。他给我的回答是, 对于线上任何和操作系统有关的问题,要做到在一周内通过我们自己的工具进行定位,找到根本原因,然后在一个月内把补丁安全应用到整个环境。
定义事故发生时的降级SLA。
Define your acceptable degraded SLA in case of incident.
对于Sami的这句话,我感到有些惭愧,因为我自己都没有做过这件事。其实这篇分享写到这里,突然觉得有点力不从心,因为很多点其实我们自己也没真正做到。
我想起了Sean(Altus,PAAS的研发经理)去美国出差找到Charles(总部流量管理的方案架构师),跟他描绘在网站上做 Capacity Add (特别是Region Add)时候的理想体验。
“你应该登陆Altus Capacity Console,找到想做的Capacity Add的应用,然后点击Extend to RNO(RNO 是我们新数据中心的缩写)。这时,你就可以去楼下星巴克喝杯咖啡,等待所有流量均衡自动完成。不用担心网站故障,因为我们会自动检查网站健康。”
Charles 听完以后,掏出打火机,点了根烟,吸了一口,看向远方,缓缓说道:“神说会有光…”
Sean 回国后大受鼓舞,对我说,Charles 他不相信我们能做成这件事,但是我们一定要做成,然后把Altus Capacity Console 的登陆页改成“神说,会有光。”
截至目前为止,离Charles 的这句话过去快两年了,神的光还是没能照到我们。我对于为什么神的光到现在还没有照到我们的根本原因的解读是: 并不是我们的能力不行,而是我们并没有坚持在这一点上真正地做高优先级持续投入。 我们的发展已经到达了一个关键点,就看我们的技术主管和架构师是不是可以坚定地去实现自己的理想。如果你觉得这就是你在eBay的核心价值,那就勇敢地说出来,一个人的善良应该有些锋芒。
把在生产环境中你可以预见的问题在上线前测试100遍。
Test at 100 times what you are expecting in production.
eBay在线上出事故的时候有两大救命工具,一个叫 GTR (Global Traffic Redirection),一个叫 DFT (Database Failover Tool)。这两个工具功能单一,就是切流量和切数据库。但是他们一定一定要好使,用乔布斯的话就是“It just works”,不然我们就惨了。从小我们就学 “Practice makes perfect”(熟能生巧),其实计算机系统也是这样,我们要经常做演习,一个没有打过仗的部队,真上战场时战斗力肯定堪忧。
最近我们看了监控部门基于Click House 的新Events 方案,觉得Click House 依赖的 ZooKeeper 真是我们的软肋。因为跨Region部署ZooKeeper担心脑裂,我们采取了把数据放共享存储,然后对ZooKeeper 做Active Standby 模式部署,所以一个Region 出问题就需要Fail Over到另一个Region。如果要正式上线,就得做他个 100遍 Fail Over才行。对于一个成熟的组织,这100遍Fail Over实施起来其实并没那么困难。 有时候我会想,CICD 的本质是什么? 后来我给了自己一个答案,CICD 就是把你上线要跑的部署逻辑,以及上线后的业务逻辑,全部固化到代码里,在平时就跑他个 上 万遍 。
尽可能缓存和批处理,减少线上处理,用消息中间件做更新。
Cache and batch whenever possible. Do the minimum online. Update through messaging.
缓存和预计算我在前面已经谈过了,这里简单说一下 批处理 。
我们不少系统都会提供 Bulk API 。由于Bulk API省去了很多交互,性能往往会好很多。但是如果要在Bulk API 处理到一半出了问题的时候还要保证操作完成性,那就难了。因为这时你其实要求的能力是Transaction (事物处理,原子操作), 对此,我的建议是做到幂等,然后重试,而且还要看一下系统能否接受最终一致性。 我们从 Openstack 过渡到 Kubernetes 时确实发生了比较严重的性能问题,在Kubernetes 和 LB(负载均衡)的交互中付出了远超预期的精力,至今印象深刻,具体内容将在稍后的迁移部分中详细讲述。
考虑异步,零拷贝,RPC,Unix Sockets…
Think about Asynchronous,Zero-Copy,RPC,Unix Sockets…
这几个概念其实并不深奥,如果想要深入了解,可以拿几个市面上的高性能开源产品学习一下。但这还是停留在纸面上,最好要有现实的舞台进行实战,做几个对性能要求很高的项目,比如Sherlock Events,Software LB Solution等。
工程部门的领导应该鼓励团队成员在可靠性和性能上做持续精进,让团队成员自己提一个自己觉得很骄傲的目标,然后支持他们去达到这个目标。我们的HR 小姐姐介绍我看《养育女孩》这本书,里面提到 “火花”理论 ,就是父母在养育子女的时候要发现和点燃孩子的火花,而不是去把孩子改造成你希望的样子。 我们的工程师也有自己的火花,作为组织领导,你愿意去挖掘和点燃这些火花吗? 如果你是真的愿意,请你以后跟大家谈话的时候多问问个人的理想,而不是一味地谈自己的理想。“私欲为公” 才是长久之道。
避免用户态与内核态交换,以用户态为友。
Avoid kernel switches. User space is your friend.
DPDK,XDP这些其实我没有怎么接触过,只知道他们性能很高。我们部门的CY(Tess HRT 架构师)和 Toddy(运维架构师,运维部门的同学平时都尊称为老法师)曾经看过Netscalar 的Software LB,其实就是一个循环,不停地从网卡读请求,然后进行处理,没有任何用户态内核态切换,所以才能做到高性能。我一直有个疑问,为什么Nginx,Envoy 这样的高性能服务不提供用户态的发行版本呢?
用监控和告警实现100%的可见性。
100% visibility through monitoring and alerting.
某作者:重要的事情说三遍!!!
某同学:欸?那前两遍呢?
某作者:欲知详情,请看上回分解: 分享 | “三高”产品设计的这些坑,你是不是也踩过?(上) 第一章 09 条
从头做一个新产品总是有趣且相对简单的。
New Product from scratch is always fun and relatively easy.
能说上面这话的人一般都是有过一线经验的了。曾经有个副总开玩笑说,他的主要工作就是“Killing Project”,其实他在位的时候对投入自研产品是比较支持的,像 CMS (Config Management System)和 Apache Kylin 两个产品就是在那个时候做出来的。
要知道,做新产品一开始就要投入大量研发,而且一般都是高级别的技术主力,然后从初级阶段到成熟阶段又需要不少投入。在eBay 这样的公司,产品往往不会孤立存在,一个产品跟其他很多系统都会有交互。所以一旦有了新的产品,就要开始做迁移,有些迁移过程比较长,于是又需要花费大量精力。
事实上,我经历的若干次新产品取代老产品的过程都是:新产品其实没有我们想象的那么简单,时间投入往往超过预期;时间一长,各种怀疑的声音就会出现,压力随之而来;更难的是,我们原来的老系统还需要维护,当技术力量调往新技术栈的时候老系统又出问题,于是两边奔波劳碌,非常辛苦;而且处理的问题还不一定是能够提升自身能力的问题,就是身累加心累。 所以说,新产品的启动一定要谨慎,一次启动,就意味着后续的大量投入。
如果有人跟你说,我只需要几个月就可以把东西搞出来,那你只能回一个“礼貌微笑”了。这里引用一下某位同学的风格:“请定义什么叫做搞出来。”我最不希望看到的就是把新产品当作练手的对象,练完手,人走了,问题却根本没有得到解决。
把老系统迁移到新系统的经历就是个噩梦。
Transition from old to new can be nightmare.
在eBay 工作了13年,我有过一次团队因为做迁移而几近崩溃的经历。那时候,Cloud E2E团队(我们就在那个时候因为合并了PAAS和IAAS,给团队起名字叫 Cloud E2E,E2E 后来也成为了这个团队的核心价值)一做迁移就出网站故障,十几年的技术债又被翻了出来。 PHX Exit 有硬期限(Hard Deadline),如果没有推动进度,就会有领导来问你细节,进度越慢,问得就越细。最后各级领导都来问候,导致我们一边奔波于汇报,一边又没有进度;对数据对到了凌晨,过了几个小时领导又要来问进度。团队成员一度士气低落,信心都快要垮了。
这件事情的转折点是把Jonathan(PAAS的架构师)从别的项目上拉回来,让他帮忙解决Tech Refresh 。回来后,Jonathan 做了几个决定: 停掉所有给领导做报表的工作,因为这并不能促进项目进度;开始分析线上应用的特点(比如历史上有没有自动修复,有没有自动部署记录),给线上应用分类,从而判断是否可以自动技术更新;最麻烦的应用由他亲自负责,而且责任到人,分到自己身上的工作无论多晚一定当天做完。我很钦佩这样的架构师,以前蒋旭(Kylin 和 CMS 的作者)带我们做项目的时候也是如此,最难的部分亲自做,而且非常有魄力,说停2个月做代码重构就停下来2个月,如果到最后项目不能如期交付,他就担责任。 我们的高级别技术人员就是应该要有些锋芒,敢于在领导面前坚持自己认为正确的事情。
最后我们终于挺了过来,涅槃重生!等做完回过头去看,我们发现系统的各个部分都得到了明显的强化。我清晰记得,那天在Seabiscuit会议室给Mazen(现任eBay CTO)汇报工作,我给他看了一组非常“impressive”的数据;然后告诉他,这里的每一个数据,都是我们亲身实践反复验证过的,绝对不是最佳情况(best case)下的产物。
迁移计划必须在新系统设计之初就考虑。
Transition path is the first thing to design.
说到迁移计划我底气也没有那么足,因为在没有详细迁移计划的情况下就启动新方案的事情不是没有。新方案总能吸引眼球,因为它只要瞄准一个点,做出亮点就可以。但如果真的要换掉老方案,就需要考虑各种情况,适配各种环境,要是做新方案的人没有亲临一线处理过老方案的各种问题,那我觉得迁移会是个大问题。 我甚至认为应该更加强势一些,没有迁移计划就不要启动新系统 。当然,人不能有两套标准,当我们这么要求别人的时候,也得审视一下自己,我觉得自己也没有都做到。
迁移并非趣事,甚至让人几近崩溃,但它是成功的关键。
Transition is not always fun and can be frustrating but it is the key for success.
把老系统迁移到新系统的例子前面已经说过了,我觉得在经历了 PHX Exit 这个项目后,团队成员的自信心都提升了一个档次,这个团队以后可以啃硬骨头而不大会被击垮了。eBay 中国研发中心的总经理Vivian 说,这是我们大团队至今为止做的最成功的项目。我觉得人要成长就得经历这个过程,不经历风雨怎么见彩虹,就像海德格尔说的“向死而生”,逼入绝境,涅槃重生。
这不仅适用于自身的成长,亦可用于人才培养。我记得有句话,说是如果你真想培养一个人,就把他领到悬崖边上,一把将他推下去,看着他往上爬,等他坚持不住要掉下去的时候,再伸手拉他一把。 “我可以承认差距,但是我不能丢失自信” ,这是我自己在经历了一些挫折后给自己总结的话。所谓“试玉要烧三日满,辨材须待七年期”,人的成长就是在一些极端情况下坚持不懈、不气馁,只要扛过来了,你就提升一个层次。
好的设计能节省不少时间。
If designed correctly,it will save you a lot of time.
看到Sami这句话的时候,我就在回想这些年来有没有这样的例子,可惜,并没有找到。 我其实有不少迁移的案例,但从没有一个案例是原来要 一年 ,然后找到了某个方法就能变成 一 个 月 的。 一般我们做迁移,都会在新系统前面放一个跟老版本兼容的Proxy层,然后慢慢切流量。比如做ODB 迁移到 CMS的时候,先是双写ODB 和 CMS,但是读以 ODB 为准;然后变成双写ODB 和 CMS ,但是读以CMS 为准;最后去除ODB。
当时监控组架构师Huai做这个项目的时候,提出了我没有想到的一点: 我们可以切读到CMS 的那个点,不要全部切掉。 由于作业启动的时候是以ODB为准的,只要切的时候系统中有作业正在进行,那么,直到这个作业运行结束都会以ODB 为准。我们每次迁移都是一次技术债务的清理,整个组织也明确了Spec Driven(规范驱动)的方向,充分认识到保存目标状态的重要性。
再思考得深一点,回顾这些年,我们似乎都在不停地做迁移: 从ODB 到 CMS(两代配置管理系统),从Stratus(基于VMware的云计算方案)到C3(基于Openstack的云计算方案),从C3到Tess(基于Kubernetes的云计算方案),Staging 环境和Sandbox环境切来切去…然而神的光芒似乎一直没有照耀到我们,甚至还有种碌碌无为的紧迫感。
这次新冠疫情,过年的时候只能呆在家里,我就在反思最近这4-5年做的迁移项目。 如果让我重做一遍,会有什么不同吗?
以C3 (基于Openstack的云计算平台)到 Tess(基于Kubernetes的云计算平台)的迁移为例 , 我做了如下总结:假设C3 环境下我们要创建一个带有 100个 虚拟机的应用,那么先准备100个虚拟机,然后一个批量操作把负载均衡器配置好,后续部署代码的时候重用这 100个 虚拟机。也就是说,多次代码部署的时候不会重建虚拟机或更改IP。迁移到Tess以后,每一个POD 创建完成都会触发一次负载均衡操作(加LB Member),Tess 不是Fire-and-Forget(发后即忘)模式,而是不停地进行Reconcile。Kubernetes Native每次部署时都会重新创建所有POD,而在胖容器环境更换Image也是需要重建全部POD的。
在这个过程中,其实API的调用次数是明显高于原来的C3环境的。但现实情况是,并非整个生态都已经在Tess 上,我们还有很多外围系统,比如 LBMS,CMS Sync,UDNS,RAS,CMPAAS。这些都已经在eBay 运行多年,但他们还没有适应Tess 的工作方式。
所以问题来了,我们是改造这些外围系统,还是改造Tess? 如果要在短时间内推翻所有的周边系统来打造一个全新的世界,我们又是否有足够的人手?
我们曾耗费了大量时间,把Tess 调用LBMS (Load Balancer Management Service)的方式改成了Bulk Call;让LBMS 去除了多余的输入有效性检验来换取性能;添加了LB 设备来分摊调用量;内部也开始有声音说Software LB才是解决之道;CMS Sync 逻辑改写了好几版,我们却仍要向Problem Management团队(出网站故障后eBay 用来跟进的专业团队)不断解释:同一个Instance 被两个不同的应用引用是因为高压下导致CMS Sync 出问题,CMPAAS(eBay的代码部署工具)暴露Schedule性能问题是因为不堪重负。
这样的投入比原来设想的大太多,我们是不是需要思考一下,当引入一个新的系统的时候,到底最看中的是什 么? 我们看中Docker的“Build Once,Run Anywhere”(一次编译,随处运行),看中Kubernetes的Spec Driven(规范驱动),而在这个例子里,Rolling Upgrade是否需要坚持POD和对应的IP 重建值得思考。
这种感觉就像,你是家里最能干的,有远大抱负,但你已经不是一个单身小伙子了。家里的孩子需要照顾,上学需要你操心,爸爸妈妈的身体也不如以前了,并且他们最需要的不是你给点钱安排他们去旅游,而是希望你能多关心关心他们,还有七大姑八大姨…总之,你必须综合地考虑问题。
再举个例子,LBMS(eBay 的LB 管理组件)到 LBaaS(Openstack的LB 管理组件)的迁移, LBMS 其实就是一个跟LB 交互的API,并不负责LB的Schedule和IP分配。大家都一致认为 LBaaS 的API 才是我们所需要的,但是这个项目做了一年多,我们还是放弃了。因为做的过程中业务上总有源源不断的要求,而且这些要求LBaaS还不能提供,于是就都落在了LBMS上。我们两线作战,花了一年时间想把 LBMS 的功能迁移到LBaaS上,但是后来人手跟不上,最后美国总部Cloud 的经理做了决定,停用了LbaaS。
现在我们面临的,就是在 Tess 环境里面缺乏类似LBaaS这样一个服务的问题。我现在的体会就是, 一定要明确什么才是我们最在乎的 。首先,需要有这样一个API,能够集LB的Operation API、LB的智能分配和IP分配于一体。其次,应该考虑哪些周边系统可以被重用,而不是追求用Go 把周边系统都重写一遍。即使真的决定重做一套新系统,也必须明确后续迁移的成本有多大,以避免长时间两线作战。
除此之外,还有一个很关键的点。以LB 和 Traffic 流量管理来说,我们在流量预测、流量再平衡上一直没有很大的进展。在流量管理的几次演进过程中,我们都花费了大量时间去做新系统,完全推翻原有系统,然后做迁移。在我看来,这里面有不少低水平的重复,而一直困扰我们的核心问题却没有足够的投入得以解决。 eBay 存储组研发经理ZhiTeng有一个形象的比喻 : 你想把门口的花盆往东挪15公分,而东面邻居家的房子距离你10公分。一种思路是,邻居把房子拆了,向东让你们5公分;邻居提出的方案则是,新找个地块,拉个地产商,按新规划重建一个小区安置你。
我想提一个观点,就是把自己的部门当成一个独立核算的公司,假设员工的工资都是你自己掏腰包,把eBay当成自己唯一的客户,然后回想一下自己在做决定的时候会有什么不一样。怎么才能让更多的同事有这样的意识呢?我觉得解决方案是 授权 ,因为授权可以激发责任心。经理特别是高级经理要放权,要 “Eyes on, Hands Off” ,约束自己的控制欲,我认为这是组织效率提升非常重要的点,比请教练搞Agile 实在。
在引入新服务的时候考虑抽象层。
Abstraction is your friend when introducing new services.
在引入新服务的时候要考虑抽象层,事实上,我们也都是这么做的。在同一个模块内部,我们会放一个接口,后面跟两个实现类;然后你会看到,在微服务架构下,几乎每一个迁移项目里都有一个Proxy服务去做类似的事情。
我在实际工作中碰到的问题是,对于那种更新换代的大项目, 比如Stratus 到C3,C3到Tess ,我们都会安排专人为新系统写这个Proxy,而且往往是有老系统经验的人去写。有的人觉得这一个Proxy/Wrapper 没有多少技术含量,应当很好处理。但实际上,由于新系统慢慢成熟和新老系统切换的时间很长,加之新系统不停修改,负责Proxy的同学是十分繁忙的,但凡一点点新系统的改动,就要去Proxy上改,这可绝非什么清闲的差事。如果新老系统在一个小组里面还好一些,但如果跨团队,出现抱怨的情绪是正常的,需要组织领导多关心和正向引导。
我越来越觉得,新系统的设计者在一开始启动的时候就要考虑这个抽象层,如果条件允许(并不是所有的事情都可以一刀切的,要因地制宜),谁启动新的系统,谁负责迁移。
要有前瞻性,做下一代产品的时候想想下下一代产品。
Think about the future so that we can make it easy for the next generation product.
我前面说到自己经历了eBay的3代云计算系统,其实我也在思考, 为什么总是搬来搬去一直忙忙碌碌? 去年9月份去美国出差,我和Tess HRT的架构师CY,Tess的总架构师Aswin,还有eBay基础架构工程的副总Rami在一起讨论如何用In-place Replacement的方式把VM 从Openstack 切到 Kubernetes 上。Aswin和 Rami 说, 我们并没有减少eBay的技术债,而是在让这身债一代一代往下传。
回来以后我就在想这个问题,我发现ODB 迁移到 CMS 最大的贡献就是把eBay 在ODB 上积累了 10年之久 的系统都梳理了一遍,去掉了很多技术债,技术更新也是这样。我们的循环就是如此,因为开发了新系统,所以需要迁移老系统, 但迁移老系统的首要问题不是如何迁移,而是看哪些在老系统上的应用可以先干掉 。先把方便迁移的迁移掉(比如已经是Cloud Native云原生的应用),然后公司投入大量人力物力去手工迁移非云原生的应用(而不是把这些应用改造成云原生应用)。这种手工迁移对基础架构部门和业务开发部门都是很重的负担,而我们又把这个负担一代一代地往下传,导致大家总是忙忙碌碌,还没有尽头。
所以说,迁移的核心其实并不在于新系统,而是在于这些不方便迁移的应用。如果我们不在真正的核心上投入力量,那这样的循环还将继续下去。比起改造那些不方便迁移的钉子户,做一个新系统其实是相对简单的。业务也已经很忙了,怎么在考虑了业务的负担的同时完成迁移才是挑战。我们公司这么多优秀的人才,为什么这个包袱还在一代一代往下传呢?这就当课后作业吧,促使我们多思考。
不要执念于当前的想法,相信总会有更好的方式。
Don’t get married to your ideas,someone will always find a better way.
之前我推荐大家看《精进,如何成为一个很厉害的人》这本书,书中一直提倡要追求更优方案。这种追求说来简单,但现实中并不容易。因为在真实的世界里,如果一个人一直坚持自己的想法,那么在结果出来之前其实是很难区分这人到底是“执念于自己的想法不够开放”还是“坚持自己的想法,力排众议最终成功”的。从某种程度上来看,甚至还有点“唯结果论”的意思。但更优方案的追求肯定是值得提倡的,这也是大势所趋。
我觉得 Altus (eBay内部的应用管理产品)的核心价值之一就是越简单越好,不要暴露后面的诸多细节。可也有人觉得你为什么要藏着掖着,我们的客户就是应该知道一切。那么到底谁对谁错呢?我倒是不纠结于此,Lyric(eBay领导力转型教练)曾跟我说, 人们总在寻找更厉害的武功秘籍,但或许世界上的武功并无所谓的优劣之分,最终的结果更多取决于谁能把自己现在的武功练到极致。 PAAS的架构师Jonathan 曾经给我提过一个醒,他说我们可以坚持自己的想法,但是不能把自己封闭起来,应该抱着开放的心态去看一下外面世界发生的事情,然后客观地做一个评估,取其精华,舍其糟粕。
如果已明确当前方案不可行,就“快速失败”吧。
Fail Fast when there is evidence that it is not working or is not going to work.
话是这么说,可当抉择摆在面前,谁又能分得清自己的坚持是“固执己见”还是“远见卓识”呢?若把时间放长,谁又能说得清到底是成功还是失败呢?现实世界里其实也没有那么多的“明确当前方案不可行”, 更多的是已经产生大量的沉没成本,放弃还是不放弃,作为组织领导你得做决定,你得担责任。越是能够提升组织效率的决定,越痛。
数据驱动。
Be data driven.
在启动项目时,光说道理却没有数据支撑是没用的。很多时候不要拍脑袋拿需求。如果你想做某个Feature,但是这个Feature 并没有排上优先级,你准备怎么去谈呢?我建议你直接去找客户,而不是先去跟领导说这个Feature 有多重要。你可以列一个表,列出所有需要这个Feature 的客户名单,以及如果没有这个Feature,会对客户产生什么样的影响。
除了在启动项目的过程中要做到数据驱动,做系统时也应该这样。我们部门2年前做云计算平台的超售,为公司节省了 1000万美金 ,这就是完全数据驱动的项目。(详情请点击: 我们如何为eBay数据中心节省1000台服务器? )eBay很多内建的系统刹车保护也是基于数据的,如果某个负载均衡器上操作的错误率明显上升,我们就对这台设备实施断路(Circuit Break)。这一思路也可以用在 Kubenetes节点上。
前面说到Rami 对我们的要求是往深层工程设计方向转型,写到这里我觉得除了工程设计需要深层化,我们的思考也需要往深里走。监控组架构师Huai有一次在劝我不要过于冲动乐观的时候说:“ 不要只看我们有多少人,而要再仔细分析一下,到底能有多少人可以在系统出问题的时候深入进去,解决那些难以解决的硬骨头。 ”大不等于强,我们在生活中也需要明白这一点,要有独立的见解,而不能人云亦云,要带着支持的心去反对,为的是更好的支持。
一切皆可测量。
Instrument Everything.
其实我觉得并不一定需要“Instrument Everything”(把一切都可测量化),毕竟打蛇打七寸。但我们得要有这个能力,在需要的时候能够“Instrument”。我们SRE 部门的Eric 在线上Java 应用问题排查上有很多一手的经验,去年出了 SRE排查6篇连载 (详情请见文末链接);Tess HRT组的CY对内核级别的系统调优和问题排查也有很多经验。他们都会于今年将自己的这些经验写进系统。
去年我们公司还做了Linux Kernel 一周的培训,其实我觉得培训本身中规中矩,但是为了能够让培训的效果更好,CY 找了5个线上的实际问题给参加培训的同学练手。然后我们再做内部分享,每次分享都是2个小时,效果很好。这让我觉得我们部门在这个方面已经不是只有一两个人可以做系统和内核级别的问题排查,而是有一批人有这个基础。
一开始就要对你的系统设置可见性。
Have visibility into your system from day 1.
我在想Sami为什么会强调“一开始”,这可能是技术出身的高管的一种习惯吧。一个有良好习惯的工程师,会对自身有一些硬性要求,比如一开始就要有测试,有监控,一开始就要考虑运维等等。
我记得蒋旭(Kylin 和 CMS 的作者)带我们做CMS的时候,有一次给Debashis (前eBay基础架构副总)汇报工作,看到 测试覆盖率 (Test Coverage)很高,Debashis就现场让我们把Sonar的Time Machine调到项目一开始的时间。工作汇报结束后,蒋旭对我们说,幸亏他一开始就对测试覆盖率提出了严格要求。
坚韧乐观,向实现业务100%可用性努力。
Be resilient,aim for 100% availability to business.
这句话需要辩证看待,像《SRE:Google运维解密》这本书里就不强调要对业务有 100% 可用性。任何事情都是有成本的,在走向100%可用性的道路上,越接近终点,每增加一点需要的投入就越大,这种投入不是线性增加,而是指数式飙升。所以应该要掌握好度,考虑投入产出比。
端到端的监控和告警。
End to end monitoring and alerting.
最近跟支付团队开会,他们说做测试失败的时候,由于上下游系统很多,不少依赖系统不在团队内部,所以往往要耗费很多时间去找到底是上下游哪里出了问题,这就很影响团队的整体测试效率。
其实基础架构部门内部也有类似的问题,Altus要调用PAAS,PAAS 就要调用IAAS,而IAAS 还有DNS,LB,IPAM,部署代码还要依赖Swift… 所以当Altus的定时E2E测试失败时,很难定位哪里出了问题。我们在 生产环境 中有一个更改请求(Change Request)的查询系统,当出现网站故障的时候,就会查询最近都有哪些变更,查询系统直接显示变更摘要。
那在测试环境,我们是不是也可以有类似的工具呢?公司规模大了就容易产生信息不通畅的问题,团队A 做测试出了问题,但是依赖系统众多,导致团队A 根本不知道该找谁。所以,我们要有一个专门的 Staging 环境支持团队 来帮忙定位问题。如果能在各个团队的监控之上构建AI OPS,业务团队排查问题的速度就会快很多,我们Staging 支持团队的工作量就可以大幅下降。如果定位精准,我们甚至可以直接触发引发问题的变更的回滚。 监控的目标是能够处理 十亿 级别的数据,但是只产生有限的可指导修复行动的告警。
云原生和自我修复。
Cloud Native and self-healing.
我认为这么多年来,我们在新旧云系统的应用迁移上之所以这么累,花了这么多的时间,原因有三:
第一是我们在促进云原生上的投入不够。
第二是流量切换的时候自动化验证能力不够。我们并没有一个强大的自动化验证系统能够协调流量调整,并且检查当前应用及其上下游应用的健康性,目前仍旧需要有人来盯着。
第三是业务应用缺乏CI(Continuous Integration),但本质上是缺乏测试。比如我们要升级一个操作系统,把虚拟机换成Docker,就需要业务确认。但以我们有限的人力很难把eBay所有的客户都服务好,更现实的做法是构建一个伊甸园,以我们基于Spring Boot的Raptor.IO 框架为例,把Raptor.IO的体验做到极致。那么,你只需使用Raptor.IO 来构建应用,什么技术更新、操作系统升级、安全规范、流量管理,业务部门都不需要费心,只需要关注业务逻辑就可以了。
画一张大图,明确你的产品在其中的位置。
Draw the big picture and understand what your product fit in there.
在公司里要拔高两个汇报级别来看问题。领导是信息的汇聚点,如果可以就让领导帮忙给你讲一下组织架构和产品地图。如果没有领导给你讲解,其实只要你自己想,也一定能把产品地图画出来。 当你明晰整个大图,了解上下游,就能很好地增强使命感。 而且当信息在脑子里由点及线及面以后自己就会有很多想法,积累一定时间以后就能提出超越自己产品层次的好建议,甚至可以主动调整产品地图,构建产品地图。
不要有孤岛,要与周围环境相协同。
No more silos,always aligned.
我们很难要求大家想法一致,但如果做什么事情都只能听到同一种声音反而更加危险。我内心不喜欢冲突,也不喜欢花大量时间做协调工作,特别是能预见到对方有不同意见的时候。但是做这份工作就有这份责任, 出现了分歧避而不谈,问题本身是不会消失的,还会更加严重。 与其藏着掖着大家互相猜,很多时候还往坏里猜,那不如干脆坦诚相见。我在eBay这么多年碰到的领导和同事都挺讲道理的,大家都是为了公司好。有时候让思想碰撞一下,反而能激发出更亮的火花。不过也要看准趋势,跟什么斗也别跟趋势斗,大势所趋之时,就没有必要螳臂挡车了。
运维就是工程工作。
Operation is engineering work.
产品上线后就会有运维工作。比较好的模式是, 运维过程中遇到的问题能够及时反馈回产品 ,比如DevOps 模式就很不错。很多只有开发背景的团队想要促进自动化的过程中,都会碰到这样一个问题,就是团队里没有专业领域的专家,而往往这样的专家就是运维。
好的运维凤毛菱角,因为这些运维都是线上事故培养出来的。好的运维在积累了大量线上经验以后,会用最直接有效的方式来促进自动化,提高效率,而不是简单地堆时间解决问题。
我们部门运维组的架构师Toddy跟我讲过一个思维方式,他说,当你看前人写的 SOP (Standard Operating Procedure)的时候, 要思考前人为什么会这么写,他当时是因为踩了什么坑才写了这句话,背后的原理又是什么? 只有这样去思考,再加上线上的积累,你碰到问题才不会慌,才知道怎么应变解决。如果你是一个开发出身的同学,尤其是在基础架构部门工作的,需要特别注意,自己开发的产品是不是在处理极端案例的时候足够细致。事实上,这些注意点你靠想是想不周全的,最好还是去线上学习,去咨询公司里那些一线的资深运维。
做隐形的服务。
Be invisible.
这句话我也听到很多次了,说基础架构就像水电煤,是生活的必需品,但从来没有哪户人家会担心缺乏水电煤。基础架构也是技术公司的必需品,有时候就像空气一样,好似看不见摸不着,但又无所不在,不可或缺。Suneet(曾任eBay云计算的主管)在管云基础架构的时候,提出过部门的核心价值之一就是“Just Works”。(当时一共提了四个核心价值:Customer Focus, Simplicity, Just Works 和 Engineering Excellence, 我现在经历了一些事情以后越发觉得有道理。)
但是我们的团队成员不能隐形,要每天使用自己的产品,经常坐到客户中去看看怎么样才能使得我们的体验更加无缝。Sean(Altus 和 PAAS 的研发经理)曾经跟我说,Karthik(美国总部分布式防火墙的高级总监,现统管云计算和分布式防火墙)会看每一个Sentinel(eBay分布式防火墙)的Support Ticket。我觉得Karthik能坚持下来不容易的。
所有的服务都是云服务,带集群管理。
Everything as cloud service/cluster management.
基础架构部门其实就是一家私有云公司。我们有很多产品,但这些产品不是孤立的。客户若想使用这些产品,不应该发送支持请求(Support Request),而是应该像在公有云里使用其中一个功能一样能够自主完成。
如果是做流量管理,我们的工作模式就不应该是每天处理客户的Ticket,而是去提供流量管理服务让业务团队使用,甚至做到业务团队都不需要关心流量管理。 如果是做安全 ,前面提到的Certificate,Key,Secrets 的服务客户就不应该有使用壁垒。我们的Messaging 服务,我们的监控,我们的数据分析…这些都作为我们私有云的能力提供出来。而且这些云服务不是像切好的豆腐块一样一块一块孤立的,我们应该结合eBay 自身业务开发的情况来做方案。 基础架构部门如果不能量化,不能提高业务开发效率,那就永远也摆脱不了成本中心的位置。
做客户需要的产品。
Build for your customers what they need.
这是一句不能再白的大白话,Sami 却在他给我们做的技术分享中专门提了出来,而且还放在挑战里提出来,我觉得值得深思。 到底是做我需要的产品还是做我的客户需要的产品? 大家有空可以思考思考。
赋能你的业务,不要做业务的绊脚石。
Enable your business and don't be a blocker.
不知道是否有业务部门把我们看作过“绊脚石”。不过,如果我是业务部门,要是有人让我不停地做迁移、打补丁,底层硬件坏了说我的服务不够云原生,每隔一段时间还要我变更密码,耗时耗力申请容量…那我也受不了。我业务要是想做一个促销,你们技术的也不要跟我说撑不住。
总的来说,我觉得做基础架构的人需要主动去了解业务部门的困难。我们不缺技术好的人,但是基础架构的同学跟业务开发的紧密程度真的不够。多年前我和一位基础架构部门的高管一起坐飞机,他要我给他提意见,我说了一些不痛不痒的话,其实那时候的我也没有什么想法。后来这位高管对我说,他觉得自己对客户体验的关注度不够。
那时候我刚转经理岗,他还送了我两句话,第一句是“追求价值,而不要追求职位”,第二句是“做经理以后一定不要丢了技术,这是一条不归路”。
跨区域部署,公有云部署 。
Geo Distribution and public cloud deployments.
公有云部署我们实践得不多,但是Tess(eBay内部下一代云平台)的愿景中确实有这么一条,希望所有在Tess 上部署的应用都能无缝迁移到公有云。
跨区域部署方面,我们现在主要是 自建POP部署 。去年上海开始做 GBH (Global Buying Hub,全球采购中心)的项目,就是让中国买家通过eBay买海外商品。落到我们基础架构部门,首先就是解决访问速度问题,因为防火墙的存在,中国大陆到香港的Akamai 访问并不稳定。而你要使用国内CDN(Content Delivery Network)还就不能使用ebay.com的域名;美国总部也绝对不会因为一个中国的GBH 项目把www.ebay.com交给中国大陆来管理。结果还是通过在框架层识别中国大陆流量替换域名,才完成了CDN 加速。
回过头看,这个项目的基础架构实施还是时间不短的。所以,要想做到像水电煤一样开箱即用,基础架构还有很长一段路要走。前途漫漫,道阻且长,仍需行而不辍,方得未来可期。
可用性和安全性。
Availability and Security.
可用性和安全性其实是业务方对我们基础架构部门的最低要求。我已经记不清四年前Sami 用这两个基础点来做结尾时是怎么讲的了,他现在就是想强调一下基础架构部门最最根本的价值:在谈赋能业务之前,应该认真审视是不是在可用性和安全性方面给业务提供了无缝的体验,减少了业务在这些方面的负担。
我记得自己刚入职eBay的时候还是很喜欢写学习心得的,当时在 CSDN 上还写了不少笔记,后来就写得少了。Sami 这篇四年前的分享,我看过很多遍,但是一直没有真的花这个时间结合自己在eBay的经历把总结写下来,这次过年期间因为疫情,总算付诸行动。我主要是从 稳定性/正确性、扩展性、高性能、过渡和迁移、整体考虑以及未来3-5年的挑战 这六个方面展开,就设计高可靠、高扩展、高性能产品的主题进行回顾总结。希望各位同学们能有所收获,也欢迎大家在评论区进行友好的探讨。
作者简介
许健,2007年加入eBay 任搜索后端开发工程师,后从事云计算相关工作。在eBay 先后经历搜索后端架构从SPARC 到X86 转型,配置管理系统从ODB 到 CMS 转型,IAAS 和 PAAS的开发,经历eBay 云计算平台从 Stratus 到 C3 到 Tess 的过渡。现任eBay 上海基础架构部研发总监。
SRE重案调查组系列全六集:
SRE重案调查组 第一集 | 高延迟问题的罪魁祸首System.gc()
SRE重案调查组 第二集 | 挖掘应用处理变慢的“真相”
SRE重案调查组 第三集 | 探秘HTTP异步请求的“潘多拉魔盒”
SRE重案调查组 第四集 | JVM元数据区的内存泄漏之谜
SRE重案调查组 第五集 | 为什么我的服务器又双叒不响应了?!
SRE重案调查组 第六集 | 剖析Java的非常规线程死锁问题
您可能还感兴趣:
分享 | “三高”产品设计的这些坑,你是不是也踩过?(上)
一探究竟 | eBay流量管理之看不见的手
解密 | 一桩由数据洁癖引发的DNS悬案
分享 | eBay流量管理之Kubernetes网络硬核排查案例
分享 | eBay流量管理之负载均衡及应用交付
:point_down:点击 阅读原文 ,一键投递
eBay大量优质职位,等的就是你!