如何从不同AWS SAM模板的Lambda调用另一个Lambda函数?
跨SAM模板实现Lambda函数调用的配置方案
问题背景
我正在使用AWS Lambda与AWS SAM,SAM CLI版本为1.39.0。我有两个模板文件:template-outbound.yaml和template-user-related.yaml:
template-outbound.yaml包含SendEmailFunction,代码如下:
SendEmailFunction: Type: AWS::Serverless::Function Properties: FunctionName: SendEmailFunction CodeUri: xxx-restapi/ Handler: source/email/send-email.sendEmail Runtime: nodejs14.x Events: SendEmailAPIEvent: Type: HttpApi Properties: Path: /email/send-email Method: post ApiId: !Ref AuthGatewayHttpApiOutbound
template-user-related.yaml包含LoginFunction,代码如下:
LoginFunction: Type: AWS::Serverless::Function Properties: FunctionName: LoginFunction CodeUri: xxx-restapi/ Handler: source/user/login.login Runtime: nodejs14.x Events: LoginAPIEvent: Type: HttpApi Properties: Path: /user/login Method: get ApiId: !Ref AuthGatewayHttpApi2
我用以下Node.js代码从LoginFunction调用SendEmailFunction:
try { var lambda = new AWS.Lambda({ region: 'us-east-1' }); var params = { FunctionName: 'SendEmailFunction', InvocationType: 'RequestResponse', LogType: 'Tail', Payload: JSON.stringify({ "text": text }) }; const result = await lambda.invoke(params).promise(); const response = JSON.parse(result.Payload); console.log(response); let fraudDetectedJson = { "statusCode": 400, "headers": { "Content-Type": "application/json" }, "body": JSON.stringify({ "error": "personal information detected" }), "isBase64Encoded": false }; } catch (error) { let errorJson = { "statusCode": 400, "headers": { "Content-Type": "application/json" }, "body": JSON.stringify({ "error": "error " }), "isBase64Encoded": false }; console.log(error); return errorJson; }
当两个函数在同一模板template-outbound.yaml中时,我可以通过以下配置正常调用:
LoginFunction: Type: AWS::Serverless::Function Properties: FunctionName: LoginFunction CodeUri: xxx-restapi/ Handler: source/user/login.login Runtime: nodejs14.x Events: LoginAPIEvent: Type: HttpApi Properties: Path: /user/login Method: get ApiId: !Ref AuthGatewayHttpApi2 Policies: - LambdaInvokePolicy: FunctionName: !Ref SendEmailFunction Environment: Variables: CREATE_EMAIL_MICROSERVICE_FUNCTION: !Ref SendEmailFunction
现在需要实现从template-user-related.yaml中的LoginFunction调用template-outbound.yaml中的SendEmailFunction,请问需要对模板文件做哪些修改?
解决方案
要实现跨SAM模板的Lambda函数调用,需按以下步骤修改模板文件,同时可优化代码引用方式:
1. 修改template-outbound.yaml:导出SendEmailFunction资源
在template-outbound.yaml末尾添加Outputs配置,将SendEmailFunction的名称和ARN导出,让其他模板可以引用这些值:
Outputs: SendEmailFunctionName: Description: SendEmail函数名称 Value: !Ref SendEmailFunction Export: Name: SendEmailFunctionName SendEmailFunctionArn: Description: SendEmail函数ARN Value: !GetAtt SendEmailFunction.Arn Export: Name: SendEmailFunctionArn
2. 修改template-user-related.yaml:导入资源并配置权限
在template-user-related.yaml的LoginFunction配置中,导入template-outbound.yaml导出的资源,同时添加调用权限和环境变量:
LoginFunction: Type: AWS::Serverless::Function Properties: FunctionName: LoginFunction CodeUri: xxx-restapi/ Handler: source/user/login.login Runtime: nodejs14.x Events: LoginAPIEvent: Type: HttpApi Properties: Path: /user/login Method: get ApiId: !Ref AuthGatewayHttpApi2 Policies: - LambdaInvokePolicy: FunctionName: !ImportValue SendEmailFunctionName # 也可以用ARN更安全:FunctionArn: !ImportValue SendEmailFunctionArn Environment: Variables: CREATE_EMAIL_MICROSERVICE_FUNCTION: !ImportValue SendEmailFunctionName
3. 优化Node.js代码(推荐)
将代码中硬编码的函数名称改为读取环境变量,避免后续函数名称变更时修改代码:
var params = { FunctionName: process.env.CREATE_EMAIL_MICROSERVICE_FUNCTION, // 替换原硬编码的'SendEmailFunction' InvocationType: 'RequestResponse', LogType: 'Tail', Payload: JSON.stringify({ "text": text }) };
部署注意事项
- 必须先部署
template-outbound.yaml,确保导出的资源存在后,再部署template-user-related.yaml,否则会出现导入资源不存在的错误。 - 如果两个模板属于同一AWS账号和区域,上述配置即可生效;若跨账号调用,还需在
SendEmailFunction的资源策略中添加允许调用的账号权限。
内容的提问来源于stack exchange,提问作者PeakGen
相关产品推荐
相关产品推荐

