将Java应用部署到AWS的Elastic Beanstalk上
本教程分享了一个通过使用亚马逊CDK将Java应用部署到Elastic Beanstalk的简单例子。
我一直在研究亚马逊网络服务,我意识到在亚马逊Elastic Beanstalk(EB)上部署Java应用与部署不需要编译就能运行的应用有些不同。所以这花了我很多时间,我决定分享一个简单的例子,通过使用亚马逊CDK将一个Java应用部署到Elastic Beanstalk。 我们也可以通过很多不同的方式来完成,比如使用EB CLI,但我要讲的是通过使用CDK CLI进行部署。
创建你的应用程序
在开始之前,你可以在GitHub上查看包括已完成的SpringBoot和CDK项目的存储库。
首先,我们需要创建一个简单的Spring boot应用,你应该在创建时添加Spring Web包。如果你没有IntelliJ Idea Ultimate,你可以从这里初始化一个Spring Boot项目。初始化项目后,你应该将你的应用程序构建为一个jar。
$ mvn clean install
当你正确遵循这些步骤时,你的spring boot应用程序的目标文件夹将看起来像这样:
在你运行命令后的'目标'文件
为了部署我们的Spring Boot应用程序,我们将使用AWS云开发工具包(CDK)与Typescript,但你可以使用任何语言代替。首先,我们需要在一个空目录下创建一个CDK应用项目的例子。在一个你想要的空目录下运行这个命令。
$ CDK init app –language typescript
运行这个命令后,你的CDK文件夹会是这样的:

初始化后的CDK文件夹
现在是编码的时候了!我们将对lib/cdk-deployment-stack.ts 文件进行修改。 首先,我们将创建一个S3 bucket资产来存储我们的应用程序,然后创建一个Elastic Beanstalk环境来运行我们的应用程序。
JavaScript
const appName ="EBS-Demo"
const app = new elasticbeanstalk.CfnApplication(this, 'Application', {
applicationName: `${appName}-EB-App`
});
const apiZipped = new s3assets.Asset(this, 'Zipped-Spring-App',{
path: `Path of our application zip`,
});
const appVersionProps = new elasticbeanstalk.CfnApplicationVersion(this, 'Version-1.0', {
applicationName: `${appName}-EB-App`,
sourceBundle: {
s3Bucket: apiZipped.s3BucketName,
s3Key: apiZipped.s3ObjectKey,
},
});
appVersionProps.addDependsOn(app);
有两个构造--由我们的Spring应用组成的S3资产和EB应用版本资源,这是我们可部署代码的迭代。
Elastic Beanstalk可以自动对环境资源执行一些操作,但你需要使用AWS身份和访问管理(IAM)服务定义一些权限。我们将为这些权限向我们的EB角色添加管理策略。
JavaScript
const EbInstanceRole = new iam.Role(this, `${appName}-aws-elasticbeanstalk-ec2-role`, {
assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'),
});
const managedPolicy = iam.ManagedPolicy.fromAwsManagedPolicyName('AWSElasticBeanstalkWebTier')
EbInstanceRole.addManagedPolicy(managedPolicy);
const profileName = `${appName}-EbsDemoProfile`
const instanceProfile = new iam.CfnInstanceProfile(this, profileName, {
instanceProfileName: profileName,
roles: [
EbInstanceRole.roleName
]
});
这些策略和角色将由我们环境实例的OptionSettingProperty来配置。在分配了所有这些之后,我们的环境设置将看起来像这样:
JavaScript
const optionSettingProperties: elasticbeanstalk.CfnEnvironment.OptionSettingProperty[] = [
{
namespace: 'aws:autoscaling:launchconfiguration',
optionName: 'InstanceType',
value: 't3.small',
},
{
namespace: 'aws:autoscaling:launchconfiguration',
optionName: 'IamInstanceProfile',
value: profileName
},
{
namespace: 'aws:autoscaling:launchconfiguration',
optionName: 'IamInstanceProfile',
value: instanceProfile.attrArn,
}
];
现在我们可以创建我们的EB环境了。
JavaScript
const ebs_env = new elasticbeanstalk.CfnEnvironment(this, 'Environmentm', {
environmentName: `${appName}-EB-Env`,
applicationName: `${appName}-EB-App`,
solutionStackName: '64bit Amazon Linux 2 v3.2.7 running Corretto 8',
optionSettings: optionSettingProperties,
versionLabel: appVersionProps.ref,
});
我们正在设置我们刚刚创建的用于配置的'optionSettings'。此外,我们还定义了VersionLabel来让EB知道我们的应用程序压缩包在哪里。SolutionStackName是另一个重要的属性,你可以自由选择你的基础设施,但你必须选择适合你的Spring Boot项目的JDK版本。要查看可用的解决方案堆栈名称,请在任何终端上运行此命令。
$ aws elasticbeanstalk list-available-solution-stacks
部署您的应用程序
在这一点上,你的应用程序将被上传到S3桶,但它还没有被部署。你可以在AWS控制台看到你的Elastic Beanstalk环境和应用程序,但应用程序的URL将无法使用。你需要使用 "Elastic Beanstalk > Environments > EBS-Demo-Env " 页面上的 "Upload and Deploy " 按钮,从版本标签中选择你上传的应用程序。在每次部署时都这样做,听起来一点都不实用,不是吗?所以,我们现在要把它自动化...
只有一个配置可以正确运行Spring应用程序。我们需要告诉Elastic Beanstalk如何运行我们存在于S3中的应用程序。我们将分三步来做这件事:
- 创建Procfile,运行所需的命令来运行上传的应用程序。你可以在Spring Boot应用程序的根目录下创建它,但建议你把它移到名为 "conf " 的文件夹下,以使你的项目树更简洁。Procfile可以只由一条运行jar的命令组成。
属性文件
web: java -jar SpringApp-0.0.1-SNAPSHOT.jar
2.在 'src/main/resources/assembly'目录下创建'bin.xml'。这就配置了我们的Procfile。
XML
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
<id>assembly-descriptor</id>
<baseDirectory>/</baseDirectory>
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<directory>${project.basedir}/conf</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>Procfile</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.build.directory}</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.basedir}</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
</fileSets>
</assembly>
SpringApp/src/main/resources/assembly/bin.xml
我们还将构建格式的输出改为zip。所以我们可以插入代理或额外的包,供我们的应用程序使用。
3.在你的pom.xml中插入汇编插件。
XML
<profiles>
<profile>
<id>build</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>assembly-on-package</id>
<configuration>
<descriptor>src/main/resources/assembly/bin.xml</descriptor>
<finalName>${project.build.finalName}</finalName>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
另外,我们还需要做一个配置,以正确运行spring应用程序。在'64bit Amazon Linux 2 v3.2.5 running Corretto 8'上,Elastic Beanstalk使用的默认端口是5000。我使用了这个端口,但Spring Boot使用的是8080。因此,如果我们直接部署我们的应用程序,EB将无法运行这个。我们可以通过添加这一行来改变我们应用程序的端口 application.properties 文件中。
server.port=5000
此外,我们还可以从 "OptionSettingProperty"中改变Elastic Beanstalk的默认端口,而不是改变Spring应用的端口。
所有的配置都完成了!现在通过使用Spring应用目录下的汇编插件再次运行构建命令。
$ mvn clean install -P build
检查目标文件下的zip文件是否存在:

