显然,运行速度更快的 JVM 意味着需要的云资源更少。
译自 How To Reduce Cloud Waste,作者 Simon Ritter。
对于当今大多数应用程序来说,说你将它们托管在自己的数据中心就像说你自发电一样。为什么要支付所有这些资本支出来配置足够的硬件以满足你的峰值负载(可能一年只发生一次),然后还要花费运营支出为这些机器供电和冷却,以及维护它们?只需让像 Amazon,Microsoft 或 Google 这样的公司为你做这些,并且只为你使用的资源付费,就像你支付电费一样。
这就是云计算的承诺:一种基于效用的定价模式,可以降低运行关键任务企业应用程序的账单。
不幸的是,现实往往与之不同,人们发现迁移到云的成本比在本地托管更高。这是怎么回事,我们该如何解决这个问题?
让我们具体看看基于 JVM 的应用程序 使用 Java。但是,许多其他语言,如 Kotlin,Scala 和 Clojure,也可以为 JVM 编译。
构建基于云的应用程序的现代方法是 使用微服务。与其开发单个的单体应用程序,我们将其分解成离散的服务,这些服务可以松散耦合但高度内聚。这样做,当一项服务成为性能瓶颈时,我们可以启动该服务的新的实例,负载均衡使用并消除瓶颈,而无需更改系统的其他部分。
这就是 JVM 的核心功能之一会导致云资源浪费的地方。
为了实现“一次编写,随处运行”的承诺,Java 应用程序编译成字节码,即虚拟机的指令,而不是特定处理器的指令。当 Java 应用程序启动时,JVM 会对其进行分析并识别可以编译成本地代码的常用代码热点。这种即时 (JIT) 编译提供了出色的性能,因为 JVM 确切地知道代码的使用方式,并可以相应地对其进行优化。
但是,识别和编译所有常用代码段所需的时间(实际上是一个更复杂的多阶段过程)可能比预期更长。这种预热时间(如其所称)对于像 Web 服务器或应用程序服务器这样的长时间运行的进程来说通常不是问题。微服务可以频繁地启动和停止,以动态响应负载变化。在微服务能够提供全部承载能力之前等待其预热会降低这种方法的优势。
一个常用的解决方案是启动服务的多个实例并让它们保持运行,以便在需要时立即提供全部性能。这显然非常浪费,并且会产生不必要的云基础设施成本。
我们如何解决这个问题?
一种方法是使用提前 (AOT) 编译。与其使用 JIT 编译,所有代码都直接编译成本地指令。这完全消除了预热,应用程序以可用的全部性能级别启动。
虽然这听起来像是理想的解决方案,但它并非没有成本和限制。
AOT 编译代码时不知道它将如何实际使用,这限制了优化的潜力。JIT 编译具有分析信息,可以实现针对应用程序使用方式量身定制的优化。通常,这会导致整体性能略有提高。
对于短暂的微服务,即所谓的无服务器计算,AOT 提供了明确的优势。对于任何将运行至少几分钟的服务,JIT 将带来更好的性能,因此会降低云计算成本。
另一种解决方案是 Azul 在其 Platform Prime 高性能 Java 运行时中实现的解决方案。这包括 ReadyNow 预热消除技术。 我们已经看到,问题在于,每次启动微服务实例时,JVM 必须执行相同的分析来识别热点,收集性能分析信息并将其编译为本地代码。即使我们之前多次以相同的方式使用过该微服务,也会发生这种情况。使用 ReadyNow,服务在生产环境中启动并允许使用真实世界的请求进行预热,而不是模拟请求。当服务完全预热(达到最佳性能水平)时,会收集一个配置文件。该配置文件包含获得该性能水平所需的所有信息:热点列表、性能分析数据甚至编译后的代码。
当需要再次启动服务时,配置文件将作为执行参数的一部分提供。JVM 使用配置文件来确保当它准备好处理第一个事务时,性能将几乎达到配置文件被获取时的水平(大约 98%,因为 JVM 工作方式的一些技术限制阻止了 100% 的交付)。
结果是几乎消除了所有预热时间,同时保留了 JIT 编译的所有性能优势。该系统提供了完全的灵活性,因为可以根据服务的使用时间和地点,为同一服务使用不同的配置文件。例如,周一上午的工作负载配置文件可能与周五下午的工作负载配置文件截然不同。可以存储多个配置文件,并在需要时选择合适的配置文件。
现在,基于 JVM 的微服务可以将预热时间降至最低,因此无需维护在后台闲置的服务池。这可以显着减少云浪费。
一个性能优化的 JVM,它还包括一个替代的内存管理系统,消除了与之相关的交易延迟,这是一个很好的选择。JIT 编译系统也得到了改进,以提供更高的吞吐量。这些不是减少云浪费,而是减少了提供相同承载能力所需的云资源。其效果是进一步降低云成本。
让我们看一个真实客户如何使用它的例子。Supercell 是一家运营着世界上一些最大的在线多人游戏的公司。在最近发布的 Brawl Stars 中,它在启动新服务器时遇到了延迟,因为 JVM 正在编译所需的代码。通过切换到 Azul Platform Prime 并利用 ReadyNow,它能够提供更一致的负载承载能力,减少游戏延迟,并将相同工作负载的 CPU 使用率降低 20% 到 25%。
显然,运行速度更快的代码的 JVM 意味着需要更少的云资源。