Python Step Functions API:get_activity_task似乎总是超时

时间:2018-03-16 05:31:29

标签: python-3.x amazon-web-services timeout boto3 aws-step-functions

我有一个像这样的lambda函数:

import boto3
import os
import json

step_functions = boto3.client('stepfunctions')
workers_topic = boto3.resource('sns').Topic(os.environ.get("WORKERS_TOPIC_ARN"))

def test_push_to_workers_sns(event, context):
    activity_response = \
        step_functions.get_activity_task(
            activityArn=os.environ.get("ACKNOWLEDGE_ACTIVITY_ARN"),
            workerName='test_push_to_workers_sns'
        )

    task_token, input_ = activity_response['taskToken'], activity_response['input']

    print(f"Task token is {task_token}")
    print(f"Input is {input}")

    if not task_token:
        print("No activity found")
        return

    workers_topic.publish(Message="blah blah")

当我开始执行我所拥有的步骤功能并且它到达活动时,我反复检查在我的终端上运行aws stepfunctions get-activity-task --activity-arn <ACKNOWLEDGE_ACTIVITY_ARN>会返回一个taskToken和输入都是正确的。然而,无论活动是否正在运行,这个lambda函数似乎总是超时(我已经将我的超时值设置为lambda函数的1分15秒,以及步骤函数的活动状态&#39;超时1小时)

1 个答案:

答案 0 :(得分:1)

我使用以下CloudFormation模板检查了这个案例并且它可以工作:

AWSTemplateFormatVersion: "2010-09-09"
Description: Stack creating AWS Step Functions state machine and lambda function calling GetActivityTask.

Resources:
  LambdaFunction:
    Type: AWS::Lambda::Function
    Properties:
      Handler: "index.handler"
      Role: !GetAtt LambdaExecutionRole.Arn
      Code:
        ZipFile: |
          import boto3
          import os
          import json

          step_functions = boto3.client('stepfunctions')
          workers_topic = boto3.resource('sns').Topic(os.environ.get("WORKERS_TOPIC_ARN"))


          def handler(event, context):
              activity_response = step_functions.get_activity_task(
                  activityArn=os.environ.get("ACKNOWLEDGE_ACTIVITY_ARN"),
                  workerName='test_push_to_workers_sns'
              )

              if 'taskToken' not in activity_response:
                  return

              task_token, task_input = activity_response['taskToken'], activity_response['input']

              print(f"Task token is {task_token}")
              print(f"Input is {input}")

              workers_topic.publish(Message="blah blah")
              step_functions.send_task_success(
                  taskToken=task_token,
                  output=task_input
              )

      Runtime: "python3.6"
      Timeout: 25
      Environment:
        Variables:
          WORKERS_TOPIC_ARN: !Ref WorkersTopic
          ACKNOWLEDGE_ACTIVITY_ARN: !Ref AcknowledgeActivity

  StateMachine:
    Type: AWS::StepFunctions::StateMachine
    Properties:
      RoleArn: !GetAtt StatesExecutionRole.Arn
      DefinitionString: !Sub
        - >
          {
            "Comment": "State Machine for GetActivityTask testing purposes.",
            "StartAt": "FirstState",
            "States": {
              "FirstState": {
                "Type": "Task",
                "Resource": "${ACKNOWLEDGE_ACTIVITY_ARN}",
                "End": true
              }
            }
          }
        - ACKNOWLEDGE_ACTIVITY_ARN: !Ref AcknowledgeActivity

  AcknowledgeActivity:
    Type: AWS::StepFunctions::Activity
    Properties:
      Name: !Sub ${AWS::AccountId}-AcknowledgeActivity

  WorkersTopic:
    Type: AWS::SNS::Topic

  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
        - Effect: Allow
          Principal:
            Service:
              - lambda.amazonaws.com
          Action:
            - sts:AssumeRole
      Path: "/"
      Policies:
        - PolicyName: StepFunctionsAccess
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - states:GetActivityTask
                  - states:SendTaskFailure
                  - states:SendTaskSuccess
                Resource: arn:aws:states:*:*:*
        - PolicyName: SNSAccess
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - SNS:Publish
                Resource: arn:aws:sns:*:*:*

  StatesExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - !Sub states.${AWS::Region}.amazonaws.com
            Action: sts:AssumeRole
      Path: "/"
      Policies: []

我从Step Functions控制台手动创建了执行,并从Lambda控制台手动执行了Lambda。

请记住,使用taskToken GetActivityTask后,与之相关的执行正在等待响应(SendTaskSuccessSendTaskFailure),直到达到超时(默认为非常长)。因此,如果您在此之前已经取得令牌,则GetAcitivtyTask无法执行。您可以在Step Functions控制台中查找执行状态,查看特定执行的事件。

SendTaskSuccess获取令牌后,您应该从代码中调用SendTaskFailureGetActivityTask(否则执行将一直挂起,直到达到超时或停止)。

除了原始问题:GetActivityTask不适合从Lambda调用。您可以将Lambda Function作为资源传递给状态机(而不是活动),并在执行到达指定状态时调用它(处理程序中的event将包含执行状态)。活动应仅用于专用机器(EC2,ECS)上的长时间运行作业。我还应该指出GetActivityTask次呼叫存在服务限制(25个RPS,桶大小为1000),基于Lambda的状态基本上仅受到转换计数限制(每秒400个,桶大小为800)的限制。您可以在此处详细了解步骤功能限制:https://docs.aws.amazon.com/step-functions/latest/dg/limits.html