视频地址:https://time.geekbang.org/dailylesson/detail/100033220
(给极客时间做个免费广告:上面这个视频来自极客时间的《每日一课》。最近一段时间开通极客时间企业账号可以免费享受两个月的《每日一课》服务)
这个技术视频是介绍淘宝是如何落地全异步化技术,以及获得的收益,还有关于自适应负载调节方面的内容。完整的 PPT 可以在这里(https://www.infoq.cn/article/P1S7UOYH-pQZWa53zSJL,文章末尾)下载。
一、内容大纲
下面是我总结的这个技术视频的内容大纲:
- 实施全异步化改造的效果
- 全异步化改造的背景
- 全异步化的技术选型
- Reactive 技术的选型
- Reactive 技术的落地难点及解决方案
- 全异步化的延伸:负载自适应
二、具体内容
接下来大致介绍一下视频的内容,其中会加入我的解释、看法和思考。
1. 全异步化技术实施效果和背景
首先介绍的是淘宝在实施全异步化改造后的效果。最先看到的是 RT 的降低和 QPS 提升。全异步化在平时不会降低 RT、提高 QPS。但异步化有助于提升系统的两大能力:Elastic 和 Resilient,前者反映了系统应对压力的表现,后者反映了系统应对故障的表现。在大促时,系统会承受更大的压力、遭受更多的故障。在这种情况下,全异步化的系统会表现出比传统同步方式的系统有更低的 RT、更高的 QPS。
除了提高资源利用率和并发能力,全异步化还能实现链路上下游的故障隔离。
2. 全异步化技术选型和落地
如何实现全异步化?Future、Callback 都是老技术,不完美。Future 在异步方面改变有限,Callback 在编排能力方面有 Callback Hell 这样的严重短板。Project Loom 愿景很美好,但距离发布还有好几年的时间(不能说跳票,毕竟也从来没宣布什么时候发布)。目前实现全异步化最理想的技术就是 Reactive Streams(https://www.reactive-streams.org/)。
淘宝选择 RxJava 实现 Reactive。最大的原因我猜是 RxJava 技术出现较早。如果我现在选择,会更倾向于 Project Reactor。毕竟最近两年 Netflix 将很多开源技术停止了维护,所以选择一个由成熟强大的开源社区维护的技术更有利于长远发展。至于稳定性和普及性,这两年随着 Spring 5 和 Spring Boot 2 的成熟,以及整个 Spring 技术生态全面支持 Reactive,也不会是问题。
但技术选型只是第一步,落地实施 Reactive 有非常多的困难。困难分两部分:技术和推广。
技术难点
先说技术方面,落地 Reactive 主要有如下几个难点:
- 中间件改造:如何是 RPC、MQ、链路跟踪、数据库等中间件支持 Reactive 技术
- 线程模型:统一管理线程设置
- 防止线程阻塞:阻塞 Reactive 核心线程非常危险
- 上下文传递:ThreadLocal 不再有效
这四点中,我认为以1、3、4点最关键。
第一点:中间件改造
目前 Spring 帮我们做了很多,如 Spring MVC、Spring Data、Spring Security 等都已支持 Reactive 技术。但是像 Dubbo、RocketMQ、MySQL 等技术对 Reactive 的成熟支持还需时日。因此,目前落地 Reactive 的项目对所采用的技术还是有所限制。
第三点:防止线程阻塞
Reactive 技术所使用的线程数一般只需要 CPU 核心数的两倍,这也是默认配置。这样,如果一旦这些线程被阻塞,那整个系统很快就会失去响应,后果很严重。所以,在采用 Reactive 技术之后,线程阻塞要彻底避免。但是这又是一件防不胜防的事情,自己的代码尚且不容易完全避免引入阻塞,又如何避免其他人写的组件和第三方类库所引入的阻塞呢?
在线程阻塞检查技术方面,主要有以下几种:
最近 Project Reactor 提供了一个新解决方案:BlockHound 技术(https://github.com/reactor/BlockHound)。上面的表格中似乎没有提到 BlockHound,后续我会跟进研究。
第四点:上下文传递
ThreadLocal 在 Java 技术中广泛使用,缓存、事务、链路跟踪,还有很多其它技术都采用了 ThreadLocal。但使用 Reactive 技术后,上下文信息就不能在 ThreadLocal 中传递了。这方面其实主要也是设计中间件技术的改造,但也有很多业务系统直接使用了 ThreadLocal,同样需要改造。这部分工作成本不低。
推广难点
技术难点主要是中间件团队的工作,推广部分主要是业务团队的工作。要想推广 Reactive 技术,首先要让团队从上至下认识到 Reactive 技术的好处。同时,还要让直接参与改造的同学能从 Reactive 技术改造的工作中感到成就感。
这里我认为一个比较合适的切入点是全链路压测和全链路故障演练。通过压测和故障演练,我们能找到系统目前所存在的瓶颈和问题,针对这些瓶颈和问题,通过实施 Reactive 改造,让大家看到收益。这样可为 Reactive 技术改造铺平道路。
思想上铺平了道路,还有其它难点。其中最大的难点是 Reactive 技术对业务逻辑不友好。这方面在我之前的文章中有介绍。其中一个解决办法就是引入 Kotlin Coroutine 技术。
3. 自适应负载调节
即便实施了 Reactive 技术改造,提升了系统的资源利用率和弹性,实现了上下游故障隔离,但在硬件条件不变的情况下,系统能力终归是有限的。这便是我们为何要做全链路压测的原因。在大促来临之前,我们需要通过全链路压测得知系统的瓶颈在哪里。但事事难料,大促实际流量总是很难估计准的,换言之就是不确定性。
这些不确定性综合在一起,使得资源评估变成一个很难做好的事情。一个服务有多个接口,这些接口在大促期间流量是多少?这些接口流量的比例是多少?系统能力是多少?我应该为大促准备多少服务资源?这些服务所依赖的服务的这些情况又是如何?
上面这些问题综合在一起,当系统和业务越来越复杂之后,便会变得不可解。所以,我们需要系统具备自适应负载的能力。
接下来视频介绍的是如何实现负载自适应。
这里面最关键的是预测算法,预测算法参考了系统自动化控制相关技术,好坏可以从三个维度评估(这里照抄一下原文):
- 稳定性:有压力时,经过一段时间,CPU 最终趋于某个值附近稳定,而不是发散的
- 准确性:处于稳定状态时,CPU 的稳定性值与目标值的误差越小越好
- 响应性:有压力时,从一个稳定状态过渡到另一个稳定状态的抖动服务和时间越小越好
负载自适应,简单说就是将过去容量评估的工作变为自动化、智能化,再结合系统自动伸缩、Reactive 技术的背压、系统自动化配置等技术,使得系统对大流量活动的支持更轻松、更稳定。
如果想进一步了解负载自适应,可阅读这篇文章:淘宝如何保障业务稳定性——诺亚(Noah)自适应流控 https://mp.weixin.qq.com/s/ePWqUiZcEy52mUHb4WbcSA。
三、后记:后续思考
阿里的这个分享可以说是干货满满。From Reactive, More Than Reactive。互联网公司在面对业务的快速变化、流量压力的难以预测、故障的突如其来等种种挑战时,简单增加集群规模,配置静态的限流熔断,是无法满足业务发展要求的。这就是全异步化和负载自适应的用武之地。
回到我目前所负责的工作,Reactive 技术和负载自适应这两方面,对于前者,计划在上半年对一个业务接口进行 Reactive 技术改造。而对于负载自适应,会进行初步的思考和探索。但因为要补的课还有很多,所以具体实施计划尚不确定。