飞天发布时刻:2024年 Forrester 公有云平台Wave™评估报告解读 了解详情
写点什么

快速实现不打折扣的云原生 Java 应用

作者:Tobi Ajila, Thomas Watson

  • 2023-06-02
    北京
  • 本文字数:4694 字

    阅读完需:约 15 分钟

快速实现不打折扣的云原生Java应用

近年来,向云原生计算迁移一直是开发人员比较关注的事情,按照云原生方式他们的业务应用能够从减少 IT 基础设施,提高可扩展性等方面受益。当涉及到云端部署应用程序时,“伸缩至零(scale-to-zero)”是标准的供应(provisioning)策略,以便于在业务需求较低的时候降低成本。随着需求的增加,会供应更多的应用程序实例和运行时,这种扩展必须非常迅速,这样终端用户才不会遇到响应滞后的问题。运行时的启动时间会对扩展性能产生很大的影响。

 

Open Liberty是一个云原生 Java 运行时,与其他 Java 运行时类似,它是建立在 JVM 技术之上的。JVM(更广泛地说,整个 JDK)所提供的性能、调试能力和类库使其成为支撑应用程序的重要技术。尽管 JVM 以出色的吞吐能力而闻名,但是其启动时间却落后于 Go 和 C++等静态编译语言。考虑到伸缩至零的需求,所以多年以来,显著改善启动时间一直是所有 JVM 实现的关键创新领域。AppCDS(HotSpot)Shared Classes Cache(Eclipse OpenJ9)这样的元数据缓存技术在启动时间方面做出了令人瞩目的改进,但并没有在启动时间方面实现数量级级别的减少,而这恰好是 serverless 计算的扩展场景所需要的。

 

编译为原生镜像以减少启动时间

 

Graal Native Image曾经宣布,借助编译为原生的方式,它能够实现低于 100 毫秒的启动时间,因此得到很多的关注。这是 JVM 领域的一个重大转变,因为这是 Java 第一次在启动时间方面能够与 C++相抗衡。虽然 Graal Native Image 显著降低了启动时间,但这也是有一定代价的。

 

首先,静态编译要求在构建时对应用有一个全局的了解。对于开发人员来说,他们在构建应用时一直依赖的动态能力将会受到限制。比如,像反射、动态类加载和 invokedynamic 等操作均需要特殊处理,因为它们会干扰生成原生镜像时的静态分析。这意味着,我们可能需要对应用程序进行大量的修改,这样原生镜像才能够正常运行,更糟糕的是,应用程序的依赖可能也需要更新。

其次,调试会变得更具挑战性,因为我们此时调试的已经不是一个 JVM 应用,而是一个原生可执行文件。我们需要将熟悉的 Java 调试器替换为原生调试器(如gdb)来调查问题。有种解决方式是在开发环境中使用 JVM,在生产环境中使用原生镜像。但是,这意味着生产环境与开发环境是不一致的,最终我们可能必须要在两个不同的运行时中修复缺陷!

 

最后,JVM 提供的优秀的特性之一就是出色的吞吐量,即时(just-in-time)编译器能够在运行时根据实时数据优化应用程序以达到最佳性能。这一点也必须在原生镜像中牺牲掉,因为开发人员只有一次编译的机会,那就是在构建时。有些框架,比如Spring Native,已经建立了帮助 Java 开发人员在原生镜像约束下运行应用程序的能力,但不得不承认的是,开发人员必须放弃一些东西以获取原生镜像在启动时间方面的收益。

 

使用检查点/恢复功能跳过启动时间

 

Liberty 运行时采用了一种不同的方式来改善启动时间。Liberty 的目标是提供快速启动,而不必进行取舍,这是通过一项名为Liberty InstantOn的特性实现的。该特性提供了 Java 开发人员熟悉的所有功能,相对于没有使用 InstantOn 的 JVM 运行环境,它的运行时启动时间最多能够优化 10 倍。

 

从基础上来讲,Liberty InstantOn 是基于检查点/恢复(checkpoint/restore)技术的。我们启动一个应用程序,然后暂停它,并在某些明确定义的点上持久化应用程序的状态,这就是检查点。这个检查点就会成为应用镜像,当部署应用的时候,我们只需要从已保存的状态恢复镜像即可,这就是恢复,通过这种方式,应用程序就跳过了它通常要经历的启动和初始化过程(因为这些步骤已经运行过了)。

 

