【问题标题】:How to get Task Token in AWS Lambda Function如何在 AWS Lambda 函数中获取任务令牌
【发布时间】:2021-06-29 13:07:30
【问题描述】:

我有一个使用 Java 实现的处理程序的 AWS Step Function。

我的步进函数定义:

definition:
  Comment: Steps for issuing a card
  StartAt: RecipientFraudChecks
  States:
    RecipientFraudChecks:
      Type: Task
      Next: SaveTaskToken
      Resource: arn:aws:lambda:eu-west-1:099720403855:RecipientFraudChecks
    SaveTaskToken:
      Type: Task
      Resource: arn:aws:lambda:eu-west-1:12345678:function:SaveTaskToken
      End: true

我有一个 Java 项目,所有 Lambda 函数处理程序都在那里定义:

public class SaveTaskToken implements RequestHandler<Map<String,String>, String> {

   ....

   @Override
   public String handleRequest(Map<String, String> input, final Context context) {

      // do the fraud checks
      System.out.println("the context is: " + gson.toJson(context));
      System.out.println("input: " + gson.toJson(input));

}

我正在使用 AWS SAM 在本地运行 step 函数,并根据此触发:https://docs.aws.amazon.com/step-functions/latest/dg/sfn-local-lambda.html#install-sam

context 内,我希望看到任务令牌,但我没有。日志显示:

the context is: {
  "memoryLimit": 512,
  "awsRequestId": "5065a9aa-1a4a-46fe-9b58-7dc2194f92b7",
  "logGroupName": "aws/lambda/SaveTaskToken",
  "logStreamName": "$LATEST",
  "functionName": "SaveTaskToken",
  "functionVersion": "$LATEST",
  "invokedFunctionArn": "",
  "cognitoIdentity": {
    "identityId": "",
    "poolId": ""
  },
  "logger": {}
}

事实上,它与我所期望的全局上下文完全不同 in the docs

我做错了什么?任务令牌如何获取?

编辑

我将Parameters 属性添加到“SaveTaskToken”并将资源更改为arn:aws:states:::lambda:invoke.waitForTaskToken,并且知道我可以获得任务令牌:

definition:
  Comment: Steps for issuing a card
  StartAt: RecipientFraudChecks
  States:
    RecipientFraudChecks:
      Type: Task
      Next: SaveTaskToken
      Resource: arn:aws:lambda:eu-west-1:099720403855:RecipientFraudChecks
    SaveTaskToken:
      Type: Task
      Resource: arn:aws:states:::lambda:invoke.waitForTaskToken
      Parameters:
        FunctionName: arn:aws:lambda:eu-west-1:12345678:function:SaveTaskToken
        Payload:
          taskToken
      End: true

在日志中我可以看到:

the input is: {
  "taskToken": "5286"
}

它导致了另一个问题 - 它覆盖了状态机的输入。我传入输入:

{"giftCode": "xxx"}

在第一个 Lambda 函数 RecipientFraudChecks 中,我可以获得输入。但是,在第二个中,自从添加了Parameters 属性后,我现在无法再获取状态机的输入,只能获取任务令牌...

编辑 已经在这里实现了答案:https://stackoverflow.com/a/66995869/1246159

{
  "Comment": "Steps for issuing a card",
  "StartAt": "RecipientFraudChecks",
  "States": {
    "RecipientFraudChecks": {
      "Type": "Task",
      "Next": "PauseCardIfNecessary",
      "ResultPath": "$.firstLambdaOutput",
      "Resource": "arn:aws:lambda:us-east-1:123456789012:function:RecipientFraudChecks"
    },
    "PauseCardIfNecessary": {
      "Type": "Task",
      "Next": "GetOrCreateClient",
      "Resource": "arn:aws:states:::lambda:invoke.waitForTaskToken",
      "Parameters": {
        "FunctionName": "arn:aws:lambda:us-east-1:123456789012:function:PauseCardIfNecessary",
        "Payload": {
          "token.$": "$$.Task.Token",
          "otherInput.$": "$"
        }
      }
    },
    "GetOrCreateClient": {
      "Type": "Task",
      "Next": "GetOrAccountClient",
      "Resource": "arn:aws:lambda:us-east-1:123456789012:function:GetOrCreateClient"
    },
    "GetOrAccountClient": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:us-east-1:123456789012:function:GetOrAccountClient",
      "End": true
    }
  }
}

但我得到另一个错误,这里是日志:

arn: aws: states: eu-west-1: 123456789012: execution: HelloWorld5: cardIssue: {
  "Type": "TaskStateExited",
  "PreviousEventId": 5,
  "StateExitedEventDetails": {
    "Name": "RecipientFraudChecks",
    "Output": "{\"inputToStep\":\"xxxx\",\"firstLambdaOutput\":\"output of recipient lambda\"}"
  }
} arn: aws: states: eu-west-1: 123456789012: execution: HelloWorld5: cardIssue: {
  "Type": "TaskStateEntered",
  "PreviousEventId": 6,
  "StateEnteredEventDetails": {
    "Name": "PauseCardIfNecessary",
    "Input": "{\"inputToStep\":\"xxxx\",\"firstLambdaOutput\":\"output of recipient lambda\"}"
  }
} arn: aws: states: eu-west-1: 123456789012: execution: HelloWorld5: cardIssue: {
  "Type": "ExecutionFailed",
  "PreviousEventId": 7,
  "ExecutionFailedEventDetails": {
    "Error": "States.Runtime",
    "Cause": "An error occurred while executing the state 'PauseCardIfNecessary' (entered at the event id #7). The value for the field 'token.$' must be a valid JSONPath expression"
  }
}

