独家揭秘!阿里大规模数据中心的性能分析
    2019-02-20    郭健美

​​

阿里妹导读:数据中心已成为支撑大规模互联网服务的标准基础设施。随着数据中心的规模越来越大,数据中心里每一次软件(如 JVM)或硬件(如 CPU)的升级改造都会带来高昂的成本。合理的性能分析有助于数据中心的优化升级和成本节约,而错误的分析可能误导决策、甚至造成巨大的成本损耗。

 

本文整理自阿里巴巴高级技术专家郭健美(花名:希伯)在Java相关行业会议的分享,主要介绍阿里大规模数据中心性能监控与分析的挑战与实践,希望对你有所启发。

 

 

作者简介:郭健美(花名:希伯),阿里巴巴高级技术专家,目前主要从事数据中心的性能分析和软硬件结合的性能优化。CCF 系统软件专委和软件工程专委的委员。

 

大家好,很高兴有机会与 Java 社区的开发者交流。我的研究领域在软件工程,主要集中在系统配置和性能方面。软件工程一个比较常见的活动是找 bug,当然找 bug 很重要,但后来也发现,即便 bug-free 的程序也会被人配置错,所以就衍生出了软件配置问题。

 

很多软件需要配置化,比如 Java 程序或 JVM 启动时可以配置很多参数。通过配置,一套软件可以灵活地提供各种定制化的功能,同时,这些配置也会对软件整体性能产生不同的影响。当然这些还在软件配置方面,来了阿里以后,我有机会把这方面工作扩展到了硬件,会更多地结合硬件比如 CPU,来看系统的配置变更和升级改造对性能、可靠性以及业务上线效果的影响。今天主要谈谈我在这方面的一点工作。

 

 

阿里最有代表性的事件是“双 11”。这里还是用的17年的数据,左上角是双十一的销售额,17年大概是 253 亿美金,比美国同期 Thanksgiving、Black Friday、Cyber Monday 加起来的销售额还要多。

当然这是从业务层面去看数据,技术同学会比较关注右边的数据,17年双十一的交易峰值达到 32.5 万笔/秒、支付峰值达到 25.6 万笔/秒。对于企业来说,这么高的峰值性能意味着什么?意味着成本!我们之所以关注性能,就是希望通过持续的技术创新,不断地提高性能、同时节省成本。

 

 

双十一零点的峰值性能不是一个简单的数字,其背后需要一个大规模数据中心来支撑。 简单来说,阿里的基础架构的上层是各种各样的应用,比如淘宝、天猫、菜鸟、钉钉,还有云计算和支付宝等,这也是阿里的一个特色,即具有丰富的业务场景。

 

底层是上百万台机器相连的大规模数据中心,这些机器的硬件架构不同、分布地点也不同,甚至分布在世界各地。中间这部分我们称之为中台,最贴近上层应用的是数据库、存储、中间件以及计算平台,然后是资源调度、集群管理和容器,再下面是系统软件,包括操作系统、JVM 和虚拟化等。

 

中台这部分的产品是衔接社区与企业的纽带。这两年阿里开源了很多产品,比如 Dubbo、PouchContainer 等,可以看出阿里非常重视开源社区,也非常重视跟开发者对话。现在很多人都在讲开源社区和生态,外面也有各种各样的论坛,但是像今天这样与开发者直接对话的活动并不是那么多,而推动社区发展最终还是要依赖开发者。

 

这样大规模的基础架构服务于整个阿里经济体。从业务层面,我们可以看到 253 亿美金的销售额、32.5 万笔交易/秒这样的指标。然而,这些业务指标如何分解下来、落到基础架构的各个部分就非常复杂了。比如,我们在做 Java 中间件或 JVM 开发时,都会做性能评估。

 

大部分技术团队开发产品后都会有个性能提升指标,比如降低了 20% 的 CPU 利用率,然而这些单个产品的性能提升放到整个交易链路、整个数据中心里面,占比多少?对数据中心整体性能提升贡献多少?这个问题很复杂,涉及面很广,包括复杂关联的软件架构和各种异构的硬件。后面会提到我们在这方面的一些思考和工作。

 

 

阿里的电商应用主要是用 Java 开发的,我们也开发了自己的 AJDK,这部分对 OpenJDK 做了很多定制化开发,包括:融入更多新技术、根据业务需要及时加入一些 patches、以及提供更好的 troubleshooting 服务和工具。

 

