跳至内容

如何将 API Gateway REST API 与 Amazon SQS 集成并解决常见错误?

5 分钟阅读
0

我想将 Amazon API Gateway REST API 与 Amazon Simple Queue Service (Amazon SQS) 集成,并对集成错误进行故障排除。

解决方法

要将 API Gateway REST API 与 Amazon SQS 集成,请使用 AWS 查询协议AWS JSON 协议

使用 AWS 查询协议将 API Gateway REST API 与 Amazon SQS 集成

完成以下步骤:

  1. 创建 SQS 队列

  2. 为 AWS 服务创建 AWS Identity and Access Management (IAM) 角色
    **注意:**对于 Service or use case(服务或用例),选择 API Gateway

  3. 要允许从 API 向 Amazon SQS 发布消息,请附加以下具有 SendMessage 权限的 Amazon SQS 策略:

    {  "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Resource": [
            "arn:aws:sqs:example-region:example-account-id:example-sqs-queue-name"
          ],
          "Action": [
            "sqs:SendMessage"
          ]
        }
      ]
    }

    **注意:**请将 example-region 替换为您的 AWS 区域,将 example-account-id 替换为您的 AWS 账户 ID,并将 example-sqs-queue-name 替换为您的 SQS 队列名称。

  4. 在 API Gateway 中创建 REST API

  5. API Gateway 控制台中,为您的 REST API 创建 Amazon SQS 集成。

  6. 创建 REST API 资源或 REST API 方法
    Resources(资源)页面上,选择 Create method(创建方法)。
    对于 Method type(方法类型),选择 POST
    对于 Integration type(集成类型),选择 AWS Service(AWS 服务)。
    对于 AWS Region(AWS 区域),选择您的区域。
    对于 AWS service(AWS 服务),选择 Simple Queue Service (SQS)
    (可选)对于 AWS Subdomain(AWS 子域),输入 AWS 服务使用的子域。查看服务的文档,确认子域是否可用。对于 Amazon SQS 示例设置,请将其留空。
    对于 HTTP method(HTTP 方法),选择 POST
    对于 Action type(操作类型),选择 Use path override(使用路径覆盖)。
    对于 Path override (optional)(路径覆盖(可选)),请按以下格式输入您的账户 ID 和 SQS 队列名称:example-account-id/example-sqs-queue-name。例如: 1234567890/MySQSStandardQueue
    对于 Execution role(执行角色),输入 IAM 角色的 ARN。
    对于 Integration timeout(集成超时),请为您的设置选择一个选项。
    继续输入您的 REST API 集成信息。
    选择 Create method(创建方法)。
    选择 POST 方法集成请求
    选择 Edit(编辑)。
    对于 Request body passthrough(请求正文传递),请选择符合您要求的选项。
    展开 URL request headers parameters(URL 请求标头参数)。
    选择 Add request header parameter(添加请求标头参数)。
    对于 Name(名称),输入 Content-Type
    对于 Mapped from(映射自),输入 'application/x-www-form-urlencoded'
    展开 Mapping Templates(映射模板)。
    选择 Add mapping template(添加映射模板)。
    对于 Content-Type,输入 application/json
    对于模板,输入 Action=SendMessage&MessageBody=$input.body,然后选择 Save(保存)。

  7. 部署 REST API

  8. 要测试这个设置,请向 API Gateway 发送以下请求:

    curl --location --request POST 'https://example-api-id.execute-api.example-region.amazonaws.com/example-stage/example-resource' \     --header 'Content-Type: application/json' \  
       --data-raw '{  
        "message": "Hello World"  
      }'
    

    **注意:**请将 example-api-id 替换为您的 API ID,将 example-region 替换为您的区域,将 example-stage 替换为您的测试阶段名称,并将 example-resource 替换为您的资源名称。
    成功集成响应示例:

    {    "SendMessageResponse": {  
        "ResponseMetadata": {  
          "RequestId": "f879fb11-e736-52c0-bd29-a0f2d09ad90d"  
        },  
          "SendMessageResult": {  
            "MD5OfMessageAttributes": null,  
            "MD5OfMessageBody": "3fc759ac1733366f98ec4270c788fcd1",  
            "MD5OfMessageSystemAttributes": null,  
            "MessageId": "4c360c3c-08f4-4392-bc14-8b0c88e314a2",  
            "SequenceNumber": null  
        }  
      }  
    }

使用 AWS JSON 协议将 API Gateway REST API 与 Amazon SQS 集成

