该文章由首席解决方案架构师 Dennis Kieselhorst 撰写。
在过去的 25 年里,Java 以其可移植性、效率、社区支持和众多特性,成为企业构建应用程序的首选语言。AWS Lambda的出现引入了无服务器功能,这改变了我们对编程语言和运行环境的需求。无服务器功能通常是短暂的、单一用途的,并且不需要复杂的基础设施配置。
本文展示了如何利用更新的 将一个遗留的 Java应用程序现代化,使其在 Lambda 上运行,且只需最少的代码更改。
经典的 Java 企业应用程序通常运行在 JBoss/WildFly、Oracle WebLogic、IBM WebSphere 等应用服务器上,或在 Apache Tomcat 等 Servlet 容器中。底层的 Java 虚拟机通常 24/7 运行,并利用多线程技术处理多个请求。

在构建 Java 的 Lambda 函数时,HTTP 服务器不再必要,同时在 Lambda环境中运行代码需要考虑其他因素。代码在执行环境中运行,每次处理一个请求。函数最多运行 15 分钟,并且最大可以分配 10GB 的内存。
函数是由 触发的,例如带有有效负载的 HTTP 请求。一个 HTTP 请求会调用该函数,并传入对应的 JSON有效负载:

用于处理这些事件的代码与传统应用中的实现方式不同。
使得在 Lambda 中运行使用 Spring、Spring Boot、或者 JAX-RS/Jersey 等框架编写的 Java应用程序变得更简单。
该容器提供适配器逻辑,以最小化代码变更。传入事件被翻译为 ,使得框架可以如同以往那样工作。

该库的第一个版本于 2018 年发布。如今,AWS 正在宣布第二版的发布,该版本支持最新的 Jakarta EE 规范,以及 SpringFramework 6.x、Spring Boot 3.x 和 Jersey 3.x。
下面的示例展示了如何迁移一个 Spring Boot 3 应用程序的过程。您可以在 找到 Spring 和其他框架的完整示例。
xml <dependency> <groupId>com.amazonaws.serverless</groupId> <artifactId>aws- serverless-java-container-springboot3</artifactId> <version>2.0.0</version> </dependency>
xml <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <configuration> <createDependencyReducedPom>false</createDependencyReducedPom> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <artifactSet> <excludes> <exclude>org.apache.tomcat.embed:*</exclude> </excludes> </artifactSet> </configuration> </execution> </executions> </plugin> </plugins> </build>
AWS Serverless Java Container 接受 API Gateway 代理请求,并将其转换为普通的 Java对象。该库还会将输出转换为适合的 API Gateway 响应对象。
一旦您运行构建过程,Maven 的 Shade 插件将生成一个包含所有依赖项的 Uber-JAR 文件,您可以将其 。
SpringDelegatingLambdaContainerHandler 实现,或 来委托给 AWS Serverless Java Container。如果您想添加额外功能,这种方式非常有用。
MAIN_CLASS 的 ,以便于通用处理程序知道在哪里查找您原始应用程序的主类,通常该类标注了 @SpringBootApplication。
您也可以使用基础设施即代码 (IaC) 工具如 、AWS 云开发工具包 (AWSCDK) 或 AWS 无服务器应用程序模型 (AWSSAM) 配置这些设置。
在 AWS SAM 模板中,相关更改如下。完整模板的内容可以在 找到。
yaml Handler: com.amazonaws.serverless.proxy.spring.SpringDelegatingLambdaContainerHandlerEnvironment: Variables: MAIN_CLASS: com.amazonaws.serverless.sample.springboot3.Application
在运行 Lambda 函数时,启动时间和内存占用是重要的考量因素。您为 Lambda 函数配置的内存量还决定了可用的虚拟 CPU数量。增加更多内存会成比例增加 CPU 的数量,从而提高整体计算能力。如果一个函数是 CPU、网络或内存密集型的,增加更多内存可能会改善其性能。
Lambda 按照函数消耗的总字节-秒(gigabyte-seconds)收费。字节-秒是内存总量(以 GB为单位)和持续时间(以秒为单位)的组合。增加内存会产生额外成本。然而,在许多情况下,增加可用的内存会因增加了 CPU而导致函数执行时间减少。因此,在获得额外性能的情况下,总的成本增加可能微不足道,甚至可能下降。
选择分配给 Lambda函数的内存是一个优化过程,需要平衡速度(执行时长)和成本。您可以手动测试函数,通过选择不同的内存分配并测量完成时间来评估性能。 是一个简化和自动化该过程的工具,您可以使用它来优化配置。
Power Tuning 使用 在不同内存分配下运行多个并行版本的 Lambda 函数,并测量其性能。该函数在您的 AWS 账户中运行,执行实时 HTTP 调用和 SDK交互,以测量生产环境中的性能。
传统应用程序往往具有庞大的依赖树。Lambda 在函数生命周期的
加载函数代码并初始化依赖项。对于许多依赖项,初始化时间可能超出您的要求。 对于基于 Java 的函数可以提供高达 10 倍的启动性能。
Lambda SnapStart 在每次冷启动时,不再重复执行函数初始化过程,而是在部署时执行函数初始化过程。Lambda会对初始化的执行环境拍摄快照。此快照经过加密并保存在分层缓存中,以便快速访问。当函数被调用并扩展时,Lambda会从持久化的快照恢复执行环境,而不是执行完整的初始化过程。这大大减少了启动延迟。
要 ,您首先必须启用配置设置,并且还要 。

确保您的 API Gateway 端点指向发布的版本或 ,以确保您使用的是启用了 SnapStart 的函数。
在 AWS SAM 模板中的对应设置为:
yaml SnapStart: ApplyOn: PublishedVersions AutoPublishAlias: my-function- alias
请阅读 文档,因为您的应用程序可能包含需要注意的特定代码。
在构建无服务器应用程序时,使用 Lambda 使功能开发更快速,但您的语言和运行时必须符合无服务器架构模型。AWS Serverless JavaContainer 帮助传统 Java 企业应用程序和现代云原生无服务器函数之间建立桥梁。
您可以使用 AWS Lambda Power Tuning 工具来优化 Java Lambda 函数的内存配置,并通过启用 SnapStart来优化初始冷启动时间。
可以通过自学的 研讨会,学习如何构建云原生 Java 应用程序以及将现有 Java 应用程序迁移至 Lambda。
探索 的 GitHub 仓库,您可以在此报告相关 。
欲获取更多无服务器学习资源,请访问 。
标签 :,
Leave a Reply