大家也知道,18年阿里入选并连任了 JCP EC(Java Community Process - Executive Committee) 职位,有效期两年,这对整个 Java 开发者社区、尤其是国内的 Java 生态都是一件大事。但是,不是每个人都了解这件事的影响。记得之前碰到一位同仁,提到 JCP EC 对阿里这种大业务量的公司是有帮助,对小公司就没意义了。

 

其实不是这样的,参选 JCP EC 的时候,大公司、小公司以及一些社区开发者都有投票资格,小公司或开发者有一票,大公司也只有一票,地位是一样的。很多国外的小公司更愿意参与到社区活动,为什么?

 

举个简单例子,由于业务需要,你在 JVM 8 上做了一个特性,费了很大的力气开发调试完成、业务上线成功,结果社区推荐升级到 JVM11 上,这时你可能又需要把该特性在 JVM 11 上重新开发调试一遍,可能还要多踩一些新的坑,这显然增加了开发代价、拉长了上线周期。但如果你能影响社区标准的制定呢?你可以提出将该特性融入社区下一个发布版本,有机会使得你的开发工作成为社区标准,也可以借助社区力量完善该特性,这样既提高了技术影响力也减少了开发成本,还是很有意义的。

 

 

过去我们做性能分析主要依赖小规模的基准测试。比如,我们开发了一个 JVM 新特性, 模拟电商的场景,大家可能都会去跑 SPECjbb2015  的基准测试。再比如,测试一个新型硬件,需要比较 SPEC 或 Linpack 的基准测试指标。

 

这些基准测试有必要性,因为我们需要一个简单、可复现的方式来衡量性能。但基准测试也有局限性,因为每一次基准测试都有其限定的运行环境和软硬件配置,这些配置设定对性能的影响可能很大,同时这些软硬件配置是否符合企业需求、是否具有代表性,都是需要考虑的问题。

 

阿里的数据中心里有上万种不同的业务应用,也有上百万台分布在世界各地的不同服务器。当我们考虑在数据中心里升级改造软件或硬件时,一个关键问题是小规模基准测试的效果是否能扩展到数据中心里复杂的线上生产环境?

 

举个例子,我们开发了 JVM 的一个新特性,在 SPECjbb2015 的基准测试中看到了不错的性能收益,但到线上生产环境灰度测试的时候,发现该特性可以提升一个 Java 应用的性能、但会降低另一个 Java 应用的性能。同时,我们也可能发现即便对同一个 Java 应用,在不同硬件上得到的性能结果大不相同。这些情况普遍存在,但我们不可能针对每个应用、每种硬件都跑一遍测试,因而需要一个系统化方法来估计该特性对各种应用和硬件的整体性能影响。

 

对数据中心来说,评估每个软件或硬件升级的整体性能影响非常重要。比如,“双11”的销售额和交易峰值,业务层面可能主要关心这两个指标,那么这两个指标翻一倍的时候我们需要买多少台新机器?需要多买一倍的机器么?这是衡量技术能力提升的一个手段,也是体现“新技术”对“新商业”影响的一个途径。我们提出了很多技术创新手段,也发现了很多性能提升的机会,但需要从业务上也能看出来。

 

 

为了解决上面提到的问题,我们开发了 SPEED 平台。首先是估计当前线上发生了什么,即 Estimation,通过全域监控采集数据,再进行数据分析,发现可能的优化点。比如,某些硬件整体表现比较差,可以考虑替换。

 

然后,我们会针对软件或硬件的升级改造做线上评估,即 Evaluation。比如,硬件厂商推出了一个新硬件,他们自己肯定会做一堆评测,得到一组比较好的性能数据,但刚才也提到了,这些评测和数据都是在特定场景下跑出来的,这些场景是否适合用户的特定需求?

 

没有直接的答案。通常,用户也不会让硬件厂商到其业务环境里去跑评测。这时候就需要用户自己拿这个新硬件做灰度测试。当然灰度规模越大评测越准确,但线上环境都直接关联业务,为了降低风险,实际中通常都是从几十台甚至几台、到上百台、上千台的逐步灰度。SPEED 平台要解决的一个问题就是即便在灰度规模很小时也能做一个较好的估计,这会节约非常多的成本。

 

