如何调试 AWS Api Gateway 和 Lambda 的“AWS/ApiGateway 5XXError”

Posted

技术标签:

【中文标题】如何调试 AWS Api Gateway 和 Lambda 的“AWS/ApiGateway 5XXError”【英文标题】:How do I debug AWS Api Gateway & Lambda's "AWS/ApiGateway 5XXError" 【发布时间】:2017-01-07 18:25:41 【问题描述】:

我有一个运行 lambda 函数的 API Gateway 资源。我正在使用我的 Api Gateway 中的 AWS Generated SDK 调用 API Gateway 资源。

这是来自我的客户端的堆栈跟踪部分似乎相关:

Caused by: com.amazonaws.mobileconnectors.apigateway.ApiClientException: "message": "Internal server error" (Service: DevnetcountableClient; Status Code: 500; Error Code: null; Request ID: 348e8f98-6f55-11e6-97f6-098c2caf220f)
at com.amazonaws.mobileconnectors.apigateway.ApiClientHandler.handleResponse(ApiClientHandler.java:255) at com.amazonaws.mobileconnectors.apigateway.ApiClientHandler.invoke(ApiClientHandler.java:88)
    at java.lang.reflect.Proxy.invoke(Proxy.java:393)
    at $Proxy1.accountCreatePost(Unknown Source)

现在查看 AWS 控制台,在我的 Api Gateway 仪表板中,我看到请求进入并导致“AWS/ApiGateway 5XXError”。但是有 0 个日志(我可以找到)。我的 lambda 函数似乎没有被调用,并且没有显示 lambda 日志。

现在这就是我的 lambda 的样子:

module.exports.createAccount = function(event, context, cb) 
    console.log('createAccount');
    console.log(event);
    console.log(context);
    console.log(cb);
    cb(null, status: 'SUCCESS', message: 'I ran!');
;

我可以做些什么来调试这个?

