2018 年 6 月 27 日,Apache ServiceComb 在北京举办主题 Workshop,当中,来自华为消费者云的架构师分享了《ServiceComb 在华为消费者云的亿级用户微服务实践》,以下为演讲实录。
讲师介绍:
李专家,华为消费者云应用市场微服务架构师,多年平台中间件、云平台、微服务框架设计和开发经验。工作之余爱好技术写作,《Netty 权威指南》和《分布式服务框架原理与实践》作者。
今天分享主要有三个主题,第一个就是服务化的总体策略,第二个是服务化实践,最后就是业务微服务化以后得到的收益。先自我介绍下,我最早是做业务的,后来从业务转到平台中间件团队做各种平台,包括:短信网关平台、SOA 中间件、PaaS 平台等。现在在华为终端消费者云业务做云化和微服务化相关架构设计。从业务到平台再回归做业务,感觉还是蛮有意思的。
关于华为消费者云服务
简单介绍一下华为消费者云服务,它包括我们经常用到的华为手机应用市场(类似于苹果的 APP Store),还有我们的智能助手、云空间、天际通等。当然还有一些生活服务相关的,例如视频、音乐、阅读等,这些都属于华为消费者云服务的范畴。我所在的华为应用市场目前是世界第三大应用市场,在全球一百多个国家(支持 70 多种语言)上线运行。
顶层统一设计
今天分享的服务化策略不仅仅单指华为应用市场,还包括了整个华为消费者云服务业务的服务化策略。首先我们看一下整个策略,华为消费者云服务的规模是非常大的,有很多个业务和产品。我们在做服务化设计的时候,最大的一个挑战就是如果能够从顶层统一设计,当一个小团队做服务化的时候,可以采用自底向上的策略。有些技术很强的骨干做技术选型,然后大家就用起来,反正团队人少,业务量也不是很大,最终效果可能还不错。但对华为消费者云服务来说有非常多的团队和业务产品线,如果没有顶层的统一设计,就会造成技术架构选型不一致,这对一个大公司来说成本是非常非常高的。假如要构建一条微服务 CI/CD 流水线,就要支持所有业务线的所有的异构服务框架,成本很高。因此对于一个体量非常大的业务,一定要有一个顶层的统一设计。我们的技术选型是由架构部跟各个业务产品线设计部一起来完成。
这里面比较重要的一点就是顶层统一设计的理念要能够标准化、规范化和工具化,前几年我们也在电信领域做运营商各个系统服务化时,发现在一个大的业务团队去做服务化时,有些架构仅仅存在于架构师的脑海里,下面的整个团队其实并不了解整个服务化的设计理念和思路。这会导致大家认为你是在强推一些东西,或者因为不理解导致实现时走弯路。当大家带着疑问被动去做服务化时,会造成整个团队的割裂,服务化的效果也不会很好。所以在我们设计之处,整体由架设体系来牵头,完成微服务规范的制定、协议选择、流水线建设,以及微服务治理、上线和验收标准。
还有一点比较重要的就是组织赋能,因为业务团队是非常大的,业务线又很多,所以要把我们整个服务化的选型以及架构的设计理念,包括我们整个的开发、测试流程以及一整套的 CI/CD 流水线都是要向设计、开发、测试还有我们的运维人员去讲解。让大家能够充分理解顶层设计和架构思路,防止实现时与架构设计不一致。
最后一点就是微服务上线以后,有个服务化地图,就是从组织架构层次来审视和管理微服务,它会包含微服务的 SLA 指标、微服务流水线地址、微服务重要的治理参数设置、以及微服务业务模型等,方便从更宏观的视角来管控上线的微服务。
没有十全十美的微服务架构,适合的才是最好的
选型其实非常非常重要,很多人向我咨询微服务框架选型问题,我也看到很多团队在纠结这个,想选 SpringCloud,又感觉 gRPC 不错,非常纠结。其实对整个服务化选型而言,最重要一点大家一定要明白,就是没有十全十美的微服务架构。现在所有开源出来的,不管是哪个厂商或者组织,都会有优缺点和适应场景,所以说大家不要去陷入一种脱离业务的争论,这种争论其实也会走偏。对我们而言,选型其实也是非常谨慎的,就个人经验,在来华为消费者云服务之前,已经在电信领域做过 3 到 4 年的服务化,所以很清楚业务需要什么样的服务框架。只有真正的理解业务的需求,才能够做出好的技术选型。
内外 API 一致,支持多种服务开发方式
选 ServiceComb 的一个重要原因就是 API 的统一和标准化:我们希望微服务内部的 API 以及对外的(例如对手机端和华为手表,以及对各种各样的设备),API 保持一致,方便管理。遵循 Open API 2.0/3.0 规范也就是支持 Swagger API 规范的 Restful API 是非常容易管理的,所以我们这次就果断地选用了 Rest API 而没用 RPC 私有协议承载 API。微服务的开发方式问题:我们在做微服务化之前,不同团队技术堆栈不同,有用 Spring MVC 的,也有用 Spring Cloud 的,还会有一些其他的微服务框架(比如透明 RPC 方式),我们希望微服务框架能支持多种开发方式,降低业务适配和学习成本。
轻量易集成
对于集成,我们倾向于微服务框架支持轻量级的集成。我们现在做微服务化,以重构为主,有一些微服务跑在 tomcat 容器里,有一些业务做的不太好,绑定了 Web 的一些技术,因为改造量工作量比较大,所以这个时候希望微服务框架能集成在 tomcat 里面跑。还有一些是纯后台的业务,不想部署在 J2EE 容器中,可以更加轻量的部署在 Docker 容器里面,可能 2C4G 的资源就能跑起来。 ServiceComb 支持 vertX 的 standalone 方式(纯后台),还支持跟 tomcat 这种 Web 容器集成,正好可以满足我们的业务场景。
ServiceComb 的轻量级主要体现在两点,第一个就是开发态可以按需引用。假如没用流控,就不需要引流控 handler,业务可以做到 ServiceComb 的最小化依赖,减小二方库/三方库冲突的风险。第二点就是支持 standalone 模式,不依赖任何 Web 容器,对于纯消费端应用,甚至不需要启动监听端口,它的启停速度非常快,特别适合云化之后的容器化部署以及弹性伸缩。
API First —“大家只认接口”
我们服务化的一个很重要实践就是 API First 的落地。不仅仅使用 Swagger 在线管理 API,还有就是服务端和消费端各自基于 API 定义生成接口和模型,消费端不导入服务端的接口定义类库,实现代码解耦。测试基于 API 定义生成自动化测试用例(API Test),防止开发人员绕过在线 API 定义私自修改接口(一旦有不一致修改,接口测试就失败)。设计、开发和测试都只遵循在线的 API 接口定义,就防止了接口文档与代码、测试用例与代码之间的不一致。
开发模式的选择
还有一个就是开发模式,其实开发模式没有好坏之分,像以前我们在做电信服务化的时候,喜欢用透明 RPC,消费端会导入服务端的接口定义类库。但是现在在消费云这边我们用的更多是 Spring MVC 注解,因为业务团队用 Spring MVC 的比较多,ServiceComb 对 Spring MVC 开发模式是天生支持的,因此改造成本非常低。
我们有些团队以前用的是我们电信软件做的支持电信级的高性能私有的服务框架 DSF,更喜欢透明 RPC 开发模式。当然 JAX-RS 风格的接口也有。开发模式没有优劣,但是有一点需要强调的就是一定要考虑到开发成本,因为对一个重构项目而言,业务需求要做,还要同时做服务化重构,需要考虑各种成本,包括学习成本、代码重用成本等。
凡是说性能不重要的都是性能没做好
很多时候大家说云时代或者硬件白菜价的时代,软件的性能就不重要了。但事实上没有哪一家的产品不把性能作为微服务框架竞争力的,所以大家不要相信所谓性能不重要之类的言乱。业务当前不需要这么高的性能并不代表未来也不需要,尤其对于快速发展的互联网业务,如果选型了一个性能不行的架构,后续横向扩展成本会非常高。按照经验,凡是说性能不重要的都是它自身的性能没做好。衡量性能有三个要素:1.吞吐量(QPS)2.时延 3.架构平滑扩展能力。
异步非常重要
关于线程模型,最重要的一点就要支持异步。像 gRPC 对异步的支持就非常好,它是基于 http /2.0 Stream 设计的,http/2.0 Stream 支持多路复用,加上异步 I/O,很容易构建异步 RPC。当前大部分的服务框架不支持异步或者对异步支持不够好,比如有些会返回一个 jdk 的原生 Feature, 很难做比较强大的异步处理。架构原生支持异步是非常重要的。
今年是微服务异步化的元年
以前大家都倾向于先用同步的方式做服务调用,但是上线后发现 CPU 等资源使用率不高但是性能也上不来,原因是什么?都是同步阻塞式调用惹的祸。异步改造之后,会把大量的资源节省下来,能把机器的 cpu 和带宽压上去,提升资源的使用率,降低业务的硬件成本。
这里澄清一个概念,微服务框架的异步跟 I/O 的异步是没有任何关系的,举个例子,Tomcat 从 5.0 以后就支持 NIO, Servlet 规范从 3.0 才开始支持异步。在此之前,Tomcat 的通信 I/O 是异步了,但是整个 http 调用是同步的,原因就是 Servlet2.X 系列接口本身就是同步的。同步服务调用主要有三大缺点:
①资源利用率低。
②超时时间比较难设,设置大了容易挂住,设置短了容易超时,比较纠结。
③雪崩效应,如果你的整个调用链上都是同步的,下游节点慢了就阻塞上游,会导致整个调用线程都被阻塞,形成雪崩。
我们业务的异步并没有一刀切,因为切异步是有成本的,适合异步的业务才需要切异步。比如说应用分发下载,每天全球有数十亿次的下载或者更新,并发量非常大,而且下载经常集中在某个时间段,流量高,针对这种这种场景就可以做异步优化。
适合异步的场景
异步的主要场景有四个:
①降低长流程/复杂业务流程时延:消费端需要调用多个微服务,进行业务逻辑编排,多个微服务之间没有执行先后顺序和参数依赖,可以并行执行。
②性能提升,使用更少的线程处理更多的消息,减少线程的等待时间。设别适用于一些时延敏感型业务。
③服务上对服务调用时延不敏感(例如 1-3S),如果采用同步调用 + 大超时时间,在业务高峰期,如果时延达到超时阈值,系统很容易被压挂。(单个线程 3S 完成一次服务调用)。采用异步,则可以按照业务实际要求设置超时时间,不用担心线程资源被挂住。
④需要调用多个微服务,希望提升可靠性,不会因为某个微服务处理慢而导致其它微服务调用、以及后续其它业务消息被阻塞,则可以考虑使用异步服务调用。
异步的收益与挑战
业务采用 Reactive 异步以后带来的收益还是比较大的,带着业务实测性能提升 40%多,时延降了 30%左右, CPU 使用率下降 56%,综合性能收益约为 2-3 倍。业务要做全栈异步实际是非常困难的,会遇到各种挑战。纯 Reactive 就意味着在整个调用链上不能有同步阻塞操作:
①同步访问数据库、redis 缓存或者对象存储服务。
②同步的磁盘 I/O 操作。
③调用第三方 SDK,SDK 提供的是同步访问接口(例如 HttpClient)。
④业务代码的意外阻塞,例如 sleep、wait 或者长时间的锁等待。
第二个难点是异步过程中的上下文的传递,因为大家以前同步写代码的时候,总是喜欢通过类似 ThreadLocal 线程变量来传递上下文。采用异步之后,只要有线程切换,就要考虑到线程上下文可能会丢失的问题,例如调用链的 Trace ID。第三个问题就是异常的传递,同步调用发生异常可以直接在当前调用线程 try catch 捕获并处理异常。但是当异步切到另一个线程发生异常时,异常是很难传递到调用方线程的,调用方如何更好的处理异步代码块里面抛出的异常,是个难点。最后一个难点就是异步超时控制机制,线程切换之后,超时控制就非常困难了,很多情况下你无法通过调用方超时去中断异步线程的执行。
做全栈异步的挑战还是蛮大的,这个不仅仅是微服务框架本身要支持,而且中间件、第三方调用等都需要支持异步,才能达到较好的预期效果。由于 Vert.X 提供了一个异步生态系统,包含了各种常用开源中间件的 SDK,因此基于 ServiceComb 的异步微服务框架 + Vert.X 的各种异步 SDK 构建全栈异步系统,相对比较容易一些。
关于回调地狱
由于接口模型的原因,一些异步框架容易出现回调地狱, ServiceComb 当前实现的是 JDK 8 Complete Feature,它支持异步操作结果可编排、可组合。这个类库里面提供 60 个左右常用的方法,每 3 个一组,实际 20 个常用的异步接口,可以指定线程池,活着使用 jdk 的 Fork Join Pool,也可以直接在当前线程执行。它具备类似 BPM 的一些对异步结果做编排的能力,例如对多个异步操作做 Join、或、与等,也支持条件判断。异步接口的参数大部分是 jdk8 的 function 接口,业务可以直接写 Lambda 表达式,避免所谓的回调地狱。
接口级隔离舱支持
还有一个故障隔离,以前我们做的,比如说 Tomcat、Spring MVC 架构。如果用同步 Spring MVC 它的后台用的是 Tomcat 的 Work 线程,就是应用在 server.xml 里面配置的 Connector。如果某一个接口或者某个服务慢了以后,它可能会导致整个线程池都被阻塞,这对业务来说是不可接受的。通过 ServiceComb 的隔离仓技术,可以把快慢不同接口、核心和非核心类接口、管理和租户面接口区分开进行线程池隔离。通过不同维度的隔离舱来实现当某个接口慢或者出了问题以后,把故障严格封闭在某个隔离舱内,防止故障扩散。ServiceComb 的隔离仓支持微服务级、接口级和方法级,支持业务自定义隔离线程池,使用起来非常灵活。
微服务治理
基于 ServiceComb 提供的服务治理功能,业务重点构建如下两大能力:
①线上自动化运维:服务状态检测、容量管理、基于大数据分析的自适应调优、故障诊断、弹性伸缩、故障自动重启、在线迁移等。
②微服务的自治理:服务无状态设计,故障自动切换,Failover 失败自动重试 , 故障隔离、大数据分析自动展示系统关键路径、调用依赖画图等。
微服务化带来的收益
以 ServiceComb 为核心构建的业务微服务体系,本质还是为了提升业务的研发效率。具体提升点如下:
①上线效率提升:以前业务都是一个大版本(超级 war 包,也就是所谓的巨无霸的业务),现在拆分成微服务之后各个微服务之间只有 API 契约依赖,各个微服务独立发版本,迭代周期更快。例如推荐系统服务化之后,各种推荐算法和策略就可以更快的上线验证和优化。
②全自动化的微服务流水线:基于 ServiceComb 业务建立了一套涵盖个人、团队到项目组级别的微服务流水线。每个开发测试都有一套自己的微服务的流水线,这个是个人级的;我们还有微服务团队一级的;业务最终要上线,还是要大家的微服务集成在一起,所以还有个整个项目集成级的流水线。利用微服务流水线,从架构师开始设计 API 接口、到开发态的静态检查、编译再到打包部署、灰度发布,自动化测试,直到最终微服务上线,全部都是自动化的。
③精细化运维能力提升:利用微服务调用链可以快速的识别业务的关键路径、热点、故障点以及接口依赖,针对特定的故障场景,可以通过服务治理、弹性伸缩、代码架构优化等来保障微服务的高质量线上运行,提升运维能力。
以微服务架构为牵引,我们构建了一套适合终端消费者云业务的微服务化体系和团队,通过更好的架构来支撑消费者云业务的全球化发展,为华为终端用户提供更好的服务和体验。
本文转载自 华为云产品与解决方案 公众号。
原文链接:https://mp.weixin.qq.com/s/Px69FJBDsHF2yfe7v3rpFg
评论