带示例的迁移 step-by-step 说明 - Amazon SDK for Java 2.x
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

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

带示例的迁移 step-by-step 说明

本节提供了将当前使用适用SDK于 Java v1.x 的应用程序迁移到适用于 Java 2.x 的应用程序SDK的 step-by-step 指南。第一部分概述了各个步骤,然后是迁移的详细示例。

此处介绍的步骤描述了正常用例的迁移,即应用程序 Amazon Web Services 服务 使用模型驱动的服务客户端进行调用。如果您需要迁移使用更高级别的代码,APIs例如 S3 传输管理器CloudFront预签名,请参阅Amazon SDK for Java 1.x 和 2.x 有什么区别目录下的部分。

此处描述的方法是一个建议。您可以使用其他技术并利用自己的IDE代码编辑功能来达到相同的结果。

步骤概述

1. 首先添加SDK适用于 Java 2.x 的 BOM

通过将适用于 Java 2.x 的 MavenBOM(材料清单)元素添加到您的POM文件中,可以确保所需的所有版本 v2 依赖项都来自同一个版本。SDKPOM你可以同时包含 v1 和 v2 依赖关系。这允许您以增量方式迁移代码,而不必一次全部更改。

<dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>bom</artifactId> <version>2.27.21</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>

您可以在 Maven 中央存储库中找到最新版本

2. 在文件中搜索 v1 类的导入语句

通过扫描应用程序中的文件,找到 v1 导入中IDs使用的 SERVICE _,你会发现IDs使用了唯一的 SERVICE _。SERVICE_ID 是一个简短、唯一的 Amazon Web Services 服务名称。例如,Amazon cognitoidentity Cognito Identity 的 SERVICE _ID。

3. 从 v1 的导入语句中确定 v2 Maven 的依赖关系

找到所有唯一的 v1 SERVICE _ 之后IDs,您可以通过参考来确定 v2 依赖项的相应的 Maven 工件。Package 名称到 Maven 映射关系 artifactId

4. 将 v2 依赖项元素添加到文件中 POM

使用步骤 3 中确定的依赖元素更新 Maven POM 文件。

5. 在 Java 文件中,逐渐将 v1 类更改为 v2 类

当你用 v2 类替换 v1 类时,请进行必要的更改以支持 v2,API例如使用构建器而不是构造函数,以及使用流畅的 getter 和 setter。

6. 从文件中移除 v1 Maven 依赖关系,POM从文件中移除 v1 的依赖关系

将代码迁移到使用 v2 类后,请从文件中移除所有剩余的 v1 导入,并从构建文件中移除所有依赖项。

7. 重构代码以使用 v API 2 增强功能

在代码成功编译并通过测试后,您可以利用 v2 增强功能,例如使用不同的HTTP客户端或分页器来简化代码。此为可选步骤。

迁移示例

在此示例中,我们迁移了一个使用 for Java v1 并访问多个应用程序的应用程序。SDK Amazon Web Services 服务我们在步骤 5 中详细研究了以下 v1 方法。这是包含八个方法的类中的一个方法,应用程序中有 32 个类。

下面仅列出了 Java 文件中的 v1 SDK 导入。

