AWS:将 OpenAPI 与 Amazon API Gateway 和 Lambda 函数集成

了解如何使用 OpenAPI 采用 IaC 方法,包括以可重复和确定的方式定义 API。

API 网关是一种 AWS 服务,它允许将应用程序的后端与其前端连接起来。下图显示了此类应用程序的示例,由基于 Web/移动设备的前端和驻留在 REST API 中的后端组成,实现为一组无服务器 Lambda 函数,以及许多遗留服务.
基于 Web/移动设备的前端和驻留在 REST API 中的后端,实现为一组无服务器 Lambda 函数,以及许多遗留服务

上图说明了所谓的设计模式遗留 API 代理,正如 Peter Sbarski、Yan Cui 和 Ajay Nair 在他们的优秀著作《AWS 上的无服务器架构》(Manning,2022 年)中所描述的那样。此模式指的是一起使用 Amazon API Gateway 和 Lambda 的用例,以便在遗留 API 和服务上创建新的 API 层,以便调整和重用它们。在此设计中,API 网关公开了一个调用 Lambda 函数的 REST 接口,这些函数反过来修改请求和响应或将数据转换为特定于旧版的格式。这样,不支持旧协议的现代客户端可能会使用旧服务。

当然,这可以使用 AWS 控制台来完成,方法是选择 API 网关服务,并代表建议的 GUI(图形用户界面)浏览数十个可能的选项,大约一小时后,来一个功能骨架。当我们的 API 规范发生变化时,即每月发生几次变化,我们需要从头开始。

我们将不采取相应行动。我们宁愿采用IaC(基础设施即代码)方法,以可重复和确定的方式定义我们的 API。这可以通过多种方式完成,例如使用AWS CLI(命令行解释器)、CloudFormation或Terraform通过基于脚本的自动化过程。但大多数开发人员更喜欢另一个有趣的替代方案:OpenAPI。我们选择在这里使用的就是这个替代方案,如进一步所示。

使用 OpenAPI 设计 REST 接口
2011 年,一家专门从事测试和监控工具的小公司 SmartBear Software 开发了 Swagger,这是一组专门用于创建和记录 RESTful 服务的实用程序。几年后的 2015 年 11 月,在 Linux 基金会的支持下,这家公司宣布成立一个名为 OpenAPI Initiative 的新组织。其他专业,如谷歌、IBM 等,作为创始成员承诺。2016 年 1 月,Swagger 更名,成为 OpenAPI。

OpenAPI 是一种基于 YAML 符号的形式主义,也可以用 JSON 表示。它旨在以与语言无关的方式定义 REST API。目前有很多围绕 OpenAPI 的工具,就这些工具及其使用而言,我们的目标不是广泛研究对我们开放的所有可能性。最常见的用例之一可能是登录到 SwaggerHub 在线服务,创建一个新的 API 项目,导出生成的 YAML 文件,并将其与 SAM(无服务器应用程序模型)工具结合使用以公开给定的 API通过亚马逊 API 网关。

由于我们需要说明上述运作方式,因此让我们考虑名为 的汇款服务的用例send-money。顾名思义,这项服务负责执行银行账户转账。它公开了一个 REST API,其规范如下表所示:
这个简单的用例由CRUD(创建、读取、更新、删除)组成并作为 REST API 公开,是我们选择在此处实施的用例,以便说明上述场景,以下是所需的步骤:

转到SwaggerHub 上的 Send Money API。在这里,您会找到一个已经准备好的项目,其中显示了上表中定义的 REST API 的 OpenAPI 规范。这是一个公共项目,为了获得访问权限,不需要注册和登录。
您将看到类似于下图中的屏幕:
SwaggerHub 项目
此屏幕在其左侧窗格中显示了我们 API 的 OpenAPI 描述。再一次,对 OpenAPI 表示法的完整解释不在我们的讨论范围之内,因为这个主题可能会成为整本书的主题,例如 Joshua S. Ponelat 和 Lukas L. Rosenstock 的优秀著作,标题为 Designing APIs with Swagger和OpenAPI(曼宁 2022)。