【问题讨论】:

    标签: java amazon-web-services aws-lambda aws-step-functions


    【解决方案1】:

    任务令牌不会在 lambda 上下文中自动传递,它需要作为输入传递。

    这里的context不是lambda函数的上下文,而是任务的上下文,要从上下文中获取细节,我们可以在step函数定义中使用$$., 例如:

    • 获取任务令牌$$.Task.Token
    • 获取开始时间$$.Execution.StartTime

    示例步骤函数:

    • 第一个任务执行带有步进函数输入的 Lambda。
    • 使用阶跃函数输入附加第一个 lambda 的输出。
    • 第二个任务使用资源 waitForTaskToken 执行另一个 lambda,在这里,我们获取任务令牌并将其与上一步的输出一起作为输入传递。
    • Step 函数一直等待,直到它获得 SendTaskSuccessSendTaskFailure

    {
      "StartAt": "fist-lambda-invoke-sync",
      "States": {
        "fist-lambda-invoke-sync": {
          "Next": "second-lambda-invoke-task-token",
          "Type": "Task",
          "ResultPath": "$.firstLambdaOutput",
          "Resource": "arn:aws:lambda:us-east-1:11112223333:function:myfirstlambda"
        },
        "second-lambda-invoke-task-token": {
          "End": true,
          "Type": "Task",
          "Resource": "arn:aws:states:::lambda:invoke.waitForTaskToken",
          "Parameters": {
            "FunctionName": "arn:aws:lambda:us-east-1:11112223333:function:mysecondlambda",
            "Payload": {
              "token.$": "$$.Task.Token",
              "otherInput.$": "$"
            }
          }
        }
      }
    }
    

    Step 函数的输入

    {
      "inputToStep": "myValue"
    }
    

    第一个 Lambda 的输出:假设它是一个字符串值“10”。由于"ResultPath": "$.firstLambdaOutput",它将被附加到输入Json

    {
      "inputToStep": "myValue",
      "firstLambdaOutput": "10"
    }
    

    第二个 Lambda 的输入:由于"token.$": "$$.Task.Token""otherInput.$": "$",将接收以下 json 作为输入并附加任务令牌

    { otherInput: { inputToStep: 'myValue', firstLambdaOutput: '10' },
      token: 'This is where Task Token generated by step function will be sent' } 
    

    【讨论】:

    • 谢谢,我实现了这个,但出现更多错误,将更新问题
    • @Mark 你还在本地测试吗?因为,我从 AWS 控制台测试了我的定义和您的定义,两者都按预期工作。
    • @Mark你使用的是快速阶跃函数还是标准阶跃函数?
    • 我使用的是默认的,我认为是标准的...
    • @Mark 你能确认你在哪里测试吗,我从头到尾测试过。我调用的所有 Lambda 都是简单的 1 行 lambda,它只打印输入并返回成功。对于等待步骤,我在等待时调用了aws stepfunctions send-task-success --task-token AAAAKgAA... --task-output '{"out":"success"}',它完成了等待步骤。
    【解决方案2】:

    关于输入,文档 [1] 中似乎有一个简单的解决方案:

    您可以使用来自状态机执行的输入,而不是在状态机定义中硬编码事件负载。以下示例使用您在运行状态机时指定的输入作为事件负载:

    "Payload.$": "$"
    

    文档 [2] 中还有另一个示例:

    {  
       "StartAt":"GetManualReview",
       "States":{  
          "GetManualReview":{  
             "Type":"Task",
             "Resource":"arn:aws:states:::lambda:invoke.waitForTaskToken",
             "Parameters":{  
                "FunctionName":"get-model-review-decision",
                "Payload":{  
                   "model.$":"$.new_model",
                   "token.$":"$$.Task.Token"
                },
                "Qualifier":"prod-v1"
             },
             "End":true
          }
       }
    }
    

    您可以将"model.$":"$.new_model" 更改为"input.$":"$" 之类的内容,并获得所需的 Lambda 有效负载。

    在 YAML 中转换为以下内容:

    Parameters:
      Payload:
        input.$: "$"
        token.$: "$$.Task.Token"
    

    [1]https://docs.aws.amazon.com/lambda/latest/dg/services-stepfunctions.html#services-stepfunctions-setup
    [2]https://docs.amazonaws.cn/en_us/step-functions/latest/dg/connect-lambda.html

    【讨论】:

    • 谢谢,实现了一些接近这个但仍然出现错误,更新问题
    猜你喜欢
    • 2019-01-01
    • 1970-01-01
    • 2018-04-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-05
    • 1970-01-01
    • 2021-11-15
    相关资源
    最近更新 更多