Liberty 使用了OpenJ9 CRIU提供的支撑功能,这是一项基于Linux CRIU的技术,它能够让任意应用均支持检查点和恢复。在 Liberty InstantOn 方式中,因为我们依然在 JVM 上运行,所以在吞吐量性能方面没有任何损失。Java 调试也能按照预期方式运行,所有依赖动态 JVM 能力的库也能正常运行。

 

解决检查点/恢复机制的局限性

 

尽管检查点/恢复的概念听起来很简单,但在现实中,会有一些限制(这是CRIU的运行方式所导致的)需要由运行时和 JVM 共同来解决,以便于让应用程序体验到这些收益。当执行检查点时(此时会构建镜像),CRIU 会将环境“冻结”在检查点状态中,包括环境变量、计算资源的信息(CPU、内存)以及时间本身的信息都会打包到镜像中。这些东西中的任何一项在恢复环境中都可能是不同的,从而导致应用程序的不一致,这是很难追踪的。此外,检查点可能会捕获一些数据,如果镜像要通过容器注册中心跨公共网络传输到部署环境中,这就不是很理想了。这些数据可能包含对端点的外部连接,而这些连接在恢复环境中可能并不存在,另外数据中还可能包含我们不想在检查点镜像中嵌入的安全令牌。

 

基于这些原因,OpenJ9 CRIU 支持内置的补偿机制,以确保在检查点保存的应用在恢复时的行为是正确和安全的。对时间敏感的 API 进行了修改以补偿检查点和恢复时的停机时间。对于像SecureRandom这样的随机 API 在恢复的时候对种子进行了重置(re-seed),以确保每次检查点恢复时,它都会被恢复为唯一的实例。

 

JVM 可以解决它所知道的所有事情,但是应用程序代码可能也需要类似的处理。Liberty 运行时通过与 JVM 合作来解决 JVM 无法自行处理的剩余问题,从而帮助开发人员摆脱检查点/恢复的复杂性。为了实现这一点,OpenJ9提供了一个钩子机制,开发人员可以利用它来注册在检查点之前和之后要执行的方法。这种机制被 Liberty 广泛采用,比如,在部署时重新解析配置,以确保为环境使用正确的配置。

 

所以,尽管 OpenJ9 提供了高效利用检查点/恢复技术的工具,但是增强现有应用程序启动时间的最简单的方式是在 Liberty 上使用 Liberty InstantOn 来运行它。Liberty InstantOn 对检查点/恢复过程进行了抽象,将开发人员的选择简化为只有几项,比如确定检查点用于应用程序启动之前还是之后。

 

总而言之,我们的终极目标是改善 Java 应用程序的云原生体验,这意味着无论采用什么样的技术,都必须要在云环境中高效运行。Liberty InstantOn 与容器技术(如 Docker 和Podman)实现了无缝集成。Liberty InstantOn 还能与KnativeOpenShift等容器引擎协作。我们完成了相关的工作以确保 Liberty InstantOn 能够在非特权模式下运行,因为这对生产环境的安全性是非常重要的。这项工作的成果正在回馈给 CRIU 项目。

 

使用自己的项目尝试一下 Liberty InstantOn

 

Liberty InstantOn 的 beta 版本已经公开可用,开发人员可以使用现有的应用程序进行尝试,以观察启动时间的改进(最多能够快 10 倍)。你只需要使用 Liberty InstantOn 工具为你的应用程序创建一个应用容器镜像即可。Open Liberty 发布了生产就绪的容器镜像,使你的应用程序可以很容易地进行容器化,以便于在容器引擎中运行,比如 Docker、Podman 或 Red Hat OpenShift 这样的 Kubernetes 环境。

 

Open Liberty 容器镜像包含了所有必要的依赖,以便于在 Open Liberty 运行时中运行应用程序。如下针对开发人员的指南描述了如何基于 Open Liberty beta-instanton 镜像(icr.io/appcafe/open-liberty:beta-instanton)创建一个带有应用程序的基础应用容器镜像,然后如何在此基础之上创建并添加一个包含检查点进程状态的层。beta-instanton 镜像包含了对 Open Liberty 创建检查点并将检查点进程存储到容器镜像层中所需的所有先决条件。这包括对 OpenJ9 CRIU 和 Linux CRIU 支持的早期访问构建。

 

如何使用 Liberty InstantOn 容器化应用程序,使其能够更快启动

如下的指南使用 Podman 来构建和运行容器,并且使用了Open Liberty入门指南中的应用程序。如果你手头有自己的应用程序,可以将其替换掉。

 