屏幕的右侧窗格示意性地显示了我们 API 的 HTTP 请求,并允许对其进行测试等。您可能会花一些时间浏览屏幕的这一部分,方法是单击标有 HTTP 请求的按钮,然后选择Try it out。请注意,这些测试是模拟的,当然,因为它们背后没有具体的实现。但是,它们允许您从句法和语义的角度确保正确定义了 API。

现在您已经玩完了测试界面,您可以使用Export -> Download API -> YAML Resolved位于屏幕右上角的功能以 YAML 格式下载我们的 API OpenAPI 定义。事实上,您实际上不必这样做,因为您可以在用于举例说明此博客票证的 Maven 项目中找到相同的文件。

现在让我们快速浏览一下这个 YAML 文件。我们注意到的第一件事是定义openapi:我们正在使用的符号版本的声明:在本例中为 3.0.0。标记的部分info标识了一般信息,如 API 名称、作者和相关的联系方式等。

下一个元素,labeledservers:定义了自动模拟功能。它允许我们在 SwagerHub 站点之外运行模拟测试。只需复制此处声明的 URL 并将其用于您首选的浏览器。

paths:最后但同样重要的是,我们在定义 API 端点的地方标记了元素。有两个这样的端点:/orders和/orders/{ref}。对于每一个,我们都定义了关联的 HTTP 请求、它们的参数以及响应,包括 HTTP 标头。OpenAPI 是一种不可知论符号,因此,它不受任何特定技术、框架或编程语言的约束。但是,可以使用特定于 AWS 的扩展。这些扩展之一是x-amazon-apigateway-integration允许 REST 端点连接到 API 网关。正如您在查看 OpenAPI YAML 定义时看到的那样,每个端点都包含一个标记为标签的元素x-amazon-apigateway-integration,其中声明了调用将被转发到的 Lambda 函数的 URL。

该项目
好的,我们有 API 的 OpenAPI 规范。为了从中生成 API 网关堆栈并将其部署在 AWS 上,我们将使用 SAM,如上所述。有关 SAM 及其使用方法的更多详细信息,请随时查看此处。

可以在此处找到包含所有必需元素的 Java 项目。从 GitHub 克隆它后,打开文件template.yaml. 我们在下面重现它:

AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: Send Money SAM Template
Globals:
Function:
Runtime: java11
MemorySize: 512
Timeout: 10
Tracing: Active
Parameters:
BucketName:
Type: String
Description: The name of the S3 bucket in which the OpenAPI specification is stored
Resources:
SendMoneyRestAPI:
Type: AWS::Serverless::Api
Properties:
Name:
send-money-api
StageName:
dev
DefinitionBody:
Fn::Transform:
Name: AWS::Include
Parameters:
Location:
Fn::Join:
- ''
- - 's3://'
- Ref: BucketName
- '/openapi.yaml'
MoneyTransferOrderFunction:
Type: AWS::Serverless::Function
Properties:
FunctionName: MoneyTransferOrderFunction
CodeUri: send-money-lambda/target/send-money.jar
Handler: fr.simplex_software.aws.lambda.send_money.functions.MoneyTransferOrder::handleRequest
Events:
GetAll:
Type: Api
Properties:
RestApiId:
Ref: SendMoneyRestAPI
Path: /orders
Method: GET
Get:
Type: Api
Properties:
RestApiId:
Ref: SendMoneyRestAPI
Path: /orders
Method: GET
Create:
Type: Api
Properties:
RestApiId:
Ref: SendMoneyRestAPI
Path: /orders
Method: POST
Update:
Type: Api
Properties:
RestApiId:
Ref: SendMoneyRestAPI
Path: /orders
Method: PUT
Delete:
Type: Api
Properties:
RestApiId:
Ref: SendMoneyRestAPI
Path: /orders
Method: DELETE
ConfigLambdaPermissionForMoneyTransferOrderFunction:
Type: "AWS::Lambda::Permission"
DependsOn:
- SendMoneyRestAPI
Properties:
Action: lambda:InvokeFunction
FunctionName: !Ref MoneyTransferOrderFunction
Principal: apigateway.amazonaws.com


