作者 | 李云(至简)
来源 | 阿里巴巴云原生公众号
过去一年,阿里巴巴在 Service Mesh 的探索道路上依旧扎实前行,这种坚定并非只因坚信 Service Mesh 未来一定是云计算基础技术的关键组成部分,还因需要借这一技术趋势去偿还过去所积累下来的技术债(“技术债”并非贬义词,是技术发展的固有产物),基于当下的技术思潮和最佳实践面向未来做出技术的新价值和新体验。
每当我们深入探索和实践一项新技术时,大多情形下会步入一段“无聊”时期,期间每天面对的并非技术之新如何诠释,而是如何先处理好技术债所带来的羁绊,以及务实地给业务创造新价值和新体验,通过携手业务共赢的方式推动新技术落地。本文总结了过去一年 Service Mesh 在阿里巴巴的建设成果和收获的洞察。
Serivce Mesh 作为一种平台型的新基础技术,发展过程中一定回避不了兑现(增量)价值这个关键问题。从技术的角度,很容易理解将框架思维下 SDK 中的易变内容下沉到 Service Mesh 中的 Sidecar 后,将促进中间件技术以业务无感的形式快速演进和升级,以平台化和体系化的思维替代过去“山头林立”的框架思维去进一步探索分布式应用构架问题的更优解,背后的价值并不容易被挑战。
从业务的角度,采纳新技术的关键是能解决当下的什么痛点、是否带来机器成本的显著降低、能否让稳定性有明显的提升、运维和研发效率有否变得更高,这些收益被总称为业务价值——业务视角下所看到的收益。发展 Service Mesh 很重要的一点是必须回归兑现(增量)业务价值,围绕不断兑现业务价值去完善新技术,否则很难持续拿到阶段性的成果。对于从事 Service Mesh 这类新技术建设的团队来说,持续收获阶段性成果对于维持团队士气致关重要,建设者会因为业务价值足够而能体会到“被需要”的感觉,进一步强化对自己工作价值的认可。
过去一年,我们经历了从“先做大规模落再兑现业务价值”到“先兑现业务价值再做大规模”的发展策略调整。在做大规模为先的阶段,落地 Service Mesh 被挑战的主要问题有三个:其一,增量业务价值不足,只是将 Java SDK 中已有的能力挪进了 Service Mesh;其二,资源开销不可忽视;其三,技术成熟度不够,没能让人看到工具化落地的问题定位与排错手段。当确实不能回答好这三个问题时,推动 Service Mesh 在核心应用上的大规模落地就变得非常困难,即便有公司层面由上至下的助推也收效甚微。最终,不得不将发展策略调整为兑现价值为先。
在兑现价值的道路上,恰好某些业务团队也从一开始挑战上面三个问题变成了积极思考如何借 Service Mesh 化这次机会让所在事业部的业务流量治理能力做一次重大升级。思路的转变很快让业务团队锚定了业务痛点,与 Service Mesh 共创出了新的解决方案,最终两个团队的合作关系从甲乙方变成了你中有我、我中有你的战友关系,大家一起抱团共赢。
回顾过去一年的经历,能得到的启示是:
无论什么新技术,先做出增量业务价值才能更好地落地推广。再先进的技术在没有兑现增量价值之前都只是个愿景,但愿景并不那么容易让人买单,技术落地依然要尊重市场规律。此外,新技术的成熟需要时间这是自然规律,技术成熟的过程中如果没有兑现增量业务价值,则没有业务甘愿只成为纯粹的小白鼠。
基础技术的发展不能只依靠基础技术团队的力量,业务团队以积极的心态参与寻求解决业务痛点将成为强劲的新技术“催熟剂”。基础技术团队并没有业务体感,而业务团队的全情投入就能很好地弥补这一短板,两者联合所形成的化学反应就能带来共赢的局面,合作关系也将升华至“战友级”。基础技术团队需要特别重视与业务团队合作,避免步入闭门造车的境况。
在技术进化的过程中,我们希望尽可能做到兑现价值之时业务没有任何的改造成本,这一点能很好地理解为何 Istio 推出至今采用了 iptables 做流量劫持。阿里巴巴在探索的过程中深知无侵入方案的价值,早在内部落地时采用的也是无侵入方案,过去一年更进了一步让无侵入方案支持流量透传功能。
去年初,阿里巴巴内部落地 Service Mesh 的技术方案并没有考虑百分百做兼容。因为历史原因,Dubbo 的序列化协议存在 Hessian2、Java 和其他小众的选择。考虑到 Hessian2 是主流协议,所以 Service Mesh 只对这一协议进行了支持。在落地的过程中,只要被 mesh 化的应用需要调用使用了不支持序列化协议的应用,就会直接导致该应用无法 Service Mesh 化。进一步,Service Mesh 的整体能力建设依赖这一技术点的突破,通过上量获得更为广泛的场景去兑现价值或为大规模落地打好基础。比如,运维面支持大规模就属于后者。另外,当所有应用都能 mesh 化时,最不济也能在使用了 Hessian2 序列化的链路上兑现价值,而不致于因为应用无法 mesh 化而使得能兑现价值的链路变得更短(价值被弱化)。
为此,Service Mesh 需要全面“支持”所有 RPC 序列化协议。下图示例了进一步的解决方案,图中示例了 A、B 和 C 三个应用,其中 A 是被 mesh 化了的。需要指出,Sidecar(Envoy)在原有的基础上增加了透传功能,对于 Hessian2 之外的协议只收集必要的统计信息后透传。需要补充的背景信息是,Service A 所使用的 RPC SDK 是全功能的,仍然具有服务治理能力。换句话说,SDK 做完路由所发出的包到达 Sidecar 后直接透传就能保证服务的连通性。
长远来看,对于 Dubbo 这种包含服务治理能力的 RPC 协议来说无侵入方案一定不是终态。原因在于,Dubbo SDK 需要有能力感知自己是否应工作于 Servcie Mesh 模式,在这种模式下将服务治理等职责下放给 Sidecar 去完成,从而省去 SDK 在这方面的内存和 CPU 开销。
基于此,过去一年阿里巴巴内部围绕终态的云原生方案也投入了相当的力量做建设,让 Service Mesh 能很好地与 Dubbo 3.0 一起协同工作。下图示例说明了 Dubbo 3.0 下的 Service Mesh。
在终态方案中,Dubbo 3.0 SDK 有一个重大的变化是针对 Service Mesh 改善了友好度,整体设计考虑了云原生浪潮这一重大技术趋势。与 Service Mesh 相关的主要变化是:
协议头采用基于 gRPC 实现的 Triple 协议。通过将 Sidecar 需要感知或变更的内容放到协议头中,完全规避需要对消息体做反序列化和序列化的动作,消息体采用什么序列化协议对于 Sidecar 完全无感。
具备因 Service Mesh 出现故障的容灾能力。Dubbo 3.0 SDK 具备 Thin 和 Fat 两种模式,分别对应于工作于 Service Mesh 和非传统模式。Thin SDK 下 CPU 和内存的开销将降到最低,所节省下来的开销腾出来给 Sidecar 使用。Fat SDK 模式下则具备全面的路由治理能力,当 Service Mesh 出现故障时由 SDK 负责完成服务调用路由。
Service Mesh 模式下服务注册与反注册由 Sidecar 负责代理完成。换句话说,当 SDK 工作于 Service Mesh 模式时,SDK 完全感知不到后端的注册中心,使得 Service Mesh 能最大程度地屏蔽下面的基础设施细节。
去除了 iptables 做流量劫持,SDK 直接通过本机的进程间通讯(TCP/IP 网络 loopback 或 Unix Domain Socket)方式与 Sidecar 通讯。流量劫持能力的价值在于,SDK 可以在完全不升级的情形下由 Service Mesh 完成流量治理并对业务无感,由于 Dubbo 3.0 本来就存在 SDK 升级的问题,为了在稳定性和性能上不引入新的问题而去除了 iptables。
值得强调,SDK 能回切至 Fat SDK 模式承担起 Service Mesh 故障时的服务调用路由的前提假设是:Service Mesh 与 SDK 具有基本的对等能力,确保满足容灾场景下的基本需求。长远来看,Service Mesh 的服务治理演进速度一定比 SDK 更快,如果有些功能与容灾能力相关则需要在 SDK 中再实现。当然,Service Mesh 应当系统性地保障稳定性,将 SDK 的保障能力放在单机维度而非全应用集群维度。
最后,正如前面所提到的,Service Mesh 的发展是需要业务方参与的,通过解决业务痛点去更好地牵引新技术落地。但凡为了解决业务问题,则一定程度地存在业务改造的需要,进一步表明无侵入方案无法从始至终地支撑好业务价值兑现这事。换句话说,准备落地 Service Mesh 的业务方,不应当将引入 Service Mesh 是否存在业务改造当作是一个核心考量点。业务改造从来都不是问题,问题在于改造有没有解决业务痛点、有没有让技术升级到更高的层次为将来业务的发展打好基础,而这一点本来就是业务落地 Service Mesh 时需要认真思考的。当然,就我们的经验来看,通过无侵入方案让业务无感试水 Serivce Mesh 是非常推荐的实践。对于同行来说,如果你所在的企业在探索 Service Mesh 或云原生相关技术,同时需要兼顾新老应用的连通和向新技术的渐进式演进,那到无侵入方案会是一个很好的过渡选择。
刚过去的一年,Service Mesh 在阿里巴巴内部找到了二大增量业务价值兑现点。随着建设工作将在接下来的几个月全面完成,将迎来 十万级应用实例的大规模落地。
增量业务价值兑现点之一,将国际化中台当下的区域化和多租路由治理能力下沉至 Service Mesh,实现流量路由治理统一和应用级机房容灾。过去,国际化中台的 Java 应用是以 Annotation 的形式去指定应运用的路由策略,但凡需要变更路由策略就得做代码修改并重新将应用发布上线,整个过程相当周折。还有,国际化中台的容灾只能做到机房级别,切流时需要将整个机房的流量全部切走。
引入 Service Mesh 后,将 Java 应用中通过 Annotation 指定路由策略的能力完全去除,通过下放到 Service Mesh 中以配置化的形式实现,使得每一次应用路由策略变更只需动态下发新的 YAML 文件即可,完全做到了与应用彻底解耦。进一步,由于路由策略是应用维度的,可以方便地以应用为颗粒度做机房间切流,提升了容灾的敏捷性和降低了切流风险。
国际化中台作为业务方,与 Service Mesh 团队抱团探索业务价值的过程中非常积极主动地思考如何最大程度地发挥这次难得的技术升级机会。将过去存在单点服务治理能力的组件全面放到 Service Mesh 的 Sidecar 中以分布式的形式完成,不仅卸下了过往的运维包袱,还让整体的业务稳定性向前迈进了一大步。
增量业务价值兑现点之二,将 Service Mesh 灵活的流量治理能力运用于新零售事业群的开发环境治理,根据开发同学的需要动态创建相互独立的开发环境。为了支撑好开发工作,阿里巴巴内部的实践是搭建了与生产环境完全独立的日常环境,将线上的应用部署到两个环境中用于每一个应用的开发调试工作。在日常环境中的每一个应用都可能因为开发的需要而进行变更,为了解耦应用间的相互影响又进一步在日常环境中又建立了基线环境,每个应用的开发工作都得基于基线环境所隔离出的开发环境完成开发工作,而不能直接将基线环境用于开发联调。当应用数和开发人员的数量都数以万计、每天的应用变更数数以千计时,如何保障好开发同学日常所需的开发环境就是很有挑战和很有价值的一件事。
由于过去的开发环境隔离技术是基于框架思维去设计的,需要不同的流量(比如, RPC、消息、缓存和数据库)从协议层面去对接同一个隔离框架,演进与维护相当困难。当存在多语言场景时,主要围绕 Java 语言构建的能力就使不上劲。另外,在没有 Service Mesh 这样的平台技术出现时,有些隔离场景相当难实现。
Service Mesh 的价值在于,其天生就是为了流量治理而生,动态且灵活地完成流量的隔离与路由是核心能力之一。我们对 Istio 中的 VirtualService 和 DestinationRule 进行了扩展,抽象出了 TrafficLabel 这一全新的 CRD,通过下发 YAML 文件动态地对流量和应用机器进行打标,Envoy 则基于流量标和机器标进行路由,从而做到灵活又快速地构建出开发同学所需的开发环境,且能很好地支持多语言应用。下图示例说明了 Service Mesh 下,同时开发 v1.1 和 v1.2 两个版本时的应用部署和流量拓扑。
上图中,需要下发 YAML 文件对特定的流量和应用进行打标。Envoy 则根据流量标将流量导到打了同样标的机器上,当对应的标并没有机器时,则运用回退机制让流量回流到基线环境中。比如,开发环境 1 中的应用 B 调用应用 C 时,由于找不到打了 tag1 的机器则直接将流量打到基线环境。
可以预见,Service Mesh 所构建的这一能力为将来探索 Test in Production 打开了一扇门。未来基于 Service Mesh 所构建的流量隔离环境将有助于节约搭建独立开发环境所需投入的机器成本,也为探索新一代的安全生产环境提供了新思路。当然,在这条路上我们任重而道远。
截止本文完稿之时,阿里巴巴集团内部 Service Mesh 的落地规模已达数万应用实例。数据、控制和运维三大平台的能力建设完全做到了具备大规模运用水平。
作者借此机会分享自己所理解的软件生命周期理论,希望在云原生这一难得的技术浪潮之下该理论有助于读者更好地看待新技术的发展并在这个过程中抓住机遇。
以静态的思维看待软件开发,极有可能最终导致所获得的软件是一个臃肿、易出错的包袱。出现这种状况的原因,是因为没有明白软件是存在生命周期的。软件也象人一样,存在形成、成长、成熟和衰退四大时期(如下图所示)。图中纵座标代表软件对新需求的适应能力,指软件对实现新需求的友好度,背后是概念与概念之间的关系是否清晰、让人对其的认识是否符合直觉与常识,本质是指软件的设计质量。图中的直线也只代表一种趋势,现实中更多地表现为存在波动的曲线。
软件进入成熟期的标志,是其功能实现程度与当初的定位和使用场景契合。进入衰退期是因为业务发展的需要而出现了新的场景,此时软件的概念抽象(又可以称之为“架构”或“主导软件设计”)对于实现新场景下的需求并不友好,导致新开发的代码变成了“贴狗皮膏药”。软件长期处于衰退期的副作用是,软件质量持续变差,开发同学的编码体验不断下降。
理解软件生命周期的另一种视角是,软件工程师对于需求的理解是随着时间逐步加深的,很难出现最初的软件设计能满足业务发展的长期需要,毕竟业务也是一天天变得复杂起来的。换句话说,软件进入衰退期是不可避免的,而技术债也是软件发展的自然产物。
走出衰退期的关键是需要让软件进入新一轮的生命周期,而最直接的办法就是“还技术债”,其中包含了重构、或用全新的思路与新技术去解决问题。从小处说来,工程师通过持续重构去还技术债是真正锻炼能力的时候,这个过程会基于个体对业务(或需求)的理解做重新的概念抽象,掌握良好的软件设计能力正是从这些“小处”习得的,也只有具备良好软件设计能力的工程师才有可能驾驭大型软件系统的设计。
软件生命周期理论告诉我们,一个好软件并非一直能保持不变,而是能经得起各种改变。当然,各种改变的背后需要以工程能力做支撑,全面通过单元测试、集成测试、系统测试等手段去保障软件的质量,一旦缺失了这些手段就很难建立起对改变的信心,也最终会趋向于固步自封地不变。
对于类似 Service Mesh 这样的平台型技术来说,都需要非常小心地应对软件生命周期理论。平台思维是为了解决通用问题,在通用和定制之间找到平衡。当平台技术自身并不能很好地适应技术或业务发展的需要而快速演进时,自然将成为业务发展道路上的阻力而非助力。
接下来的一年,我们将持续地探索 Service Mesh 的价值,在兑现 RPC 流量治理价值的同时,完成 RocketMQ 等的 Service Mesh 化,进一步延展 Service Mesh 的流量治理能力并兑现更多的增量业务价值。
我们致力于解决阿里巴巴内部基础技术的 Service Mesh 化,因为以阿里巴巴自身的业务规模来看更需要 Service Mesh 。接下来,我们也将与更多业界同仁进行交流,期待通过分享所收获的经验与客户手牵手坚实地进入云原生时代。
如果读者有交流的需求,或者希望成为阿里巴巴 Service Mesh 的建设者之一,请来信至 [email protected]。