拼不过 GO?阿里如何重塑云上的 Java

阿里梅简介:爪哇诞生于20年前。它有大量优秀的企业级框架和实践面向对象的概念。它体现了在长期运行条件下更加严格、稳定和高性能。相比之下,在今天需要快速迭代交付的云场景中,语言简单性似乎是首要要求,而传统的Java语言似乎有点过于沉重。今天,阿里JVM团队的技术专家雷宇分享了JVM团队是如何面对和处理团队庞大的业务规模和复杂的业务场景的。

音乐没有边界,但是音乐家有边界。

云源也是如此。虽然没有明确的编程语言,但是应用程序使用的编程语言已经决定了应用程序部署和操作的行为。

弹性便宜

Java经常因消耗资源而受到批评。最重要的一点是堆对内存的使用。即使在处理过程中没有请求和对象分配,该过程仍将保留完整的堆内存空,以确保GC快速灵活的内存分配和操作。

ajdkzenc/elastichap double-eleven完全支持数百个应用程序和数十万个核心链接实例。

JDK12开始支持在固定时间内触发并发标记和缩小Java堆以返回内存的功能。然而,它并没有解决stw中增加暂停时间的问题,因此每次年轻的GC都不能进行内存返回。弹性廉价在并发异步线程中反复完成内存处理的开销映射/取消映射和页面错误,因此任何年轻的垃圾回收器都可以迅速返回内存或恢复内存使用。

弹性便宜货阿里巴巴实战

弹性低成本场景1:可预测的高峰流量

弹性廉价场景2:运行多个Java实例的单机

多个Java实例接收的流量任务相对随机,峰值不重叠。在空闲时间,可以有效减少多个实例的整体内存占用,提高部署密度。

Double 11验证了核心交易系统使用弹性便宜货(ElasticHeap)在低功耗模式下运行,大大缩小了WSS的规模。

静态编译

云上的许多新应用同时选择了围棋语言。主要原因是Go应用程序不依赖于运行时,静态编译的程序启动很快,不需要由JIT预热。在阿里拥有大量Java代码的前提下,我们如何将这种能力注入到Java中?

Java静态编译技术是一种激进的AOT技术,它通过单独的编译阶段将Java程序编译成本地代码,运行时不需要传统的Java虚拟机和运行时环境,只需要操作系统类库的支持。其操作的基本原理如下图所示。静态编译技术实现了Java语言和本机程序的“集成”,并将原始的Java程序编译成具有Java行为的自举本机程序,从而兼具了Java程序和本机程序的优点。

JVM团队与SOFAStack团队密切合作,带头在中间件应用程序上实现静态编译。应用程序的启动速度从60秒优化到3.8秒。静态编译的应用程序运行稳定,在双十一期间没有故障。气相色谱暂停时间在100毫秒内。在业务允许的范围内,内存占用和实时性与传统的Java应用程序相同。

综上所述,静态编译应用在稳定性、资源占用、实时响应等指标与传统的Java应用基本相同的情况下,启动时间减少了2000%。

Wisp2

当你用最酷的垂直开发一个简单的网络服务时。十、准备体验最强的性能,质量保证学生带了1C 2G的容器给你按,但是你发现你不能和别人的围棋应用程序竞争。研究发现,在如此少量的核心下,原始协同模型具有更好的性能。时代变了吗,Java落后了吗?

AJDK Wisp2回答了这个问题:Java也可以有高性能的协调。这是Wisp2首次大规模推出。Wisp2具有以下特征:

整个Java运行时和线程都支持协调调度。read())阻塞将成为一个更轻的协调开关。

与线程应用编程接口完全兼容。在打开Wisp2的JDK,Thread.start()实际上创建了一个协程,这类似于go只提供协程关键字Go而不公开线程接口。我们也只提供了创建协同过程的方法,应用程序可以透明地切换到协同过程。

支持工作日志,调度策略特别适合网络场景,在高压下调度开销最小。

今年11日,Wisp支持数百个应用程序和10万个容器,其中90%已经升级到Wisp2。

可以看出,在高峰期前后,Wisp2机器的中央处理器降低了7%左右,主要是系统中央处理器通过轻量级调度节省下来。0处的CPU相等,这也表明Wisp2解决了调度开销。当中央处理器很低并且没有调度压力时,没有区别。

从RT的角度来看,Wisp2机器的RT大约低20%。实时性降低的一个明显原因是这些机器的中央处理器压力很高,协调过程的调度优势更容易体现出来。这一优点可以帮助系统达到更高的水位,提高整体利用率,并担心高辐射引起的雪崩

FDO

在接下来的几分钟里,相对于双11正零点,将会有一个明显的中央处理器峰值。根据数据分析,主要原因是双11零触发JIT编译。例如,程序中有逻辑:

if )) { branch1}否则{ branch2 }