我们的template.yaml文件将创建一个包含 API 网关的 AWS CloudFormation 堆栈。这个 API 网关将根据我们刚刚讨论的 OpenAPI 规范生成。DefinitionBody资源中的元素表示SendMoneyAPIAPI 的端点由位于 S3 存储桶中的名为文件描述openapi.yaml,该名称作为输入参数传递。这里的想法是,我们需要创建一个新的 S3 存储桶,将我们的 OpenAPI 规范以文件的形式复制到其中yaml,并将该存储桶用作包含 API 网关的 AWS CloudFormation 堆栈的输入源。

一个名为 的 Lambda 函数MoneyTransferOrderFunction也在同一个 SAM 模板中定义。该CodeUri参数配置包含关联代码的 Java 存档的位置,而参数Handler声明实现 AWS Lambda 请求处理程序的 Java 方法的名称。最后但同样重要的是,事件段落设置了我们的 Lambda 函数正在服务的 HTTP 请求。如您所见,有 5 个端点,标记如下(每个都在 OpenAPI 规范中定义):

GetAll映射到GET /orders操作
Get映射到GET /orders/{ref}操作
Create映射到POST /orders操作
Update映射到PUT /orders操作
Delete映射到DELETE /orders/{ref}操作
要构建和部署项目,请按照下面的清单所示进行操作:

$ mkdir test-aws
$ cd test-aws
$ git clone https://github.com/nicolasduminil/aws-showcase
...
$mvn package
...
$ ./deploy.sh
...
make_bucket: bucketname-3454
upload: ./open-api.yaml to s3://bucketname-3454/openapi.yaml
Uploading to 73e5d262c96743505970ad88159b929b 2938384 / 2938384 (100.00%)

Deploying with following values
===============================
Stack name : money-transfer-stack
Region : eu-west-3
Confirm changeset : False
Disable rollback : False
Deployment s3 bucket : bucketname-3454
Capabilities : ["CAPABILITY_IAM"]
Parameter overrides : {"BucketName": "bucketname-3454"}
Signing Profiles : {}

Initiating deployment
=====================

Uploading to b0cf548da696c5a94419a83c5088de48.template 2350 / 2350 (100.00%)


Waiting for changeset to be created..

CloudFormation stack changeset
...
Successfully created/updated stack - money-transfer-stack in eu-west-3

Your API with ID mtr6ryktjk is deployed and ready to be tested at https://mtr6ryktjk.execute-api.eu-west-3.amazonaws.com/dev


在此清单中,我们首先克隆包含该项目的 Git 存储库。然后,我们执行 Maven 构建,它将在执行一些单元测试后打包名为 的Java存档。send-money-lambda.jar

脚本deploy.sh,顾名思义,负责有效地完成部署操作。其代码转载如下:

#!/bin/bash
RANDOM=$
BUCKET_NAME=bucketname-$RANDOM
STAGE_NAME=dev
AWS_REGION=$(aws configure list | grep region | awk '{print $2}')
aws s3 mb s3://$BUCKET_NAME
echo $BUCKET_NAME > bucket-name.txt
aws s3 cp open-api.yaml s3://$BUCKET_NAME/openapi.yaml
sam deploy --s3-bucket $BUCKET_NAME --stack-name money-transfer-stack --capabilities CAPABILITY_IAM --parameter-overrides BucketName=$BUCKET_NAME
aws cloudformation wait stack-create-complete --stack-name money-transfer-stack
API_ID=$(aws apigateway get-rest-apis --query "items[?name=='send-money-api'].id" --output text)
aws apigateway create-deployment --rest-api-id $API_ID --stage-name $STAGE_NAME >/dev/null 2>&1
echo "Your API with ID $API_ID is deployed and ready to be tested at https://$API_ID.execute-api.$AWS_REGION.amazonaws.com/$STAGE_NAME"