编辑:好的,这里是把所有东西放在一起的 cloudformation 脚本。


   "AWSTemplateFormatVersion":"2010-09-09",
   "Description":"The AWS CloudFormation template for this Serverless application",
   "Resources":
      "ServerlessDeploymentBucket":
         "Type":"AWS::S3::Bucket"
      ,
      "IamRoleLambda":
         "Type":"AWS::IAM::Role",
         "Properties":
            "AssumeRolePolicyDocument":
               "Version":"2012-10-17",
               "Statement":[
                  
                     "Effect":"Allow",
                     "Principal":
                        "Service":[
                           "lambda.amazonaws.com"
                        ]
                     ,
                     "Action":[
                        "sts:AssumeRole"
                     ]
                  
               ]
            ,
            "Path":"/"
         
      ,
      "IamPolicyLambda":
         "Type":"AWS::IAM::Policy",
         "Properties":
            "PolicyName":"dev-coolsoftware-lambda",
            "PolicyDocument":
               "Version":"2012-10-17",
               "Statement":[
                  
                     "Effect":"Allow",
                     "Action":[
                        "logs:CreateLogGroup",
                        "logs:CreateLogStream",
                        "logs:PutLogEvents"
                     ],
                     "Resource":"arn:aws:logs:us-west-2:*:*"
                  
               ]
            ,
            "Roles":[
               
                  "Ref":"IamRoleLambda"
               
            ]
         
      ,
      "createAccount":
         "Type":"AWS::Lambda::Function",
         "Properties":
            "Code":
               "S3Bucket":
                  "Ref":"ServerlessDeploymentBucket"
               ,
               "S3Key":"coolsoftware-1472853507538.zip"
            ,
            "FunctionName":"coolsoftware-dev-createAccount",
            "Handler":"handler.createAccount",
            "MemorySize":128,
            "Role":
               "Fn::GetAtt":[
                  "IamRoleLambda",
                  "Arn"
               ]
            ,
            "Runtime":"nodejs4.3",
            "Timeout":30
         
      ,
      "RestApiApigEvent":
         "Type":"AWS::ApiGateway::RestApi",
         "Properties":
            "Name":"dev-coolsoftware"
         
      ,
      "ResourceApigEventCreateaccountAccount":
         "Type":"AWS::ApiGateway::Resource",
         "Properties":
            "ParentId":
               "Fn::GetAtt":[
                  "RestApiApigEvent",
                  "RootResourceId"
               ]
            ,
            "PathPart":"account",
            "RestApiId":
               "Ref":"RestApiApigEvent"
            
         
      ,
      "PutMethodApigEventCreateaccountAccount":
         "Type":"AWS::ApiGateway::Method",
         "Properties":
            "AuthorizationType":"AWS_IAM",
            "HttpMethod":"PUT",
            "MethodResponses":[
               
                  "ResponseModels":
                     "application/json":"AccountCreationResponseModel"
                  ,
                  "ResponseParameters":

                  ,
                  "StatusCode":"200"
               
            ],
            "RequestParameters":

            ,
            "Integration":
               "IntegrationHttpMethod":"POST",
               "Type":"AWS",
               "Uri":
                  "Fn::Join":[
                     "",
                     [
                        "arn:aws:apigateway:",
                        
                           "Ref":"AWS::Region"
                        ,
                        ":lambda:path/2015-03-31/functions/",
                        
                           "Fn::GetAtt":[
                              "createAccount",
                              "Arn"
                           ]
                        ,
                        "/invocations"
                     ]
                  ]
               ,
               "RequestTemplates":
                  "application/json":"\n            #define( $loop )\n              \n              #foreach($key in $map.keySet())\n                  \"$util.escapejavascript($key)\":\n                    \"$util.escapeJavaScript($map.get($key))\"\n                    #if( $foreach.hasNext ) , #end\n              #end\n              \n            #end\n            \n              \"body\": $input.json(\"$\"),\n              \"method\": \"$context.httpMethod\",\n              \"principalId\": \"$context.authorizer.principalId\",\n              \"stage\": \"$context.stage\",\n\n              #set( $map = $input.params().header )\n              \"headers\": $loop,\n\n              #set( $map = $input.params().querystring )\n              \"query\": $loop,\n\n              #set( $map = $input.params().path )\n              \"path\": $loop,\n\n              #set( $map = $context.identity )\n              \"identity\": $loop,\n\n              #set( $map = $stageVariables )\n              \"stageVariables\": $loop\n            \n          "
               ,
               "IntegrationResponses":[
                  
                     "StatusCode":"200",
                     "ResponseParameters":

                     ,
                     "ResponseTemplates":
                        "application/json":""
                     
                  
               ]
            ,
            "ResourceId":
               "Ref":"ResourceApigEventCreateaccountAccount"
            ,
            "RestApiId":
               "Ref":"RestApiApigEvent"
            ,
            "RequestModels":
               "application/json":"AccountCreationRequestModel"
            
         
      ,
      "DeploymentApigEvent1472853508283":
         "Type":"AWS::ApiGateway::Deployment",
         "Properties":
            "RestApiId":
               "Ref":"RestApiApigEvent"
            ,
            "StageName":"dev"
         ,
         "DependsOn":[
            "PutMethodApigEventCreateaccountAccount"
         ]
      ,
      "createAccountApigPermission":
         "Type":"AWS::Lambda::Permission",
         "Properties":
            "FunctionName":
               "Fn::GetAtt":[
                  "createAccount",
                  "Arn"
               ]
            ,
            "Action":"lambda:InvokeFunction",
            "Principal":"apigateway.amazonaws.com"
         
      ,
      "DynamoDBTableAccounts":
         "Type":"AWS::DynamoDB::Table",
         "DeletionPolicy":"Retain",
         "Properties":
            "TableName":"dev-coolsoftware-accounts",
            "ProvisionedThroughput":
               "ReadCapacityUnits":1,
               "WriteCapacityUnits":1
            ,
            "AttributeDefinitions":[
               
                  "AttributeName":"accountid",
                  "AttributeType":"S"
               
            ],
            "KeySchema":[
               
                  "AttributeName":"accountid",
                  "KeyType":"HASH"
               
            ]
         
      ,
      "AccountCreationRequestModel":
         "Type":"AWS::ApiGateway::Model",
         "Properties":
            "RestApiId":
               "Ref":"RestApiApigEvent"
            ,
            "ContentType":"application/json",
            "Description":"Schema for AccountCreationRequestModel",
            "Name":"AccountCreationRequestModel",
            "Schema":
               "$schema":"http://json-schema.org/draft-04/schema#",
               "title":"AccountCreationRequestModel",
               "type":"object",
               "properties":
                  "publickey":
                     "type":"string"
                  ,
                  "deviceid":
                     "type":"string"
                  
               
            
         
      ,
      "AccountCreationResponseModel":
         "Type":"AWS::ApiGateway::Model",
         "Properties":
            "RestApiId":
               "Ref":"RestApiApigEvent"
            ,
            "ContentType":"application/json",
            "Description":"Schema for AccountCreationResponseModel",
            "Name":"AccountCreationResponseModel",
            "Schema":
               "$schema":"http://json-schema.org/draft-04/schema#",
               "title":"AccountCreationResponseModel",
               "type":"object",
               "properties":
                  "status":
                     "type":"string"
                  ,
                  "message":
                     "type":"string"
                  
               
            
         
      ,
      "FailureResponseModel":
         "Type":"AWS::ApiGateway::Model",
         "Properties":
            "RestApiId":
               "Ref":"RestApiApigEvent"
            ,
            "ContentType":"application/json",
            "Description":"Schema for FailureResponseModel",
            "Name":"FailureResponseModel",
            "Schema":
               "$schema":"http://json-schema.org/draft-04/schema#",
               "title":"FailureResponseModel",
               "type":"object",
               "properties":
                  "status":
                     "type":"string"
                  ,
                  "message":
                     "type":"string"
                  
               
            
         
      
   ,
   "Outputs":
      "ServerlessDeploymentBucketName":
         "Value":
            "Ref":"ServerlessDeploymentBucket"
         
      ,
      "Function1Arn":
         "Description":"Lambda function info",
         "Value":
            "Fn::GetAtt":[
               "createAccount",
               "Arn"
            ]
         
      ,
      "ServiceEndpoint":
         "Description":"URL of the service endpoint",
         "Value":
            "Fn::Join":[
               "",
               [
                  "https://",
                  
                     "Ref":"RestApiApigEvent"
                  ,
                  ".execute-api.us-west-2.amazonaws.com/dev"
               ]
            ]
         
      
   

