这AWS控制台允许用户以用户友好的方式创建和更新云基础架构资源。尽管这种高级工具可能具有所有优势,但使用它是重复的且容易出错。例如,每次我们使用AWS控制台创建Lambda函数时,我们都需要一次又一次地重复相同的操作,即使这些操作像图形小部件操作一样直观和简单,整个过程也是耗时费力的。这种工作模式便于快速原型制作,但是一旦我们不得不从事范围和持续时间相对较大的实际项目时,它就不再符合团队的目标和愿望了。在这种情况下,首选解决方案是基础设施即代码.
IaC本质上包括使用声明性符号来指定基础设施资源。在AWS的情况下,这种以基于JSON或YAML语法的形式表示的符号在配置文件中被捕获并提交给云的形成IaC实用程序。
云的形成是一个庞大的话题,无法在博客门票中详细说明。我们需要记住的重要一点是,该服务能够处理输入配置文件,并保证相关AWS云基础架构资源的创建和更新。虽然CloudFormation IaC方法的优势是显而易见的,但该工具以冗长、笨拙和不灵活而闻名。幸运的是,AWS Lambda开发人员可以选择使用SAM,这是CloudFormation的超集,其中包含一些特殊的命令和快捷方式,旨在简化Java无服务器代码的开发、测试和部署。
安装SAM
安装SAM非常简单:只需遵循指南. 例如,在Ubuntu 22.04 LTS版上安装它非常简单,如下所示:
$ sudo apt-get update
...
$ sudo apt-get install awscli
...
$ aws --version
aws-cli/2.9.12 Python/3.9.11 Linux/5.15.0-57-generic exe/x86_64.ubuntu.22 prompt/off
用SAM在Java中创建AWS Lambda函数
现在SAM已经安装在您的工作站上了,您可以编写和部署您的第一个Java无服务器功能了。当然,我们这里假设您的AWS帐户已经创建,并且您的环境已经配置为可以运行AWS CLI命令.
像云形成一样,SAM基于以下概念模板,它是描述AWS基础设施的YAML格式文本文件。该模板文件默认命名为template.yaml,必须手动创作,以便与SAM模板解剖结构保持一致(完整规范可在这里). 但是写一个template.yaml文件从头开始很难;因此,自动生成它的想法。进入厨师.
CookieCutter是一个允许自动生成代码的开源项目。它在Python世界中被广泛使用,但在这里,我们将在Java世界中使用它。它的做法非常类似于Maven原型之一,因为它能够自动生成完整的Java 语言(一种计算机语言,尤用于创建网站)项目,包括但不限于包、类、配置文件等。生成过程是高度可定制的,并且能够用外部JSON格式文件中定义的值替换出现的字符串,这些字符串由专用语法表示的占位符标记。
这个GitHub仓库 提供了这样一个基于CookieCutter的生成器,它能够生成一个简单但完整的Java项目,可以作为AWS Lambda无服务器功能。下面的清单显示了如何操作:
$ sam init --location https://github.com/nicolasduminil/sam-template
You've downloaded /home/nicolas/.cookiecutters/sam-template before. Is it okay to delete and re-download it? [yes]:
project_name [my-project-name]: aws-lambda-simple
aws_lambda_resource_name [my-aws-lambda-resource-name]: AwsLambdaSimple
java_package_name [fr.simplex_software.aws.lambda.functions]:
java_class_name [MyAwsLambdaClassName]: AwsLambdaSimple
java_handler_method_name [handleRequest]:
maven_group_id [fr.simplex-software.aws.lambda]:
maven_artifact_id [my-aws-function]: aws-lambda-simple
maven_version [1.0.0-SNAPSHOT]:
function_name [AwsLambdaTestFunction]: AwsLambdaSimpleFunction
Select architecture:
1 - arm64
2 - x86_64
Choose from 1, 2 [1]:
timeout [10]:
Select tracing:
1 - Active
2 - Passthrough
Choose from 1, 2 [1]:
命令sam init上面提到了用于生成新Java项目的基于CookieCutter的模板的位置。这个生成过程采用对话框的形式,实用程序在对话框中提出问题并接受答案。每个问题都有默认答案,用户只需输入答案即可接受进入.
一切都是从询问项目名称和我们的选择开始的aws-lambda-simple。需要输入的进一步信息是:
AWS资源名称
马文·加夫(GroupId,ArtifactId,版本)
Java包名称
Java类名
处理器架构
超时值
跟踪配置文件
命令一终止,您就可以在首选IDE中打开新项目并检查生成的代码。完成后,您可以进行第一次构建,如下所示:
$ cd aws-lambda-simple/
nicolas@nicolas-XPS-13-9360:~/sam-test/aws-lambda-simple$ mvn package
[INFO] Scanning for projects...
[INFO]
[INFO] ----------< fr.simplex-software.aws.lambda:aws-lambda-simple >----------
[INFO] Building aws-lambda-simple 1.0.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ aws-lambda-simple ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /home/nicolas/sam-test/aws-lambda-simple/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ aws-lambda-simple ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /home/nicolas/sam-test/aws-lambda-simple/target/classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ aws-lambda-simple ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /home/nicolas/sam-test/aws-lambda-simple/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ aws-lambda-simple ---
[INFO] No sources to compile
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ aws-lambda-simple ---
[INFO] No tests to run.
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ aws-lambda-simple ---
[INFO] Building jar: /home/nicolas/sam-test/aws-lambda-simple/target/aws-lambda-simple-1.0.0-SNAPSHOT.jar
[INFO]
[INFO] --- maven-shade-plugin:3.2.1:shade (default) @ aws-lambda-simple ---
[INFO] Replacing /home/nicolas/sam-test/aws-lambda-simple/target/aws-lambda-simple.jar with /home/nicolas/sam-test/aws-lambda-simple/target/aws-lambda-simple-1.0.0-SNAPSHOT-shaded.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.604 s
[INFO] Finished at: 2023-01-12T19:09:23+01:00
[INFO] ------------------------------------------------------------------------
我们的新Java项目已经构建并打包为一个JAR(Java存档).生成的template.yaml文件定义了所需的AWS云基础架构,如下所示:
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Description: aws-lambda-simple
Resources:
AwsLambdaSimple:
Type: AWS::Serverless::Function
Properties:
FunctionName: AwsLambdaSimpleFunction
Architectures:
- arm64
Runtime: java11
MemorySize: 128
Handler: fr.simplex_software.aws.lambda.functions.AwsLambdaSimple::handleRequest
CodeUri: target/aws-lambda-simple.jar
Timeout: 10
Tracing: Active
该文件是根据生成过程中输入的值创建的。像AWS模板版本和转换版本这样的东西是常量,应该这样使用。所有其他元素都是已知的,因为它们反映了输入数据。必须特别考虑CodeUri指定作为Lambda函数部署的JAR的位置的元素。它包含类AwsLambdaSimple如下图:
public class AwsLambdaSimple
{
private static Logger log = Logger.getLogger(AwsLambdaSimple.class.getName());
public String handleRequest (Map<String, String> event)
{
log.info("*** AwsLambdaSimple.handleRequest: Have received: " + event);
return event.entrySet().stream().map(e -> e.getKey() + "->" + e.getValue()).collect(Collectors.joining(","));
}
}
Java中的Lambda函数可以在以下两种模式下运行:
同步或RequestResponse调用者等待Lambda函数返回的任何响应的模式
异步或Event一种模式,在这种模式下,Lambda平台无需等待即可响应调用者,同时函数继续处理请求,不返回任何进一步的响应
在这两种情况下,该方法handleRequest()顾名思义,上面是处理请求。该请求是作为Map<String, String>.
好吧!现在我们的新Java项目已经生成,而类AwsLambdaSimple如上所述(将被部署最后作为一个AWS Lambda函数)做的不多,但它足够完整,可以演示我们的用例。让我们部署我们的云基础架构。但是首先,我们需要创建一个AWS S3桶,以便在其中存储我们的Lambda函数。最简单的方法如下所示:
$ aws s3 mb s3://bucket-$$
make_bucket: bucket-18468
这里我们刚刚创建了一个名为bucket-18468。AWS S3时段必须在各地区具有唯一的名称。由于很难保证名称的唯一性,我们在这里使用Linux$$生成随机数的函数。
sam deploy --s3-bucket bucket-18468 --stack-name simple-lambda-stack --capabilities CAPABILITY_IAM
Uploading to 44774b9ed09001e1bb31a3c5d11fa9bb 4031 / 4031 (100.00%)
Deploying with following values
===============================
Stack name : simple-lambda-stack
Region : eu-west-3
Confirm changeset : False
Disable rollback : False
Deployment s3 bucket : bucket-18468
Capabilities : ["CAPABILITY_IAM"]
Parameter overrides : {}
Signing Profiles : {}
Initiating deployment
=====================
Uploading to 3af7fb4a847b2fea07d606a80de2616f.template 555 / 555 (100.00%)
Waiting for changeset to be created..
CloudFormation stack changeset
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Operation LogicalResourceId ResourceType Replacement
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ Add AwsLambdaSimpleRole AWS::IAM::Role N/A
+ Add AwsLambdaSimple AWS::Lambda::Function N/A
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Changeset created successfully. arn:aws:cloudformation:eu-west-3:495913029085:changeSet/samcli-deploy1673620369/0495184e-58ca-409c-9554-ee60810fec08
2023-01-13 15:33:00 - Waiting for stack create/update to complete
CloudFormation events from stack operations (refresh every 0.5 seconds)
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ResourceStatus ResourceType LogicalResourceId ResourceStatusReason
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
CREATE_IN_PROGRESS AWS::IAM::Role AwsLambdaSimpleRole -
CREATE_IN_PROGRESS AWS::IAM::Role AwsLambdaSimpleRole Resource creation Initiated
CREATE_COMPLETE AWS::IAM::Role AwsLambdaSimpleRole -
CREATE_IN_PROGRESS AWS::Lambda::Function AwsLambdaSimple -
CREATE_IN_PROGRESS AWS::Lambda::Function AwsLambdaSimple Resource creation Initiated
CREATE_COMPLETE AWS::Lambda::Function AwsLambdaSimple -
CREATE_COMPLETE AWS::CloudFormation::Stack simple-lambda-stack -
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Successfully created/updated stack - simple-lambda-stack in eu-west-3
我们的Java类已经作为AWS Lambda函数成功部署。让我们使用上面介绍的两种调用方法来测试它。
$ aws lambda invoke --function-name AwsLambdaSimpleFunction --payload $(echo "{\"Hello\":\"Dude\"}" | base64) outputfile.txt
{
"StatusCode": 200,
"ExecutedVersion": "$LATEST"
}
$ cat outputfile.txt
"Hello->Dude"
上面的清单演示了同步或RequestResponse祈祷。我们传递一个JSON格式的有效负载作为输入事件,因为它的默认格式是Base64,所以我们需要首先转换它。由于调用是同步的,调用者等待文件中捕获的响应outputfile.txt。正如预期的那样,返回的状态代码是HTTP 200,这意味着请求得到了正确处理。让我们看看异步orEvent祈祷。
$ aws lambda invoke --function-name AwsLambdaSimpleFunction --payload $(echo "{\"Hello\":\"Dude\"}" | base64) --invocation-type Event outputfile.txt
{
"StatusCode": 202
}
这次–invocation-type是Event因此,返回的状态代码是HTTP 202,这意味着请求已被接受但尚未处理。文件output.txt是空的,因为没有结果。
我们展示通过SAM工具在Java中部署AWS Lambda功能的用例到此结束。离开前不要忘记清理环境,跑步:
$ aws s3 rm --recursive s3://bucket-18468
$ aws s3 rb --force s3://bucket-18468
$ aws cloudformation delete-stack --stack-name simple-lambda-stack