完成以下步骤:

  1. 创建 SQS 队列

  2. 为 AWS 服务创建 IAM 角色
    **注意:**对于 Service or use case(服务或用例),选择 API Gateway

  3. 要允许从 API 向 Amazon SQS 发布消息,请附加以下具有 SendMessage 权限的 Amazon SQS 策略:

    {    "Version": "2012-10-17",  
      "Statement": [  
        {  
          "Effect": "Allow",  
          "Resource": [  
            "arn:aws:sqs:example-region:example-account-id:example-sqs-queue-name"  
          ],  
          "Action": [  
            "sqs:SendMessage"  
          ]  
        }  
      ]  
    }
    

    **注意:**请将 example-region 替换为您的 AWS 区域,将 example-account-id 替换为您的 AWS 账户 ID,并将 example-sqs-queue-name 替换为您的 SQS 队列名称。

  4. 在 API Gateway 中创建 REST API

  5. API Gateway 控制台中,为您的 REST API 创建 Amazon SQS 集成。

  6. 创建 REST API 资源或 REST API 方法
    Resources(资源)页面上,选择 Create method(创建方法)。
    对于 Method type(方法类型),选择 POST
    对于 Integration type(集成类型),选择 AWS Service(AWS 服务)。
    对于 AWS Region(AWS 区域),选择您的区域。
    对于 AWS service(AWS 服务),选择 Simple Queue Service (SQS)
    对于 AWS Subdomain(AWS 子域),请将其留空。这是一个可选参数,您可以在其中输入 AWS 服务使用的子域。查看服务的文档,确认子域是否可用。
    对于 HTTP method(HTTP 方法),选择 POST
    对于 Action type(操作类型),选择 Use path override(使用路径覆盖)。
    对于 Path override(路径覆盖),请输入 / 字符。
    对于 Execution role(执行角色),输入 IAM 角色的 ARN。
    对于 Default timeout(默认超时),请为您的设置选择一个选项。
    展开 HTTP request headers(HTTP 请求标头)。
    选择 Add header(添加标头)。
    对于 Name(名称),输入 Content-Type
    选择 Add header(添加标头)。
    对于 Name(名称),输入 X-Amz-Target
    选择 Create method(创建方法)。
    选择 POST 方法集成请求
    选择 Edit(编辑)。
    对于 Request body passthrough(请求正文传递),当没有模板与请求内容类型标头匹配时,保留为默认选项。
    展开 URL request headers parameters(URL 请求标头参数)。
    选择 Add request header parameter(添加请求标头参数)。
    对于 Name(名称),输入 Content-Type
    对于 Mapped from(映射自),输入 method.request.header.Content-Type
    选择 Add request header parameter(添加请求标头参数)。
    对于 Name(名称),输入 X-Amz-Target
    对于 Mapped from(映射自),输入 method.request.header.X-Amz-Target
    选择 Save(保存)。

  7. 部署 REST API

  8. 要测试这个设置,请向 API Gateway 发送以下请求:

    curl --location --request POST 'https://example-api-id.execute-api.example-region.amazonaws.com/example-stage/example-resource' \  --header 'Content-Type:application/x-amz-json-1.0' \
      --header 'X-Amz-Target:AmazonSQS.SendMessage' \
      --data-raw '{
        "QueueUrl": "https://sqs.<region>.<domain>/<awsAccountId>/<queueName>/",
        "MessageBody": "This is a test message"
    }'

    **注意:**请将 example-api-id 替换为您的 API ID,将 example-region 替换为您的区域,将 example-stage 替换为您的测试阶段名称,并将 example-resource 替换为您的资源名称。要查找您的 QueueUrl 值,请查看您的 Amazon SQS 队列详细信息。

成功集成响应示例:

{"MD5OfMessageBody":"fafb00f5732ab283681e124bf8747ed1","MessageId":"b5aef1f3-af31-49f2-9973-6f802f7753e6"}

**注意:**AWS JSON 协议的预期响应与 AWS 查询协议不同,即使是相同的 API 调用也是如此。

解决常见的 SQS 错误

要解决常见的 Amazon SQS 错误,请针对您收到的错误消息执行以下故障排除步骤。

"UnknownOperationException" 错误

AWS 查询协议和 AWS JSON 协议都可能出现 "UnknownOperationException" 错误。

如果您使用 AWS 查询协议,则当您没有在集成请求 HTTP 标头中将 Content-Type 配置为 "application/x-www-form-urlencoded" 时,就会出现此错误。当您没有将 SendMessage 操作添加到集成请求的映射模板时,也会出现此错误。要解决此错误,请确保 Content-Type 格式正确,并在映射模板中包含 SendMessage 操作。

如果您使用 AWS JSON 协议,则当您没有发送或未正确配置 Content-TypeX-Amz-Target 标头时,就会收到此错误。要解决此错误,请将 Content-Type 标头配置为 "application/x-amz-json-1.0",并将 X-Amz-Target 标头配置为 AmazonSQS.{SQS-Action},并在请求中包含两个标头。