假设在预热过程中使用了branch2,JIT有理由相信branch2将在将来基本上被使用,并且不会编译branch1。从零开始,我们进入branch1,此时我们需要触发反编译重新编译方法。让我们看看AJDK是如何通过剖析来解决这个问题的。

去优化原理及其危害

当JDK运行代码时,它以分层的方式动态编译Java方法。在最高级别的编译中,出于性能考虑,在编译期间将基于收集的信息做出一些乐观的假设。一旦这些假设得不到满足,就会出现去优化现象。例如,热方法中的某个代码将只在Double Eleven中执行,那么该代码将不会在预热过程中编译。一旦这个代码在双十一到达时被执行,它将触发整个方法的去优化。

去优化的出现有两个负面影响。首先,需要运行的方法已经从高效编译执行变为解释执行,运行速度已经降低了100多倍。第二,优化方法将在高峰流量期间快速重新编译,编译线程将消耗中央处理器。因此,在双十一的情况下,去优化的危害将特别明显,在双十一的情况下,流量在短时间内急剧增加,并且不同于预热流量。

减少FDO的去优化

FDO是反馈导向优化(feedback directed optimization)的缩写,指的是过去JVM运行时的编译信息,以指导在这个运行时更好的编译。具体来说,我们采用了两级方法来减少去优化。

将每次运行期间的解优化信息记录到文件中,在下次运行期间读取文件,并在决定是否进行乐观假设时参考文件中的信息进行判断,从而降低解优化的概率。

信息显示,最常见的去优化与if-else有关,占总数的一半以上。我们提供了一种基于如果不优化的信息关闭某条路径上所有相关乐观假设的方法。

《双十一》中的FDO效应

FDO于今年11日推出,旨在解决两个问题:

1.双110流量峰值和去优化/编译峰值叠加导致的CPU利用率脉冲过高。

2.预热效率低。在预热很长一段时间后,在增加流量时,压力测量仍然伴随着大量的编译和解优化。

在回答第一个问题时,我们收集了双十一高峰期第一分钟的去优化/C2编译数量和中央处理器数据。

可以看出,在打开FDO之后,C2编译的数量减少了大约45%,反优化的数量减少了大约70%。

就中央处理器数据而言,在高峰时段的第一分钟开启FDO后,中央处理器从约67.5降至63.1,降幅约为7.0%。

第二个目标可以通过按下第一分钟的中央处理器数据来验证。

当FDO开启时,压力测量第一分钟的中央处理器利用率从66.19%降至60.33%,约为10%。

优雅

ZProfiler一直是整个团队检查Java应用程序中各种问题的利器。Grace作为其平台版本,已经在其上实现了一系列优化,从最初的独立版本到当前的主/工作架构。同时,引入了任务排队机制,在高压力下对用户的任务进行排队,解决了工作人员不堪重负的问题。可维护性、可扩展性和用户体验得到了质的提高,为后续工具平台的云和开源问题奠定了坚实的基础。

目前,堆转储功能已经集成,并在继承ZProfiler功能的基础上进行了一定的优化。解析引擎的版本已经升级,支持更全面的OQL语法等。

JDK11

JDK8作为经典版本,正在大规模使用。尽管迁移JDK6和JDK 7有些困难,但升级后的总体反馈“非常好”。

OpenJDK 8的下一个稳定版本是OpenJDK 11。JVM团队自然会朝着这个方向积极跟进。目前,AJDK11支持AJDK8的Wisp2和多租户功能。这款双十一的一些集群已经发布到JDK11,并且运行稳定。

升级JDK11会给我们带来和升级JDK8一样的惊喜吗?我们可以在JDK11上体验最新的ZGC。

ZGC

JDK11引入了一个重要特性:ZGC内存垃圾收集器。这个垃圾收集器声称能够在几十千兆到几兆字节的堆上保持10毫秒内的暂停时间。过去,许多Java开发人员都受到垃圾收集器暂停时间造成的延迟的困扰。ZGC的短暂暂停功能无疑将成为未来Java开发人员的新宠。

目前,ZGC在OpenJDK中仍处于实验性特征,JDK11尚未在行业中全面推广。JDK11只在Linux上支持ZGC,许多Java开发人员仍然只能觊觎和观望。

如何才能阻止我们吃螃蟹?阿里JVM团队和数据库团队已经开始在ZGC运行数据库应用,并根据运行效果对ZGC做了相应的改进,包括优化ZGC的页面缓存机制、优化ZGC的触发时机等。

自9月份以来,这两个团队已经推动在线数据库应用程序在ZGC运行。它已经稳定运行了两个月,并成功通过了双十一考试。在线反馈的效果值得称赞:

1.JVM暂停时间保持在官方的10ms以内;

2.ZGC大大提高了在线集群的平均实时性和故障指数。

摘要

从上面的特性中,我们可以看到AJDK已经从传统的托管运行时发生了变化。未来,AJDK将继续致力于改善基于云的应用程序的开发体验,并通过底层创新为上层应用程序提供更多可能性。

大家都在看

相关专题