随着灰度规模增大,平台会不断提高性能分析质量,进而辅助用户决策,即 Decision。这里的决策不光是判断要不要升级新硬件或新版软件,而且需要对软硬件全栈的性能有一个很好的理解,明白什么样的软硬件架构更适合目标应用场景,这样可以考虑软硬件优化定制的方向。

 

比如,Intel 的 CPU 从 Broadwell 到 Skylake,其架构改动很大,但这个改动的直接效果是什么?Intel 只能从基准测试中给答案,但用户可能根据自己的应用场景给出自己的答案,从而提出定制化需求,这对成本有很大影响。

 

最后是 Validation,就是通常规模化上线后的效果来验证上述方法是否合理,同时改进方法和平台。

 

 

数据中心里软硬件升级的性能分析需要一个全局的性能指标,但目前还没有统一的标准。Google 今年在 ASPLOS 上发表了一篇论文,提出了一个叫 WSMeter 的性能指标,主要是基于 CPI 来衡量性能。

在 SPEED 平台里,我们也提出了一个全局性能指标,叫资源使用效率 RUE。基本思想很简单,就是衡量每个单位 Work Done 所消耗的资源。这里的 Work Done 可以是电商里完成的一个 Query,也可以是大数据处理里的一个 Task。而资源主要涵盖四大类:CPU、内存、存储和网络。通常我们会主要关注 CPU 或内存,因为目前这两部分消费了服务器大部分的成本。

 

RUE 的思路提供了一个多角度全面衡量性能的方法。举个例子,业务方反映某台机器上应用的 response time 升高了,这时登录到机器上也看到 load 和 CPU 利用率都升高了。这时候你可能开始紧张了,担心出了一个故障,而且很可能是由于刚刚上线的一个新特性造成的。

 

然而,这时候应该去看下 QPS 指标,如果 QPS 也升高了,那么也许是合理的,因为使用更多资源完成了更多的工作,而且这个资源使用效率的提升可能就是由新特性带来的。所以,性能需要多角度全面地衡量,否则可能会造成不合理的评价,错失真正的性能优化机会。

 

 

下面具体讲几个数据中心性能分析的挑战,基本上是线上碰到过的具体问题,希望能引起大家的一些思考。

 

首先是性能指标。可能很多人都会说性能指标我每天都在用,这有什么好说的。其实,真正理解性能指标以及系统性能本身并不是那么容易。举个例子,在数据中心里最常用的一个性能指标是 CPU 利用率,给定一个场景,数据中心里每台机器平均 CPU 利用率是 50%,假定应用需求量不会再增长、并且软件之间也不会互相干扰,那么是否可以把数据中心的现有机器数量减半呢?

这样,理想情况下 CPU 利用率达到 100% 就可以充分利用资源了,是否可以这样简单地理解 CPU 利用率和数据中心的性能呢?肯定不行。就像刚才说的,数据中心除了 CPU,还有内存、存储和网络资源,机器数量减半可能很多应用都跑不起来了。

 

再举个例子,某个技术团队升级了其负责的软件版本以后,通过线上测试看到平均 CPU 利用率下降了 10%,因而声明性能提升了 10%。这个声明没有错,但我们更关心性能提升以后是否能节省成本,比如性能提升了 10%,是否可以把该应用涉及的 10% 的机器关掉?这时候性能就不应该只看 CPU 利用率,而应该再看看对吞吐量的影响。

 

所以,系统性能和各种性能指标,可能大家都熟悉也都在用,但还需要更全面地去理解。

 

 

刚才提到 SPEED 的 Estimation 会收集线上性能数据,可是收集到的数据一定对吗?这里讲一个 Hyper-Threading 超线程的例子,可能对硬件了解的同学会比较熟悉。超线程是 Intel  的一个技术,比如我们的笔记本,一般现在都是双核的,也就是两个 hardware cores,如果支持超线程并打开以后,一个 hardware core 就会变成两个 hardware threads,即一台双核的机器会有四个逻辑 CPU。

来看最上面一张图,这里有两个物理核,没有打开超线程,两边 CPU 资源都用满了,所以从任务管理器报出的整台机器平均 CPU 利用率是 100%。左下角的图也是两个物理核,打开了超线程,每个物理核上有一个 hardware thread 被用满了,整台机器平均 CPU 利用率是 50%。

 

