5.4.2 Alibaba Dragonwell
背景概述
Java诞生于20多年前,拥有大量优秀的企业级框架,践行OOP理念,更多体现的是严谨以及在长时间运行条件下的稳定性和高性 能。在如今微服务、云原生大行其道的时代,过于重量的 Java 语言面临着启动速度慢、运行消耗大等诸多挑战。
Alibaba Dragonwell是OpenJDK的下游发行版本,支持X64/AArch64平台,被广泛应用于在线电商、金融、物流等领域,百万量 级部署规模。 Alibaba Dragonwell依托于丰富的阿里巴巴Java应用场景的锤炼, 全面拥抱云原生,为Java注入新鲜血液。
Wisp协程
在分布式微服务应用领域,存在着大量的网络IO,请求处理线程通常会阻塞等待后台的数据库、缓存、RPC访问。这种开发模型导 致线程频繁阻塞,大量CPU资源浪费在调度和上下文切换上。协程方案可以以阻塞的方式写出异步执行的代码,极大提升密集网络 IO型应用的性能。
Wisp在Alibaba Dragonwell上提供了一种用户态的线程实现。开启Wisp后,Java线程不再简单地映射到内核级线程,而是对应到 一个协程,JVM在少量内核线程上调度大量协程执行,以减少内核的调度开销,提高Java应用性能。
开启Wisp后,应用程序无需任何修改就可以获得性能提升。以下是在Framework Benchmark的Spring实现下,开启协程和关闭协 程的性能比较。
JWarmup编译预热
Java拥有即时编译特性,代码以解释器执行为基础,当方法执行足够多次数成为热方法后会触发Just In Time(JIT)编译,性能得到 数十倍提升。但应用程序有一个预热的过程,通常需要运行一段时间才能达到峰值性能。
JWarmup以可控的方式来完成预热: 根据前一次程序运行的情况,记录下热点方法、类编译顺序等信息, 在应用下一次启动的时候 积极加载相关的类,并积极编译相关的方法,进而应用启动后可以直接运行编译好的Java代码 (C2编译)。
上图显示了JWarmup典型的用法:
- 在Beta灰度环境,进行应用压测,记录(Record)热点方法、类编译顺序等信息。
- 在Production环境,使用提前记录的profiling data提前编译(Compile)热点方法。
上图显示了生产环境下使用JWarmup与关闭JWarmup的CPU曲线对比。可以看到代表 JWarmup使用的红线CPU使用率相当稳定:
在(1) 的时间点过后,JWarmup提前编译方法,相对于正常蓝线情况,红线使用的CPU上升。
在(2) 的时间点过后,真实流量进来,因为JWarmup情况下方法已经在 (1) 被提前编译,所有使用的CPU要明显低于蓝线。
多租户
在有些场景中,Java应用并非作为单一业务用途的程序存在的,而是作为一个平台存在,在他上面运行着一些更加轻量的应用或函 数。在这类平台型Java应用上面,一般通过动态类加载机制把遵循一定编程接口规范的,和Java字节码技术兼容的软件模块(可以 是从Scala、Kotlin等语言编译而来)加载到应用进程,并运行其中的业务逻辑,一个典型的例子是Tomca的动态加载机制。这类架 构有一个缺点:就是平台型Java应用缺乏对轻量应用所使用资源的管控能力。容易出现某个应用占用过多资源——比如CPU时间——而 导致其他同进程应用无法响应。 JDK多租户技术的目的就是为平台型 Java应用提供一个细粒度资源管控的能力。
Alibaba Dragonwell多租户技术通过在JDK中创建虚拟的进程内容器 “租户” ,来让JVM可以识别出运行时代码所持有的资源组, 架构图如下:
在高密度部署场景,多租户技术允许将多个Java应用安全部署在同一个JVM中,为基于JVM技术栈的PaaS、SaaS、 FaaS应用平台提供了基于租户粒度的底层资源,包括CPU,内存等隔离能力。
生产就绪ZGC及弹性堆
Alibaba Dragonwell 11第一个版本应业务和云上客户的需求,默认提供了Java 11的实验性ZGC特性。随着ZGC进入生产实践而逐步落地,客户在享受响应时间优化的同时,也遭遇到了一些实际问题。因此我们发布了Alibaba Dragonwell11.0.11.7 ,其中的ZGC特性由OpenJDK 11中的实验特性改造为生产就绪(production-ready)特性,同时保证Alibaba Dragonwell 11长期支持的质量稳定性:
系统性移植OpenJDK15 ZGC代码:OpenJDK15(首个支持生产就绪ZGC的OpenJDK上游正式版本)的大部分ZGC相关代码,这些代码完善了ZGC的功能,支持更多的平台,并且修复了重大bug。
ZGC AArch64平台优化:Alibaba Dragonwell向OpenJDK社区贡献了AArch64平台上ZGC的优化方案,减少内存屏障指令,将Heapothesis benchmark的ZGC吞吐能力提升超过15%。
Apache RocketMQ使用ZGC暂停时间从200ms降到10ms以内。
JVM为应用程序提供了自动管理堆内存的能力,包括空闲内存在内。即使应用完全空闲,这些内存也无法被操作系统中其他进程使用。G1ElasticHeap特性支持在G1中动态归还堆物理内存并降低Java进程的内存占用。
在多应用混合部署的场景,G1ElasticHeap空闲内存回收特性可以在应用低负载时降低内存使用,供其他混部的应用使用。下图蓝色表示在线任务,绿色表示离线任务。在线服务空闲时通过G1ElasticHeap释放空闲内存,以供离线服务使用。
另外一个典型的应用场景是大促,Java进程内存根据实际服务的压力动态调整。当大促高峰服务繁忙期间,Java进程会占用比较多的内存,而在服务空闲时段,Java进程会及时归还物理内存给操作系统。如下图