使用Python SDK调用同VPC内AWS Lambda遇500内部服务器错误
你的问题核心在于目标Lambda依赖的AWS Serverless Java Container框架只认标准的API Gateway/ALB代理事件格式,但你直接用boto3.invoke传递的是自己简化构造的请求字典,缺少框架要求的必要元数据字段,所以才抛出了InvalidRequestEventException。
问题根源拆解
你的目标Lambda是Spring Boot应用,通过AWS Serverless Java Container(比如aws-serverless-java-container-springboot)部署,这个框架的作用就是把API Gateway/ALB的代理事件转换成Servlet请求给Spring Boot处理。它需要的是AWS标准的API Gateway代理事件结构,包含requestContext、headers、identity等大量必填元数据,而你构造的{'resource':'/bucketstatus/latest','path':'/bucketstatus/latest','httpMethod':'GET'}太简陋,完全不符合框架的解析要求。
两种可行解决方案
方案一:通过私有API Gateway端点调用(推荐,贴合你的架构设计)
既然目标Lambda已经绑定了私有API Gateway,且两个Lambda在同一VPC,触发Lambda直接通过API Gateway的私有端点发HTTP请求才是最合理的做法,这也是私有API Gateway的设计初衷。
修改触发Lambda的代码如下:
from __future__ import print_function import json import logging import os from urllib2 import urlopen, Request, HTTPError import boto3 logger = logging.getLogger() logger.setLevel(logging.INFO) region = os.environ['AWS_REGION'] def lambda_handler(event, context): # 替换成你的私有API Gateway的实际端点URL private_api_url = "https://your-private-api-id.execute-api.us-east-1.amazonaws.com/dev/bucketstatus/latest" try: req = Request(private_api_url) response = urlopen(req) response_body = response.read() print(response_body) logger.info('Process Complete') return json.loads(response_body) except HTTPError as e: logger.error(f"请求失败: {e.code} - {e.read()}") raise
注意事项:
- 确保触发Lambda的安全组允许出站访问API Gateway的VPC端点(或私有IP)
- 私有API Gateway的资源策略要放行触发Lambda所在VPC的IP范围
- 如果VPC未启用私有DNS,需要用API Gateway VPC端点的DNS名称访问
方案二:构造标准API Gateway代理事件直接调用Lambda
如果你一定要通过boto3.invoke直接调用目标Lambda,必须构造符合AWS规范的API Gateway代理事件格式。以下是一个最小可用的事件示例:
from __future__ import print_function import json import logging import os import boto3 logger = logging.getLogger() logger.setLevel(logging.INFO) region = os.environ['AWS_REGION'] def lambda_handler(event, context): invokeLambda = boto3.client('lambda', region_name='us-east-1') # 构造标准API Gateway代理事件 api_gateway_event = { "resource": "/bucketstatus/latest", "path": "/bucketstatus/latest", "httpMethod": "GET", "requestContext": { "requestId": "test-request-id-123", "identity": { "sourceIp": "10.0.0.1" } }, "headers": {}, "queryStringParameters": {}, "pathParameters": {}, "stageVariables": {}, "body": None, "isBase64Encoded": False } invoke_response = invokeLambda.invoke( FunctionName='loader_development', InvocationType='RequestResponse', Payload=json.dumps(api_gateway_event) ) print(invoke_response['Payload'].read()) logger.info('Process Complete')
这个事件包含了框架要求的核心字段,目标Lambda应该能正确解析处理。
为什么其他Lambda可以正常工作?
推测你提到的其他同VPCLambda没有使用AWS Serverless Java Container框架,而是直接处理自定义事件格式,所以它们能接受你构造的简化请求。
内容的提问来源于stack exchange,提问作者nehacharya