运行命令后的'目标'文件
你可以记得,我们在创建S3资产时没有填写应用路径。请按以下方式更新你的代码。
JavaScript
const apiZipped = new s3assets.Asset(this, 'Zipped-Spring-Api',{
path:`${__dirname}/../../SpringApp/target/SpringApp-0.0.1-SNAPSHOT.zip`,
})
最后,在你的CDK目录下运行deploy命令,这就结束了。
$ cdk deploy
我们可以看到我们的应用程序在EB上运行。从AWS控制台查看:

转到你的URL地址:
恭喜你!你的应用程序正在云上运行。你的应用程序正在云上运行。不要忘记销毁你的应用程序以防止不需要的发票。
$ cdk destroy
奖金
我简单地谈到了为什么我们要配置我们的 "bin.xml "来在一个压缩文件中构建我们的应用程序。现在我们将在我们的Spring应用程序中使用一个代理。这将帮助我们监控在Elastic Beanstalk上运行的应用程序。通过这样做,我们将能够监控端点的点击率、成功率、延迟信息等。这是一个来自Thundra的名为应用性能监控(APM)的产品。
在你的应用程序中添加一个APM代理是很容易的。你也可以按照文档来做,但我将简单介绍一下如何做。
-
注册Thundra 后,登录并选择 APM。从左侧底部选择 "简介">"项目",然后从这里复制API密钥。不要分享这个ApiKey,要把它当作自己的荣誉来保护:)
-
下载APM代理,并将其移动到Spring应用程序的根目录中。

3.更新procfile,使我们的应用程序与APM代理一起运行。
属性文件
web: java -javaagent:thundra-agent-bootstrap-2.7.50.jar -Dthundra.apiKey=********-****-****-****-************ -Dthundra.agent.application.name=My-Spring-App -jar SpringApp-0.0.1-SNAPSHOT.jar
这就是全部! 当你用'mvn clean install -P build'再次构建你的应用程序时,你会看到我们的压缩文件包括APM代理。最后,你可以重新部署资源并更新应用程序:
$ cdk deploy