技术领域 - AWS 规范性指导

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

技术领域

此部分提供了容器化主要技术领域概述。传统的 Java EE 应用程序的架构如下图所示。

重构的 Java EE 应用程序

容器化的 Java EE 应用程序的架构如下图所示。

重构的 Java EE 应用程序

1. 会话状态

在大多数情况下,Java EE 应用程序存储与用户请求相关的会话数据,例如 servlet 的 Cookie 和 Enterprise Java Bean(EJB)有状态会话。我们建议您不要将状态信息存储在 Java 虚拟机(JVM)内存中,因为您的容器必须保持无状态状态。有关一次性原则的更多信息,请参阅 Red Hat 文档中的基于容器的应用程序设计原理。在 Java EE 中,有两种类型的会话数据:HTTP 会话数据和 EJB 会话数据。应用程序服务器可以永久保存 HTTP 和 EJB 会话数据。多个传统应用程序服务器支持内存复制以提高此会话数据的可用性,例如 IBM WebSphere 应用程序服务器上的 Infinispan RedHat JBoss 和 Data Replication Server 上的数据复制服务。

内存复制机制假设集群中始终存在一组特定的服务器,或者有少数服务器加入或离开集群。这与容器环境不兼容,因此我们建议您取消内存复制机制。在容器环境中,在构建新版本的容器映像时,会重新部署应用程序服务器。也就是说,所有复制的内存数据也会被擦除。

2. 代理

在单个物理或虚拟服务器上有多个正在运行的代理进程,它们通常执行自动化和实用任务,例如:

  1. 监控 — 传统的 Java EE 应用程序环境通常使用专用的代理进行监控。这些代理负责监控服务器 CPU、内存、磁盘使用情况、JVM 内部的内存使用情况、日志消息等。但是,不可能在容器环境中直接运行监控代理。您必须将监控代理替换为容器平台提供的监控机制,例如 Amazon CloudWatch 和 Amazon CloudWatch Logs。

  2. 作业(计划任务)— 在传统的 Java EE 应用程序环境中,作业执行环境通常与应用程序服务器位于同一台服务器上,除了用户请求外,还负责长时间运行的批处理过程。例如,由作业控制器控制的批处理过程访问数据库以检索数据并创建报告。由于这些多个工作负载无法在容器环境中共存,因此必须将作业和批处理执行环境与容器环境分开构建。

  3. 文件传输功能 — 文件传输功能代理在 Java EE 应用程序环境中通常不那么常见,但它们有时在与 Java 应用程序相同的操作系统上运行,作为与外部应用程序相互交换文件的独立过程。例如,其他应用程序使用的数据每天都会传输到一个文件并反映在数据库中。文件传输功能代理不能在容器旁边运行,但必须在另一台可以访问数据库和文件的服务器上运行。

3. 应用程序服务器

容器化的最大挑战是更改应用程序服务器。传统的 Java EE 兼容应用程序服务器采用静态计算环境,因此它们可能不适合在容器环境中运行。也就是说,假设物理或虚拟服务器是 Java EE 应用程序计算环境的实体。例如,专有 Java EE 应用程序服务器,例如传统的 IBM WebSphere 应用程序服务器 (TWA) 和 Oracle WebLogic Server,都有自己的应用程序部署机制。

在容器环境中,情况有所不同。在此环境中,容器包括应用程序服务器和带有应用程序构建包(例如 .war 和 .jar 文件)的运行时系统,并部署到 Amazon ECS 或 Amazon EKS 等容器平台。我们建议您使用容器平台机制将应用程序部署到环境中。应用程序服务器经常使用容器部署,因此它们必须体积小(小于 500 MB)且启动速度必须快。为了满足此要求,您可能需要更改传统的应用程序服务器,并迁移到更适合容器的应用程序服务器。这可能需要从 IBM WebSphere 应用程序服务器迁移到 IBM Liber WebSphere ty,或者将 JBoss企业应用程序平台 (EAP) 迁移到 WildFly。

我们建议您考虑更改应用程序服务器可能产生的以下影响:

  1. 通过环境变量注入配置(与配置存储在文件中的传统的 Java EE 应用程序(例如 web.xml)形成鲜明对比)

  2. 与 Java EE 功能的兼容性

  3. JVM 版本

4. 文件存储

传统 Java EE 应用程序最常用的文件存储是本地文件系统。最常见的使用案例包括应用程序日志文件、应用程序生成的文件(例如业务报告)和用户上传的内容。我们建议您不要将文件存储在容器内,因为容器是无状态的,这意味着需要对文件存储进行外部化才能进行容器化。

考虑以下容器化选项:

  1. Amazon Elastic File System(Amazon EFS) — Amazon EFS 是一项托管 NFS 服务,可通过容器进行访问。Amazon EFS 已与 Amazo ECS 和 Amazo EKS 集成。如果您使用 Amazon EFS,则无需编写自定义脚本即可将 EFS 卷挂载到您的容器中。此选项的第一步是列出应用程序中用于读取或写入的所有文件系统路径。确定要永久保留的文件系统路径后,可以将文件系统路径映射到 EFS 文件系统路径。有关更多信息,请参阅 Amazon ECS 文档中的教程:将 Amazon EFS 文件系统用于 Amazon ECS。并非所有路径都需要永久保存,尤其是应用程序日志文件。大多数企业应用程序将日志文件写入本地文件系统。作为容器化过程的一部分,我们建议您考虑更改日志目标以使用标准输出和标准错误。这使您无需管理 CloudWatch 日志存储大小和性能即可将所有输出捕获到日志。有关 Amazon ECS 的日志记录的更多信息,请参阅 Amazon ECS 文档中的使用 awslogs 日志驱动程序

  2. Amazon Simple Storage Service(Amazon S3)— Amazon S3 比 Amazon EFS 便宜,支持的带宽也比 Amazon EFS 更大,但与 Amazon EFS 相比,Amazon S3 需要对应用程序代码进行更大范围的更改。这是因为 Amazon S3 不是文件系统。

5. 构建和部署流程

容器化过程涉及更改和扩展应用程序交付流程。在传统环境中,应用程序交付过程主要涉及 Java 构件(例如 .war 和 .ear 文件)。在容器环境中,交付单元则是容器映像。除了构建现有 Java 构件的过程外,您还必须构建用于构建和交付 Docker 容器的流程。有关管道流程的更多信息,请参阅 AWS 规范性指南文档中的使用 CI/CD 管道自动构建 Java 应用程序并将其部署到 Amazon EKS

6. 数据库访问

传统的应用程序容器化通常伴随着数据库迁移。为了降低迁移风险,我们建议遵循关系数据库的迁移策略(AWS 规范性指南)。容器化环境需要外部化配置,包括数据库连接字符串。您可以使用诸如 Spring Cloud Config(GitHub 存储库)之类的工具在分布式环境中将 Java 应用程序配置外部化。