再看右下角的图,也是两个物理核,也打开了超线程,有一个物理核的两个hardware threads 都被用满了,整台机器平均 CPU 利用率也是 50%。左下角和右下角的 CPU 使用情况完全不同,但是如果我们只是采集整机平均 CPU 利用率,看到的数据是一样的!

 

所以,做性能数据分析时,不要只是想着数据处理和计算,还应该注意这些数据是怎么采集的,否则可能会得到一些误导性的结果。

 

 

数据中心里的硬件异构性是性能分析的一大挑战,也是性能优化的一个方向。比如这里左边的 Broadwell 架构,是 Intel 过去几年服务器 CPU 的主流架构,近几年在推右边的 Skylake 架构,包含最新的 Cascade Lake CPU。Intel 在这两个架构上做了很大的改动,比如,Broadwell 下访问内存还是保持多年的环状方式,而到了 Skylake 改为网格状方式。

 

再比如,L2 Cache 到了Skylake  上扩大了四倍,通常来说这可以提高 L2 Cache 的命中率,但是 cache 越大也不代表性能就一定好,因为维护 cache coherence 会带来额外的开销。这些改动有利有弊,但我们需要衡量利和弊对整体性能的影响,同时结合成本来考虑是否需要将数据中心的服务器都升级到 Skylake。

 

了解硬件的差异还是很有必要的,因为这些差异可能影响所有在其上运行的应用,并且成为硬件优化定制的方向。

 

 

现代互联网服务的软件架构非常复杂,比如阿里的电商体系架构,而复杂的软件架构也是性能分析的一个主要挑战。举个简单的例子,图中右边是优惠券应用,左上角是大促主会场应用,左下角是购物车应用,这三个都是电商里常见的业务场景。从 Java 开发的角度,每个业务场景都是一个 application。电商客户既可以从大促主会场选择优惠券,也可以从购物车里选择优惠券,这是用户使用习惯的不同。

 

从软件架构角度看,大促主会场和购物车两个应用就形成了优惠券应用的两个入口,入口不同对于优惠券应用本身的调用路径不同,性能影响也就不同。

 

所以,在分析优惠券应用的整体性能时需要考虑其在电商业务里的各种错综复杂的架构关联和调用路径。像这种复杂多样的业务场景和调用路径是很难在基准测试中完全复现的,这也是为什么我们需要做线上性能评估。

 

 

这是数据分析里著名的辛普森悖论,在社会学和医学领域有很多常见案例,我们在数据中心的性能分析里也发现了。这是线上真实的案例,具体是什么 App 我们不用追究。

 

假设还用前面的例子,比如 App 就是优惠券应用,在大促的时候上线了一个新特性 S,灰度测试的机器占比为 1%,那么根据 RUE 指标,该特性可以提升性能 8%,挺不错的结果。但是如果优惠券应用有三个不同的分组,分组假设就是关联刚才提到的不同入口应用,那么从每个分组看,该特性都降低了应用的性能。

 

同样一组数据、同样的性能评估指标,通过整体聚集分析得到的结果与通过各部分单独分析得到的结果正好相反,这就是辛普森悖论。既然是悖论,说明有时候应该看总体评估结果,有时间应该看部分评估结果。在这个例子里面,我们选择看部分评估、也就是分组上的评估结果,所以看起来这个新特性造成了性能下降,应该继续修改并优化性能。

 

所以,数据中心里的性能分析还要预防各种可能的数据分析陷阱,否则可能会严重误导决策。

 

 

最后,还有几分钟,简单提一下性能分析师的要求。这里通常的要求包括数学、统计方面的,也有计算机科学、编程方面的,当然还有更重要的、也需要长期积累的领域知识这一块。这里的领域知识包括对软件、硬件以及全栈性能的理解。

 

其实,我觉得每个开发者都可以思考一下,我们不光要做功能开发,还要考虑所开发功能的性能影响,尤其是对数据中心的整体性能影响。比如,JVM 的 GC 开发,社区里比较关心 GC 暂停时间,但这个指标与 Java 应用的 response time 以及所消耗的 CPU 资源是什么关系,我们也可以有所考虑。​​​​