"AccessDenied" 错误

AWS 查询协议和 AWS JSON 协议都可能出现 "AccessDenied" 错误。

当 API 集成执行角色未拥有向 SQS 队列发送消息的 sqs:SendMessage 权限时,会出现此错误。

当您使用 AWS 查询协议并在请求正文有效载荷字符串中传递不支持的特殊字符时,也会出现此错误。必须对特殊字符进行编码以避免此错误。在映射模板中添加 $util.urlEncode() 函数,将请求正文从字符串转换为编码格式。以下是映射模板示例:

Action=SendMessage&MessageBody=$util.urlEncode($input.body)

如果您使用 Amazon SQS 先入先出 (FIFO) 队列,请确保包含 MessageGroupIdMessageDeduplicationId 属性。以下是 FIFO 映射模板示例:

Action=SendMessage&MessageBody=$util.urlEncode($input.body)&MessageGroupId=$your-msg-group-id&MessageDeduplicationId=$your-msg-dedup-id

**注意:**请将 your-msg-group-id 替换为消息组 ID,并将 your-msg-dedup-id 替换为消息重复数据删除 ID。

以下示例包括向 SQS 队列发送消息所需的权限:

{  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Resource": [
        "arn:aws:sqs:example-region:example-account-id:example-sqs-queue-name"
      ],
      "Action": [
        "sqs:SendMessage"
      ]
    }
  ]
}

**注意:**请将 example-region 替换为您的区域,将 example-account-id 替换为您的账户 ID,并将 example-sqs-queue-name 替换为您的 SQS 队列名称。

"KMS.AccessDeniedException" 错误

AWS 查询协议和 AWS JSON 协议都可能出现 "KMS.AccessDeniedException" 错误。

当 API 集成执行角色无法通过 AWS Key Management Service (AWS KMS) 执行操作时,就会出现此错误。要解决此错误,必须配置权限,才能对附加到 Amazon SQS 服务器端加密队列的 AWS KMS 密钥执行操作。

以下示例包括对附加到 SQS 队列的 KMS 密钥执行操作所需的权限:

{  "Sid": "Allow use of the key",
  "Effect": "Allow",
  "Principal": {
    "AWS": "arn:aws:iam::example-account-id:role/example-api-gw-integration-execution-role"
  },
  "Action": [
    "kms:Encrypt",
    "kms:GenerateDataKey*",
    "kms:Decrypt"
  ],
  "Resource": "*"
}

**注意:**请将 example-account-id 替换为您的账户 ID,并将 example-api-gw-integration-execution-role 替换为您的执行角色名称。

"MalformedQueryString" 错误

AWS 查询协议和 AWS JSON 协议都可能出现 "MalformedQueryString" 错误。

当请求正文有效载荷字符串中存在特殊字符时,就会发生此错误。在映射模板中添加 $util.urlEncode() 函数,将请求正文从字符串转换为编码格式。以下是映射模板示例:

Action=SendMessage&MessageBody=$util.urlEncode($input.body)

"SignatureDoesNotMatch" 错误

使用 AWS 查询协议时,可能会出现 "SignatureDoesNotMatch" 错误。

集成请求HTTP 方法设置为 GET 而非 POST 时,就会出现此错误。要解决此错误,请将 HTTP 方法设置为 POST。

"InvalidAddress" 错误

使用 AWS JSON 协议时,可能会出现 "InvalidAddress" 错误。

当正文有效载荷中的 SQS 队列 URL 不正确时,就会出现此错误。要解决此错误,请检查 API 调用所针对的 SQS 队列的队列 URL。

"SerializationException" 错误

使用 AWS JSON 协议时,可能会出现 "SerializationException" 错误。

当正文有效载荷并非有效的 JSON 时,就会发生此错误。例如,您的 JSON 可能缺少一个逗号或存在多余的逗号,或者缺少大括号或存在多余的大括号。要解决此错误,请将您的 JSON 修改为有效格式。

"MissingRequiredParameterException" 错误

使用 AWS JSON 协议时,可能会出现 "MissingRequiredParameterException" 错误。

当您没有在正文有效载荷中包含一个或多个所需参数时,就会出现此错误。所需参数取决于您的 API 调用。例如,当缺少 MessageBody 参数时,您就会从 SendMessage API 调用中收到此错误。有关所需的参数和语法,请查看 SQS API 参考

相关信息

将 Amazon API Gateway 与 Amazon SQS 集成以处理异步 REST API

如何使用 API Gateway 作为其他 AWS 服务的代理?