我们在这里使用$生成随机数的 Linux 命令。通过将这个随机生成的数字附加到将用于存储 OpenAPI 规范文件的 S3 存储桶名称,我们满足了它在区域范围内的唯一性条件。此存储桶名称进一步存储在本地文件中,以便以后可以检索和清理。另请注意aws configure用于获取当前 AWS 区域的命令。

该命令aws s3 mb正在创建 S3 存储桶。这里mb声明make bucket。创建存储桶后,我们将使用它来存储open-api.yaml包含 API 规范的文件。这是代表命令完成的aws s3 cp。

现在,我们准备开始部署过程。这是通过sam deploy命令完成的。由于此操作可能需要一段时间,因此我们需要等到 AWS CloudFormation 堆栈完全创建后再继续。这是由 statement 完成的aws cloudformation wait,如上面的清单所示。

最后一个操作是部署之前创建的 API 网关,通过运行命令完成aws apigateway create-deployment。这里我们需要将代表命令检索的 API 网关标识符作为输入参数传递aws apigateway get-rest-api,它返回有关当前所有 API 网关的信息。然后,使用该--query选项,我们在 JSON 负载中进行过滤,以找到我们的,名为send-money-api.

在执行结束时,脚本会显示新创建的 API 网关的 URL。这是可用于测试目的的 URL。例如,您可以使用 Postman(如果您安装了它),或者只是使用 AWS 控制台,这有利于一个漂亮且直观的测试界面。

如果您决定使用 AWS 控制台,则需要选择 API 网关服务,您将看到所有当前存在的服务的列表。单击命名的send-money-api将显示要测试的端点列表。为此,您当然需要先创建一个新的汇款单。您可以通过将下面的 JSON 有效负载粘贴到请求正文中来执行此操作:

{
"amount": 200,
"reference": "reference",
"sourceAccount": {
"accountID": "accountId",
"accountNumber": "accountNumber",
"accountType": "CHECKING",
"bank": {
"bankAddresses": [
{
"cityName": "poBox",
"countryName": "countryName",
"poBox": "cityName",
"streetName": "streetName",
"streetNumber": "10",
"zipCode": "zipCode"
}
],
"bankName": "bankName"
},
"sortCode": "sortCode",
"transCode": "transCode"
},
"targetAccount": {
"accountID": "accountId",
"accountNumber": "accountNumber",
"accountType": "CHECKING",
"bank": {
"bankAddresses": [
{
"cityName": "poBox",
"countryName": "countryName",
"poBox": "cityName",
"streetName": "streetName",
"streetNumber": "10",
"zipCode": "zipCode"
}
],
"bankName": "bankName"
},
"sortCode": "sortCode",
"transCode": "transCode"
}
}

如果出现在 AWS 控制台中的状态代码是 200,则操作成功,现在您可以测试这两个GET操作,一个检索所有现有的汇款单,另一个获取其引用标识的汇款单。对于最后一个,您需要使用GET汇款单参考的值初始化 HTTP 请求的输入参数,在我们的测试中,它只是“参考”。

为了测试该PUT操作,只需将之前用于测试 的相同 JSON 有效负载粘贴到其主体中POST,并对其稍作修改。例如,将金额修改为 500 而不是 200。现在再次测试这两个GET操作,它们应该会检索到新更新的汇款单,这次的金额为 500。

玩完 AWS 控制台界面后,测试该DELETE操作并将相同的引用粘贴到其输入参数中。之后,这两个GET操作应该返回一个空的结果集。

如果您厌倦了使用 AWS 控制台,可以切换到提供的集成测试。首先,您需要FunctionsIT在send-money-lambdaMaven 模块中打开该类。在这里,您需要确保命名的静态常量与脚本AWS_GATEWAY_URL显示的 URL 相匹配deploy.sh。然后按如下方式编译并运行集成测试:

mvn test-compile failsafe:integration-test



您应该会看到显示所有集成测试都已成功的统计信息。


展开阅读全文

页面更新:2024-03-10

标签:函数   汇款单   控制台   网关   命令   定义   参数   操作   文件   测试

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top