入门应用程序包含了一个Dockerfile,如下所示:

 

FROM icr.io/appcafe/open-liberty:full-java11-openj9-ubi

ARG VERSION=1.0ARG REVISION=SNAPSHOT

COPY --chown=1001:0 src/main/liberty/config/ /config/COPY --chown=1001:0 target/*.war /config/apps/

RUN configure.sh
复制代码

 

首先,开发人员需要更新 FROM 指令以使用 beta-instanton 镜像:

 

FROM icr.io/appcafe/open-liberty:beta-instanton
复制代码

 

然后,借助更新后的 Dockerfile,可以使用如下的命令构建应用容器镜像:

 

podman build –t getting-started .
复制代码

 

该命令会创建应用容器镜像,但是还没有创建检查点进程。应用程序的检查点进程是通过如下命令运行应用容器镜像来创建的,这里添加了一些额外的选项:

 

podman run \--name getting-started-checkpoint-container \--privileged \--env WLP_CHECKPOINT=applications \getting-started
复制代码

 

通过 WLP_CHECKPOINT 变量,Open Liberty 运行时声明在被配置的应用启动后但在打开端口以接受传入的请求之前对应用进程生成检查点。当应用程序进程完成检查点生成后,运行中的容器将会停止。这将会形成一个包含检查点进程状态的已停止的容器。

 

最后一步是将这个检查点进程状态以层的形式添加到原始应用程序的进程镜像中。这可以通过如下的命令将名为 getting-started-checkpoint-container 的已停止应用容器提交给一个新的容器镜像:

 

podman commit \getting-started-checkpoint-container \getting-started-instanton
复制代码

 

最终的结果是可运行的 getting-started-instanton 容器镜像。

 

运行具有 Linux 特权能力的容器

当运行 getting-started-instanton 容器时,开发人员必须授予其一组Linux能力,以便容器镜像中的 CRIU 二进制文件执行恢复过程:

 

  • cap_checkpoint_restore

  • cap_net_admin

  • cap_sys_ptrace

 

在创建检查点进程时,使用了一个具有特权的容器,它授予了容器镜像中的 CRIU 二进制文件所需的Linux能力

 

请通过如下的 Podman 命令以运行具有三种所需能力的容器:

podman run \--rm \--cap-add=CHECKPOINT_RESTORE \--cap-add=NET_ADMIN \--cap-add=SYS_PTRACE \-p 9080:9080 \getting-started-instanton
复制代码

 

getting-started-instanton 容器会以必要的权限来运行,以执行恢复过程,应用程序的运行速度要比原始的 getting-started 应用程序快 10 倍。

 

未来的改进

 

Open Liberty的beta版本发布了对 Liberty InstantOn 的定期更新。未来的版本已经规划了一些改进,它们将会让 Liberty InstantOn 构建和运行应用镜像变得更加容易。例如,为了消除对 NET_ADMIN Linux能力的要求,一些额外的相关工作已经完成。还有一项计划是在恢复应用的过程中移除对 SYS_PTRACE 能力的要求。这将减少运行应用所需的能力清单,在运行应用程序的时候,仅需 CHECKPOINT_RESTORE 能力即可。

 

其他规划包括在应用容器的构建步骤中执行应用进程检查点,这样不需要容器运行和容器提交命令就能将应用进程状态存储到应用容器镜像层中了。

 

请反馈你们的想法

 

虽然云原生需要对组织的业务方式做出许多变化,但是有了 Liberty InstantOn,开发人员就不用担心改变他们的应用开发方式了。

 

我们鼓励开发人员使用 Open Liberty 22.0.0.11-beta 或后续版本来尝试Liberty InstantOn的beta功能。欢迎通过项目的邮件列表进行反馈。如果遇到问题,开发人员可以在StackOverflow上发布问题。如果发现缺陷的话,欢迎提交issue

 

背景说明

 

Open LibertyEclipse OpenJ9均是开源项目。IBM 基于这些项目构建了其商业的WebSphere Liberty Java 运行时和IBM Semeru Runtimes Java 发行版。Liberty InstantOn 使用了 Linux Checkpoint/Restore In Userspace(CRIU)项目提供的检查点/恢复技术,并与 CRIU 合作,将代码反馈给该项目。

 

原文链接:


https://www.infoq.com/articles/rapid-startup-of-your-cloud-native-java/

 

相关阅读:


Java 是如何毁掉你的编程思维的?

系统学 Java,看这篇 Java 综合笔记万字总结就够了!..

Java 8 之后的新特性都是鸡肋吗?

扫盲篇:Java 中为啥一个 main 方法就能启动项目?

2023-06-02 11:0011168

评论 1 条评论

发布
用户头像
这种native程序应该是像Rust那样内存安全的吧?
2023-06-03 23:35 · 湖南
回复
没有更多了
发现更多内容

解读科学计算助力行业高质量发展|2023开放原子全球开源峰会科学智能分论坛即将启幕

开放原子开源基金会

人工智能 开源 开放原子 科学智能

项目汇报的正确打开方式

老张

汇报 向上管理

中企出海,全球供应链业务如何更有效地经营?

用友BIP

中企出海 全球供应链

企业出海,全球合并有高招!

用友BIP

中企出海

ChatGPT应用助推跨境电商发展,低代码凭啥不行?!

加入高科技仿生人

低代码 跨境电商 ChatGPT JNPF

9秒被骗245万元?AI火了,骗子也来了!

引迈信息

AI 低代码 JNPF AI诈骗

开源数据库迎来技术创新拐点|2023开放原子全球开源峰会开源数据库分论坛即将启幕

开放原子开源基金会

数据库 开源 开放原子

累计下载破 10 万,阿里云 ACR 制品中心 5 月最受欢迎镜像排行榜

阿里巴巴云原生

阿里云 阿里云云原生 容器镜像服务

推动科技教育普惠|2023开放原子全球开源峰会校源行分论坛即将启幕

开放原子开源基金会

开源 开放原子全球开源峰会 开放原子

活动回顾丨首期阿里云 Serverless 技术创新实战营上海开讲(含 PPT 下载)

阿里巴巴云原生

阿里云 Serverless 云原生

展望开源产业与数字经济未来|2023开放原子全球开源峰会开源创新理论与实践分论坛即将启幕

开放原子开源基金会

开源 开放原子

多数据中心助力中企出海全球化经营

用友BIP

中企出海

中核集团财务共享迈上新台阶

用友BIP

财务共享

恒参信道特性及其对信号传输的影响

timerring

信息论

为什么 AIGC 和大模型创业者都在安利向量数据库?

Zilliz

Milvus AIGC 向量数据库 zillizcloud

火山引擎A/B测试:MAB智能调优实验,企业活动效果提升新利器

字节跳动数据平台

AB testing实战 A/B 测试

财务共享中心搭建以后,如何进行精细化管理?

用友BIP

财务共享

2023数字政府高质量发展论坛在京召开

信通院IOMM数字化转型团队

数字化转型 数字政府 IOMM 政府数字化转型

悦数图数据库:图 + AI 在金融行业的应用及技术前瞻

悦数图数据库

AI 金融 图数据库实战

瑞云科技CTO赵志杰出席广州广告数字创意峰会并发表演讲

3DCAT实时渲染

元宇宙 实时云渲染 云3D渲染

信道的数学模型

timerring

信息论

Web3 游戏的用户留存的挑战与机遇:从经济模型与游戏设计谈起

Footprint Analytics

区块链游戏 web3 web3游戏

聊点技术 | 可观测性十问十答

博睿数据

可观测性 智能运维 博睿数据 发展趋势 聊点技术

轻松掌握,板对板连接器选型指南

元器件秋姐

电路 元器件 PCB 连接器 PCB设计

开源教育与人才|2023开放原子全球开源峰会开源教育和人才分论坛即将启幕

开放原子开源基金会

开源 开放原子 教育与人才

SDK轻量化,降低日均耗电量和日均流量

MobTech袤博科技

单卡轻松打造 ChatGPT 竞争者“原驼”,QLoRA 革新大语言模型微调技术

Zilliz

openai AIGC Towhee ChatGPT

软件测试/测试开发丨接口测试实战学习笔记

测试人

程序员 软件测试 自动化测试 接口测试 测试开发

通义千问预体验,如何让 AI 模型应用“奔跑”在函数计算上?

阿里巴巴云原生

阿里云 云原生 函数计算

wireshark分析tcp传输之文件上传速率问题

蓝胖子的编程梦

TCP 网络 Wireshark tcpdump 抓包

Authing 结合 APISIX 实现统一可配置 API 权限网关(快速启动版)

Authing

API APISIX APISIX 网关 API 接口

快速实现不打折扣的云原生Java应用_服务革新_InfoQ精选文章