在Kubernetes中优化Java无服务器 - Danie


在 Kubernetes 上实现更快的启动、更小的内存占用运行无服务器函数。
由于运行数千个应用程序 pod 的费用以及使用更少的工作节点和其他资源来节省成本,在Kubernetes 中更快的启动和更小的内存占用总是很重要的。在 Kubernetes 上的容器化微服务上,内存比吞吐量更重要,因为:

  • 由于永久性(与 CPU 周期不同),它更昂贵
  • 微服务成倍增加开销成本
  • 一个单体应用变成N 个微服务(例如,20 个微服务 ≈ 20GB)

这会显着影响无服务器功能开发和 Java 部署模型。这是因为许多企业开发人员选择了 Go、Python 和 Nodejs 等替代方案来克服性能瓶颈——直到现在,多亏了Quarkus,一个新的 Kubernetes 原生 Java 堆栈。本文介绍了如何优化 Java 性能以使用 Quarkus 在 Kubernetes 上运行无服务器功能。
 
容器优先设计
Java 生态系统中的传统框架在初始化这些框架所需的内存和启动时间方面是有代价的,包括配置处理、类路径扫描、类加载、注释处理以及构建世界的元模型,框架需要这些操作。对于不同的框架,这一次又一次地成倍增加。Quarkus 通过将几乎所有开销“左移”到构建阶段来帮助解决这些 Java 性能问题。通过在构建时只进行一次代码和框架分析、字节码转换和动态元模型生成,您最终会得到一个高度优化的运行时可执行文件,它启动速度超快,并且不需要传统启动的所有内存,因为工作在构建阶段完成一次。
更重要的是,Quarkus 允许您构建具有性能优势的本机可执行文件,包括惊人的快速启动时间和非常小的驻留集大小 (RSS) 内存,与传统云相比,可实现即时扩展和高密度内存利用率——本机 Java 堆栈。
 
下面是一个快速示例,说明如何使用 Quarkus通过Java 无服务器项目构建本机可执行文件。
1. 创建 Quarkus 无服务器 Maven 项目
此命令生成一个 Quarkus 项目(例如,quarkus-serverless-native)来创建一个简单的函数:
$ mvn io.quarkus:quarkus-maven-plugin:1.13.4.Final:create \
       -DprojectGroupId =org.acme \
       -DprojectArtifactId =quarkus-serverless-native \
       -DclassName = "org.acme.getting.started.GreetingResource"

2. 构建原生可执行文件
您需要一个 GraalVM 来为 Java 应用程序构建本机可执行文件。您可以选择任何 GraalVM 发行版,例如Oracle GraalVM 社区版 (CE)Mandrel(Oracle GraalVM CE 的下游发行版)。Mandrel 旨在支持在 OpenJDK 11 上构建 Quarkus 原生可执行文件。
打开pom.xml,您将找到此native配置文件。您将使用它来构建本机可执行文件:

<profiles >
    <profile >
        <id > native </id >
        <properties >
            <quarkus.package.type > native </quarkus.package.type >
        </properties >
    </profile >
</profiles >

假设您已经启动了容器运行时,请运行以下 Maven 命令之一。
对于Docker

$ ./mvnw package -Pnative \
-Dquarkus.native.container-build=true \
-Dquarkus.native.container-runtime=docker

对于 Podman::
$ ./mvnw package -Pnative \
-Dquarkus.native.container-build=true \
-Dquarkus.native.container-runtime=podman

在没有 Java 虚拟机 (JVM) 的情况下直接运行本机可执行文件:
$ target/quarkus-serverless-native-1.0.0-SNAPSHOT-runner
超音速!19 毫秒启动。时间可能因您的环境而异。

正如 Linuxps实用程序报告的那样,它还具有极低的内存使用率。在应用程序运行时,在另一个终端中运行此命令:
$ ps -o pid,rss,command -p $(pgrep -f runner)
 
 将函数部署到 Knative 服务
请在OKD(OpenShift Kubernetes 分发版)上创建一个命名空间(例如,)以将此本机可执行文件部署为无服务器功能。然后为 Knative 服务部署添加一个扩展:quarkus-serverless-nativequarkus-openshift
$ ./mvnw -q quarkus:add-extension -Dextensions="openshift"
添加以下变量src/main/resources/application.properties以配置 Knative 和 Kubernetes 资源:

quarkus.container-image.group=quarkus-serverless-native
quarkus.container-image.registry=image-registry.openshift-image-registry.svc:5000
quarkus.native.container-build=true
quarkus.kubernetes-client.trust -certs=true
quarkus.kubernetes.deployment-target=knative
quarkus.kubernetes.deploy=true
quarkus.openshift.build-strategy=docker

构建原生可执行文件,然后直接部署到OKD集群:
$ ./mvnw clean package -Pnative

输出应以BUILD SUCCESS. 完成原生二进制构建并部署新的 Knative 服务需要几分钟时间。成功创建服务后,您应该使用kubectl或oc命令工具看到 Knative 服务 (KSVC) 和修订版 (REV) :

$ kubectl get ksvc
NAME URL   [ ... ]
quarkus-serverless-native http: // quarkus-serverless-native- [ ... ] .SUBDOMAIN True

$ kubectl get rev
NAME CONFIG NAME K8S SERVICE NAME GENERATION READY REASON
quarkus-serverless -native-00001 quarkus-serverless-native quarkus-serverless-native-00001   1            

 
访问原生可执行函数
通过运行以下kubectl命令检索无服务器函数的端点 :
$ kubectl get rt/quarkus-serverless-native

访问路由URL与curl命令:
$ curl http://quarkus-serverless-restapi-quarkus-serverless-native.SUBDOMAIN/hello

当您访问 OKD 集群中 Quarkus 运行 pod 的日志时,您将看到本机可执行文件正在作为 Knative 服务运行。