import com.amazonaws.ClientConfiguration; import com.amazonaws.regions.Region; import com.amazonaws.regions.RegionUtils; import com.amazonaws.services.ec2.AmazonEC2Client; import com.amazonaws.services.ec2.model.AmazonEC2Exception; import com.amazonaws.services.ec2.model.CreateTagsRequest; import com.amazonaws.services.ec2.model.DescribeInstancesRequest; import com.amazonaws.services.ec2.model.DescribeInstancesResult; import com.amazonaws.services.ec2.model.Instance; import com.amazonaws.services.ec2.model.InstanceStateName; import com.amazonaws.services.ec2.model.Reservation; import com.amazonaws.services.ec2.model.Tag; import com.amazonaws.services.ec2.model.TerminateInstancesRequest; ... private static List<Instance> getRunningInstances(AmazonEC2Client ec2, List<String> instanceIds) { List<Instance> runningInstances = new ArrayList<>(); try { DescribeInstancesRequest request = new DescribeInstancesRequest() .withInstanceIds(instanceIds); DescribeInstancesResult result; do { // DescribeInstancesResponse is a paginated response, so use tokens with multiple requests. result = ec2.describeInstances(request); request.setNextToken(result.getNextToken()); // Prepare request for next page. for (final Reservation r : result.getReservations()) { for (final Instance instance : r.getInstances()) { LOGGER.info("Examining instanceId: "+ instance.getInstanceId()); // if instance is in a running state, add it to runningInstances list. if (RUNNING_STATES.contains(instance.getState().getName())) { runningInstances.add(instance); } } } } while (result.getNextToken() != null); } catch (final AmazonEC2Exception exception) { // if instance isn't found, assume its terminated and continue. if (exception.getErrorCode().equals(NOT_FOUND_ERROR_CODE)) { LOGGER.info("Instance probably terminated; moving on."); } else { throw exception; } } return runningInstances; }

1. 添加 v2 Maven BOM

将BOM适用于 Java 2.x SDK 的 Maven 添加到本POM节中的任何其他依赖项旁边。dependencyManagement如果您的POM文件有 v1 BOM 的SDK,请暂时将其保留。它将在以后的步骤中删除。

<dependencyManagement> <dependencies> <dependency> <groupId>org.example</groupId> <!--Existing dependency in POM. --> <artifactId>bom</artifactId> <version>1.3.4</version> <type>pom</type> <scope>import</scope> </dependency> ... <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk-bom</artifactId> <!--Existing v1 BOM dependency. --> <version>1.11.1000</version> <type>pom</type> <scope>import</scope> </dependency> ... <dependency> <groupId>software.amazon.awssdk</groupId> <!--Add v2 BOM dependency. --> <artifactId>bom</artifactId> <version>2.27.21</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>

2. 在文件中搜索 v1 类的导入语句

在应用程序的代码中搜索唯一出现的。import com.amazonaws.services这可以帮助我们确定项目使用的 v1 依赖关系。如果你的应用程序有一个列出了 v1 依赖关系的 Maven POM 文件,你可以改用这些信息。

在这个例子中,我们使用 ripgrep(rg) 命令来搜索代码库。

从代码库的根目录执行以下ripgrep命令。ripgrep找到导入语句后,会将它们通过管道传送到cutsort、和uniq命令以隔离 SERVICE _ IDs。

rg --no-filename 'import\s+com\.amazonaws\.services' | cut -d '.' -f 4 | sort | uniq

对于此应用程序,将以下 SERVICE _ IDs 记录到控制台。

autoscaling cloudformation ec2 identitymanagement

这表明import语句中使用的以下每个软件包名称至少出现一次。我们的目的有四,各个类名无关紧要。我们只需要找到IDs使用的 SERVICE _。

com.amazonaws.services.autoscaling.* com.amazonaws.services.cloudformation.* com.amazonaws.services.ec2.* com.amazonaws.services.identitymanagement.*

3. 从 v1 的导入语句中确定 v2 Maven 的依赖关系

我们从步骤 2 中分离出来的 v1 的 SERVICE _IDs(例如autoscalingcloudformation)在大多数情况下可以映射到相同的 v2 SERVICE _ID。由于 v2 Maven 在大多数情况下都与 SERVICE _ID artifactId 匹配,因此您拥有向文件添加依赖块所需的信息。POM

下表显示了我们如何确定 v2 依赖关系。

v1 SERVICE _ID 映射到...

包名

v2 SERVICE _ID 映射到...

包名

v2 Maven 依赖关系

ec2

com.amazonaws.services.ec2.*

ec2

software.amazon.awssdk.services.ec2.*

<dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>ec2</artifactId> </dependency>

自动缩放

com.amazonaws.services.autoscaling.*

自动缩放

software.amazon.awssdk.services.autoscaling.*

<dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>autoscaling</artifactId> </dependency>
cloudformation

com.amazonaws.services.cloudformation.*

cloudformation

software.amazon.awssdk.cloudformation.*

<dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>cloudformation</artifactId> </dependency>
身份管理*

com.amazonaws.services.identitymanagement.*

我*

software.amazon.awssdk.iam.*

<dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>iam</artifactId> </dependency>

* to identitymanagement iam 映射是一个例外,其中 SERVICE _ID 因版本而异。如果 Maven 或 Gradle 无法解析 v2 依赖关系,请参阅了解例外情况。Package 名称到 Maven 映射关系 artifactId

4. 将 v2 依赖项元素添加到文件中 POM

在步骤 3 中,我们确定了需要添加到POM文件中的四个依赖块。我们不需要添加版本,因为我们已经BOM在步骤 1 中指定了。添加导入后,我们的POM文件具有以下依赖元素。

... <dependencies> ... <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>autoscaling</artifactId> </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>iam</artifactId> </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>cloudformation</artifactId> </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>ec2</artifactId> </dependency> ... </dependencies> ...

5. 在 Java 文件中,逐渐将 v1 类更改为 v2 类

在我们正在迁移的方法中,我们看到

  • 来自的EC2服务客户端com.amazonaws.services.ec2.AmazonEC2Client

  • 使用了几个EC2模型类。例如DescribeInstancesRequestDescribeInstancesResult

import com.amazonaws.ClientConfiguration; import com.amazonaws.regions.Region; import com.amazonaws.regions.RegionUtils; import com.amazonaws.services.ec2.AmazonEC2Client; import com.amazonaws.services.ec2.model.AmazonEC2Exception; import com.amazonaws.services.ec2.model.CreateTagsRequest; import com.amazonaws.services.ec2.model.DescribeInstancesRequest; import com.amazonaws.services.ec2.model.DescribeInstancesResult; import com.amazonaws.services.ec2.model.Instance; import com.amazonaws.services.ec2.model.InstanceStateName; import com.amazonaws.services.ec2.model.Reservation; import com.amazonaws.services.ec2.model.Tag; import com.amazonaws.services.ec2.model.TerminateInstancesRequest; ... private static List<Instance> getRunningInstances(AmazonEC2Client ec2, List<String> instanceIds) List<Instance> runningInstances = new ArrayList<>(); try { DescribeInstancesRequest request = new DescribeInstancesRequest() .withInstanceIds(instanceIds); DescribeInstancesResult result; do { // DescribeInstancesResponse is a paginated response, so use tokens with multiple re result = ec2.describeInstances(request); request.setNextToken(result.getNextToken()); // Prepare request for next page. for (final Reservation r : result.getReservations()) { for (final Instance instance : r.getInstances()) { LOGGER.info("Examining instanceId: "+ instance.getInstanceId()); // if instance is in a running state, add it to runningInstances list. if (RUNNING_STATES.contains(instance.getState().getName())) { runningInstances.add(instance); } } } } while (result.getNextToken() != null); } catch (final AmazonEC2Exception exception) { // if instance isn't found, assume its terminated and continue. if (exception.getErrorCode().equals(NOT_FOUND_ERROR_CODE)) { LOGGER.info("Instance probably terminated; moving on."); } else { throw exception; } } return runningInstances; } ...

我们的目标是用 v2 导入替换所有 v1 导入。我们一次只能上一堂课。

a. 替换导入语句或类名

我们看到该describeRunningInstances方法的第一个参数是 v1 AmazonEC2Client 实例。请执行以下操作之一:

  • 将的导入替换为 com.amazonaws.services.ec2.AmazonEC2Clientsoftware.amazon.awssdk.services.ec2.Ec2Client,然后更改AmazonEC2ClientEc2Client

  • 将参数类型更改为,Ec2Client然后让IDE提示我们进行正确的导入。IDE我们会提示我们导入 v2 类,因为客户端名称不同,而AmazonEC2Client且。Ec2Client如果两个版本中的类名相同,则此方法不起作用。

b. 将 v1 模型类替换为 v2 等效项

在 v2 更改之后Ec2Client,如果我们使用IDE,则会在以下语句中看到编译错误。

result = ec2.describeInstances(request);

编译错误是由于使用 v1 的实例DescribeInstancesRequest作为 v2 Ec2Client describeInstances 方法的参数而导致的。要修复此问题,请使用以下替换语句或导入语句。

replace 替换为
import com.amazonaws.services.ec2.model.DescribeInstancesRequest
import software.amazon.awssdk.services.ec2.model.DescribeInstancesRequest

c. 将 v1 构造函数更改为 v2 构建器。

我们仍然会看到编译错误,因为 v2 类上没有构造函数。要修复此问题,请进行以下更改。

更改
final DescribeInstancesRequest request = new DescribeInstancesRequest() .withInstanceIds(instanceIdsCopy);
final DescribeInstancesRequest request = DescribeInstancesRequest.builder() .instanceIds(instanceIdsCopy) .build();

d. 将 v1 *Result 响应对象替换为 v *Response 2 等效对象

v1 和 v2 之间的一致区别是,v2 中的所有响应对象都以而不是结*Response尾*Result将 v1 DescribeInstancesResult 导入替换为 v2 导入,。DescribeInstancesResponse

d. 做出API改变

以下语句需要进行一些修改。

request.setNextToken(result.getNextToken());

在 v2 中,setter 方法不使用set或 with。prefix前缀为前缀的 Getter 方法get也已在 Java 2.x 中SDK消失

模型类(例如request实例)在 v2 中是不可变的,因此我们需要DescribeInstancesRequest使用构建器创建一个新的模型。

在 v2 中,该语句变为以下内容。

request = DescribeInstancesRequest.builder() .nextToken(result.nextToken()) .build();

d. 重复直到方法使用 v2 类进行编译

继续执行代码的其余部分。用 v2 导入替换 v1 导入并修复编译错误。如有必要,请参阅 v2 API 参考不同之处参考资料

在我们迁移这个单一方法之后,我们有了以下 v2 代码。

import com.amazonaws.ClientConfiguration; import com.amazonaws.regions.Region; import com.amazonaws.regions.RegionUtils; import com.amazonaws.services.ec2.AmazonEC2Client; import com.amazonaws.services.ec2.model.AmazonEC2Exception; import com.amazonaws.services.ec2.model.CreateTagsRequest; import com.amazonaws.services.ec2.model.InstanceStateName; import com.amazonaws.services.ec2.model.Tag; import com.amazonaws.services.ec2.model.TerminateInstancesRequest; import software.amazon.awssdk.services.ec2.Ec2Client; import software.amazon.awssdk.services.ec2.model.DescribeInstancesRequest; import software.amazon.awssdk.services.ec2.model.DescribeInstancesResponse; import software.amazon.awssdk.services.ec2.model.Ec2Exception; import software.amazon.awssdk.services.ec2.model.Instance; import software.amazon.awssdk.services.ec2.model.Reservation; ... private static List<Instance> getRunningInstances(Ec2Client ec2, List<String> instanceIds) { List<Instance> runningInstances = new ArrayList<>(); try { DescribeInstancesRequest request = DescribeInstancesRequest.builder() .instanceIds(instanceIds) .build(); DescribeInstancesResponse result; do { // DescribeInstancesResponse is a paginated response, so use tokens with multiple re result = ec2.describeInstances(request); request = DescribeInstancesRequest.builder() // Prepare request for next page. .nextToken(result.nextToken()) .build(); for (final Reservation r : result.reservations()) { for (final Instance instance : r.instances()) { // if instance is in a running state, add it to runningInstances list. if (RUNNING_STATES.contains(instance.state().nameAsString())) { runningInstances.add(instance); } } } } while (result.nextToken() != null); } catch (final Ec2Exception exception) { // if instance isn't found, assume its terminated and continue. if (exception.awsErrorDetails().errorCode().equals(NOT_FOUND_ERROR_CODE)) { LOGGER.info("Instance probably terminated; moving on."); } else { throw exception; } } return runningInstances; } ...

由于我们在使用八种方法迁移 Java 文件中的单个方法,因此在处理文件时会混合使用 v1 和 v2 导入。我们在执行这些步骤时添加了最后六个 import 语句。

在我们迁移所有代码之后,将不再有 v1 导入语句。

6. 从文件中移除 v1 Maven 依赖关系,POM从文件中移除 v1 的依赖关系

迁移文件中的所有 v1 代码后,我们有以下 v2 SDK import 语句。

import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.regions.ServiceMetadata; import software.amazon.awssdk.services.ec2.Ec2Client; import software.amazon.awssdk.services.ec2.model.CreateTagsRequest; import software.amazon.awssdk.services.ec2.model.DescribeInstancesRequest; import software.amazon.awssdk.services.ec2.model.DescribeInstancesResponse; import software.amazon.awssdk.services.ec2.model.Ec2Exception; import software.amazon.awssdk.services.ec2.model.Instance; import software.amazon.awssdk.services.ec2.model.InstanceStateName; import software.amazon.awssdk.services.ec2.model.Reservation; import software.amazon.awssdk.services.ec2.model.Tag; import software.amazon.awssdk.services.ec2.model.TerminateInstancesRequest;

在我们迁移应用程序中的所有文件后,我们不再需要POM文件中的 v1 依赖项。BOM从该dependencyManagement部分中删除 v1(如果使用)以及所有 v1 依赖块。

7. 重构代码以使用 v API 2 增强功能

对于我们一直在迁移的片段,我们可以选择使用 v2 分页器,让他们SDK管理基于令牌的更多数据请求。

我们可以将整个子do句替换为以下内容。

DescribeInstancesIterable responses = ec2.describeInstancesPaginator(request); responses.reservations().stream() .forEach(reservation -> reservation.instances() .forEach(instance -> { if (RUNNING_STATES.contains(instance.state().nameAsString())) { runningInstances.put(instance.instanceId(), instance); } }));

Package 名称到 Maven 映射关系 artifactId

当你将 Maven 或 Gradle 项目从 Java 版的 v1 迁移到 v2 时,你需要弄清楚要将哪些依赖项添加到你的构建文件中。SDK带示例的迁移 step-by-step 说明(步骤 3)中描述的方法使用导入语句中的软件包名称作为起点来确定要添加到构建文件中的依赖关系。artifactIds

您可以使用本主题中的信息将 v1 软件包名称映射到 v artifactIds 2。

软件包名称和 Maven 中使用的常见命名约定 artifactIds

下表显示了用于给定 SERVICE _ID 的常SDKs用命名约定。SERVICE_ID 是的唯一标识符。 Amazon Web Services 服务例如,亚马逊 S3 服务的 SERVICE _ID 是亚马逊 Cognito Identity 的 _ID,也是s3亚马逊 cognitoidentity Cognito Identity 的 SERVICE _ID。

v1 软件包名称(导入语句) v1 artifactId v2 artifactId v2 软件包名称(导入语句)
com.amazonaws.servic SERVICE_ID aws-java-sdk-SERVICE _ID SERVICE_ID 软件.amazon.awssdk.services。 SERVICE_ID
亚马逊 Cognito 身份示例 (SERVICE_ID:) cognitoidentity
com.amazonaws.servic 认知身份 aws-java-sdk-认知身份 认知身份 软件.amazon.awssdk.services。 认知身份

SERVICE_ID 差异

在 v1 中

在某些情况下,软件包名称和相同服务的包名称之间 artifactId 的 SERVICE _ID 会有所不同。例如,下表的 “ CloudWatch 指标” 行显示软件包名称中的 SERVICE _ID 但却cloudwatchmetricsartifactId是 SERVICE _ID。metrics

在 v2 中

软件包名称中使用的 SERVICE _ID 和artifactIds没有区别。

在 v1 和 v2 之间

对于大多数服务,v2 中的 SERVICE _ID 与软件包名称和 v1 的 SERVICE _ID 相同。artifactIds这方面的一个例子是 cognitoedentity SERVICE _ID,如上表所示。但是,两者之间有一些 SERVICE _ IDs 有所不同,如下表所示。SDKs

v1 中任一列中的粗SERVICE体 _ID 表示它与 v2 中使用的 SERVICE _ID 不同。

服务名称 v1 软件包名称 v1 artifactId v2 artifactId v2 软件包名称

所有软件包名称都以开头com.amazonaws.services,如第一行所示。

所有 artifactIds 内容都包含在标签中,如第一行所示。

所有 artifactIds 内容都包含在标签中,如第一行所示。

所有软件包名称都以开头software.amazon.awssdk,如第一行所示。

API网关 com.amazonaws.services.apigatewa < artifactId > aws-java-sdk-api-gatew ay </ > artifactId < artifactId >ap artifactId igateway</ > 软件.amazon.awssdk.services.apigateway
应用程序注册表 鉴定登记 鉴定登记 servicecatalogappregistry servicecatalogappregistry
Application Discovery 应用程序发现 discovery 应用程序发现 应用程序发现
增强型 AI 运行时 增强空中运行时间 增强空中运行时间 sagemakera2iRuntime sagemakera2iRuntime
Certificate Manager 证书管理器 acm acm acm
CloudControl API 云控制 api 云控制 api 云控制 云控制
CloudSearch cloudsearch cloudsearch cloudsearch cloudsearch
CloudSearch 域名 云搜索域名 云端搜索 云搜索域名 云搜索域名
CloudWatch 大事记 云监视活动 事件 cloudwatcheVent cloudwatcheVent
CloudWatch 显然 cloudwatchevice cloudwatchevice evidently evidently
CloudWatch 日志 日志 日志 云监视日志 云监视日志
CloudWatch 指标 指标 云监视指标 cloudwatch cloudwatch
CloudWatch 朗姆酒 cloudwatc cloudwatc rum rum
Cognito 身份提供商 cognitoidp cognitoidp 认知身份提供者 认知身份提供者
Connect 广告系列 连接活动 连接活动 connect广告系列 connect广告系列
Connect Wis 连接智慧 连接智慧 wisdom wisdom
Database Migration Service 数据库迁移服务 dms 数据库迁移 数据库迁移
DataZone datazone 数据区外部 datazone datazone
DynamoDB dynamodbv2 dynamodb dynamodb dynamodb
弹性文件系统 弹性文件系统 efs efs efs
弹性地图缩小 elasticmapreduce emr emr emr
Glue DataBrew gluedatabrew gluedatabrew databrew databrew
IAM角色随处可见 我在任何地方都扮演角色 我在任何地方都扮演角色 rolesanywhere rolesanywhere
身份管理 身份管理 IAM IAM IAM
物联网数据 iotdata iot 物联网数据平面 物联网数据平面
Kinesis Analytics kinesisanalytics kinesis kinesisanalytics kinesisanalytics
Kinesis Firehose kinesisis fire kinesis firehose firehose
Kinesis 视频信令频道 kinesis 视频信号频道 kinesis 视频信号频道 kinesis 视频信号 kinesis 视频信号
Lex lexrunt lex lexrunt lexrunt
警惕视力 留意视力 留意视力 lookoutvision lookoutvision
大型机现代化 大型机现代化 大型机现代化 m2 m2
市场计量 市场计量 市场计量服务 市场计量 市场计量
托管 Grafana managedgrafana managedgrafana grafana grafana
Mechanical Turk mturk 机械火鸡请求者 mturk mturk
Migration Hub Strategy Recommendations 迁移中心策略建议 迁移中心策略建议 迁移中心策略 迁移中心策略
Nimble Studio 灵活的工作室 灵活的工作室 nimble nimble
专用 5G 私密的 5g 私密的 5g 私有网络 私有网络
Prometheus 普罗米修斯 普罗米修斯 放大器 放大器
回收站 回收箱 回收箱 rbin rbin
Redshift 数据 API redshiftdataap redshiftdataap 红移数据 红移数据
Route 53 route53 个域名 route53 route53 个域名 route53 个域名
Sage Maker 边缘管理 sagemakeredgeManager sagemakeredgeManager sagemakeredge sagemakeredge
安全令牌 安全令牌 sts sts sts
服务器迁移 服务器迁移 服务器迁移 sms sms
简单电子邮件 简单电子邮件 ses ses ses
简单电子邮件 V2 simpleemailv2 sesv2 sesv2 sesv2
简单的系统管理 简化系统管理 ssm ssm ssm
简单的工作流程 简单的工作流程 简单的工作流程 swf swf
Step Functions 阶梯函数 阶梯函数 sfn sfn