编辑 2:当我在 AWS 控制台中使用 API Gateway 的测试功能测试端点时,一切正常:/

编辑 3:再次更新 cloudformation 脚本 - 仍然无法正常工作。

【问题讨论】:

我因缺少集成而出现此类错误。但是如果不查看您是如何创建网关/lambda 的,就很难弄清楚。 嗯,可能就是这样。我使用无服务器框架生成它,但我试图通过 cloudformation 脚本包含请求/响应模型、身份验证并启用“使用调用者凭据调用”。也许这就是破坏它的原因。无服务器框架通过 cloudformation 完成所有工作。我来看看模板。谢谢 @RhythmicFistman 我已经添加了我的 cloudformation 脚本,你介意看一下吗? 【参考方案1】:

如何调试:

    创建一个 IAM 角色以允许 API Gateway 将日志推送到 CloudWatch。该角色必须附加以下政策:

    "Version": "2012-10-17",
    "Statement": [
        
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:DescribeLogGroups",
                "logs:DescribeLogStreams",
                "logs:PutLogEvents",
                "logs:GetLogEvents",
                "logs:FilterLogEvents"
            ],
            "Resource": "*"
        
    ]

具有以下信任策略:


  "Version": "2012-10-17",
  "Statement": [
    
      "Sid": "",
      "Effect": "Allow",
      "Principal": 
        "Service": "apigateway.amazonaws.com"
      ,
      "Action": "sts:AssumeRole"
    
  ]

    在您的 API 区域的 API Gateway 控制台中:转到设置 >>> 输入 API Gateway-CloudWatch 日志记录角色的 ARN >>> 单击“保存”

    转到您的 API 阶段。在“CloudWatch 设置”下,选择“启用 CloudWatch 日志”。将“日志级别”设置为“信息”。选择“记录完整的请求/响应数据”。

    将您的 API 重新部署到该阶段:转到您的 API 的“资源”选项卡。选择操作 >>> 部署 API。

    发出请求,等待几分钟,然后查看日志的内容(在 CloudWatch 中)。

错误:

原因:

一旦我使用 Credentials: 'arn:aws:iam::*:user/*' 启用“使用调用方凭据调用”,调用方的 IAM 角色就无权调用 lambda 函数。这导致了 500 错误。一旦我授予调用者的 IAM 角色访问权限,一切就开始正常工作了。

【讨论】:

现在您可以使用托管策略,而不是创建自己的策略。它被称为AmazonAPIGatewayPushToCloudWatchLogs 您能否详细说明如何解决错误 500,尤其是调用者的 IAM 角色访问权限中的内容?谢谢。 我想知道当我的代码在 AWS Api Gateway 中运行时如何在本地机器上打断点?有可能吗?【参考方案2】:

以防万一有人需要。

以下链接说明了如何启用 cloudwatch 日志以调试 api 网关问题。

https://kennbrodhagen.net/2016/07/23/how-to-enable-logging-for-api-gateway/

【讨论】:

【参考方案3】:

API 网关日志显示什么?它是否显示“Lambda 函数的权限无效”?我认为您需要在 CloudFormation 模板中包含权限创建(资源)。这是我的一个:

"PERMISSIONGET": 
        "Type": "AWS::Lambda::Permission",
        "Properties": 
            "FunctionName": "createCabinet",
            "Action": "lambda:InvokeFunction",
            "Principal": "apigateway.amazonaws.com",
            "SourceArn": 
                "Fn::Join": [
                    "",
                    [
                        "arn:aws:execute-api:us-east-1:87875636623:",
                        
                            "Ref": "APIGATEWAY"
                        ,
                        "/*/GET/*"
                    ]
                ]
            
        ,
        "DependsOn": "APIDEPLOYMENT"
    

【讨论】:

我已经解决了这个问题(请参阅下面的答案)。调用者凭据需要调用 lambda 函数的权限,因为在 API 网关中我启用了“使用调用者凭据调用”

以上是关于如何调试 AWS Api Gateway 和 Lambda 的“AWS/ApiGateway 5XXError”的主要内容,如果未能解决你的问题,请参考以下文章

API 创新不会触发 AWS API Gateway 的基于自定义请求的 lambda 授权方

如果在 Terraform 模块中创建了 aws_api_gateway_integration,如何在 aws_api_gateway_deployment 资源上填充depends_on?

AWS API Gateway:如何实现持续交付?

HTTP 请求正文未通过 AWS API Gateway 访问 AWS lambda 函数

如何将特定 AWS API Gateway 阶段连接到特定 AWS lambda 别名

如何在 API Gateway 和 React 应用程序之间启用 AWS 中的 CORS 策略?