如何从SAM本地中的另一个Lambda调用AWS Lambda?

时间:2020-02-12 04:55:21

标签: python aws-lambda boto3

我正在将AWS SAM与Python结合使用。我的目标是拥有两个Lambda:

  • 功能A:正常的同步Lambda,它将调用功能B,然后快速返回
  • 功能B:长时间运行的异步事件Lambda

还有其他一些SO问题可以解决这种情况,但是据我所知,还没有人谈到在本地部署SAM时该如何做。

这是我的SAM模板文件:

# template.yaml

Resources:
  FunctionA:
    # PUT /functions/a, should invoke FunctionB asynchronously
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: api/
      Handler: functions.a
      Runtime: python3.7
      Events:
        FunctionA:
          Type: Api
          Properties:
            Path: /functions/a
            Method: put

  FunctionB:
    # Long-running asynchronous function
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: 'FunctionB'
      CodeUri: api/
      Handler: functions.b
      Runtime: python3.7
      EventInvokeConfig:
        MaximumRetryAttempts: 2
        DestinationConfig:
          OnSuccess:
            Type: SQS
          OnFailure:
            Type: SQS

还有我的Python lambda处理程序逻辑:

# functions.py

def a(event, context):
  boto3.client('lambda').invoke(
    FunctionName='FunctionB',
    InvocationType='Event',
    Payload='some_data'.encode('UTF-8')
  )
  return { "statusCode": 200, "body": {} }

def b(data):
  print("SUCCESS!")

我在本地部署它:

# deploy.sh
sam build
sam local start-api

到目前为止,一切都很好。当我调用PUT /functions/a时,出现以下错误,指示无法从功能A调用功能B:

[ERROR] ResourceNotFoundException: An error occurred (ResourceNotFoundException) when calling the Invoke operation: Function not found: arn:aws:lambda:us-east-2:[iam-user-id]:function:FunctionB

有人找到了解决办法吗?这是我尝试过的:

  1. 验证可以通过命令行成功调用功能B:
sam local invoke FunctionB # works great
  1. 尝试将InvocationType=Event更改为InvocationType=RequestResponse并收到相同的错误
  2. 实例化了lambda客户端以引用本地URL
boto3.client('lambda', endpoint_url='http://localhost:3000')
# [ERROR] EndpointConnectionError: Could not connect to the endpoint URL: "http://localhost:3000/2015-03-31/functions/ScheduleShowsAsyncFunction/invocations"

1 个答案:

答案 0 :(得分:0)

您可以使用sam local start-lambda运行FunctionA,它将在端口3001上进行仿真,并使用lambda客户端从FunctionB调用它:

boto3.client('lambda', endpoint_url='http://docker.for.mac.localhost:3001')

您必须使用InvocationType=RequestResponse,因为尚不支持事件https://github.com/awslabs/aws-sam-cli/pull/749

如果FunctionB长时间运行并且由于只能使用RequestResponse,则可以更改lambda客户端配置以增加超时:

config_lambda = Config(retries={'total_max_attempts': 1}, read_timeout=1200)

lambda_client = boto3.client('lambda',
                             config=config_lambda,
                             endpoint_url='http://docker.for.mac.localhost:3001')