

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 在 Amazon SWF 中开发决策者
<a name="swf-dg-dev-deciders"></a>

决策程序指的是工作流程类型协作逻辑的执行，在您执行工作流程期间运行。您可以针对一种工作流程类型运行多个决策程序。

工作流执行的执行状态存储在其工作流历史记录中，因此决策程序可以是无状态的。Amazon SWF 会维护工作流执行历史记录，并将其提供给每项决策任务的决策程序。这会使您视需要动态增加和删除决策程序，从而使您的工作流程处理过程具有高度可扩展性。随着系统负载的增长，您只需增加更多决策程序来处理增加的容量。但是，请注意，任何时候，对于给定的工作流程执行，都只能由一个决策任务处于开启状态。

每当工作流执行的状态发生更改时，Amazon SWF 都会安排一个决策任务。每当决策程序收到决策任务时，它都会执行以下操作：
+ 解析与决策任务一并提供的工作流程执行历史
+ 根据工作流程执行历史采用协作逻辑，并作出下一步操作的决策。每一个决策都由一个 Decision 结构表示
+ 完成该决策任务，并向 Amazon SWF 提供一个决策列表。

本章表述了开发决策程序的方法，其中包括：
+ 给您的决策程序编程以轮询决策任务
+ 给您的决策程序编程以解析工作流程执行历史并作出决策
+ 给您的决策程序编程以响应决策任务。

本章节中的示例显示的是，您针对电子商务示例工作流程给决策程序编程的方法。

您可以使用所需的任何语言来实现决策程序并在任何位置运行，只要该决策程序可通过其服务 API 与 Amazon SWF 通信。

**Topics**
+ [定义协作逻辑](#swf-dg-coordination-logic)
+ [轮询决策任务](#swf-dg-polling-decision-tasks)
+ [应用协作逻辑](#swf-dg-apply-coord-logic)
+ [响应决策](#swf-dg-responding-with-decisions)
+ [关闭工作流程执行](#swf-dg-closing-workflows)
+ [启动决策程序](#swf-dg-deciders-launch)

## 定义协作逻辑
<a name="swf-dg-coordination-logic"></a>

开发决策程序的第一步是定义协作逻辑。在电子商务示例中，在前一个活动完成后排定每个活动的协作逻辑可能与以下内容相似：

```
IF lastEvent = "StartWorkflowInstance"
 addToDecisions ScheduleVerifyOrderActivity

ELSIF lastEvent = "CompleteVerifyOrderActivity"
 addToDecisions ScheduleChargeCreditCardActivity

ELSIF lastEvent = "CompleteChargeCreditCardActivity"
 addToDecisions ScheduleCompleteShipOrderActivity

ELSIF lastEvent = "CompleteShipOrderActivity"
 addToDecisions ScheduleRecordOrderCompletion

ELSIF lastEvent = "CompleteRecordOrderCompletion"
 addToDecisions CloseWorkflow

ENDIF
```

决策程序将协作逻辑应用于工作流程执行历史，并在使用 `RespondDecisionTaskCompleted` 操作完成决策任务时创建决策列表。

## 轮询决策任务
<a name="swf-dg-polling-decision-tasks"></a>

每个决策程序都要轮询决策任务。决策任务中包含决策程序用于生成决策（如排定活动任务）的信息。要轮询决策任务，决策程序应使用 `PollForDecisionTask` 操作。

在此示例中，决策程序轮询决策任务，以指定 `customerOrderWorkflow-0.1` 任务列表。

```
https://swf.us-east-1.amazonaws.com
PollForDecisionTask
{
  "domain": "867530901",
  "taskList": {"name": "customerOrderWorkflow-v0.1"},
  "identity": "Decider01",
  "maximumPageSize": 50,
  "reverseOrder": true
}
```

如果指定的任务列表中有可用的决策任务，Amazon SWF 会立即返回该任务。如果没有决策任务可用，Amazon SWF 会保持连接打开长达 60 秒，并在任务可用时立即将其返回。如果没有任务可用，Amazon SWF 会返回一个空响应。空响应为 `Task` 结构，其中的 `taskToken` 值为空字符串。确保给您的决策程序编程以在它收到空响应时轮询另一个任务。

如果决策任务可用，Amazon SWF 会返回一个包含决策任务和工作流执行历史分页视图的响应。

在此示例中，最近事件类型指的是启动的工作流程执行，输入元素中包含执行第一个任务所需的信息。

```
{
  "events": [
    {
      "decisionTaskStartedEventAttributes": {
        "identity": "Decider01",
        "scheduledEventId": 2
      },
      "eventId": 3,
      "eventTimestamp": 1326593394.566,
      "eventType": "DecisionTaskStarted"
    }, {
      "decisionTaskScheduledEventAttributes": {
        "startToCloseTimeout": "600",
        "taskList": { "name": "specialTaskList" }
      },
      "eventId": 2,
      "eventTimestamp": 1326592619.474,
      "eventType": "DecisionTaskScheduled"
    }, {
      "eventId": 1,
      "eventTimestamp": 1326592619.474,
      "eventType": "WorkflowExecutionStarted",
      "workflowExecutionStartedEventAttributes": {
        "childPolicy" : "TERMINATE",
        "executionStartToCloseTimeout" : "3600",
        "input" : "data-used-decider-for-first-task",
        "parentInitiatedEventId": 0,
        "tagList" : ["music purchase", "digital", "ricoh-the-dog"],
        "taskList": { "name": "specialTaskList" },
        "taskStartToCloseTimeout": "600",
        "workflowType": {
          "name": "customerOrderWorkflow",
          "version": "1.0"
        }
      }
    }
  ],
  ...
}
```

收到工作流程执行历史后，决策程序会对历史进行解析并根据其协作逻辑做出决策。

由于一个工作流程执行的工作流程历史事件数量可能会很大，返回的结果可能会被拆分跨页显示。要检索后续页面，请`PollForDecisionTask`使用初始调用*nextPageToken*返回的进行其他调用。请注意，你*不能*`GetWorkflowExecutionHistory`用这个来电*nextPageToken*。请重新调用 `PollForDecisionTask` 替代之。

## 应用协作逻辑
<a name="swf-dg-apply-coord-logic"></a>

在决策程序收到决策任务后，给任务编程以解析工作流程执行历史，从而确定目前为止发生的情况。决策程序应该基于这个情况生成决策列表。

在电子商务示例中，我们只关心工作流程历史中最近的事件，所有我们要定义以下逻辑。

```
IF lastEvent = "StartWorkflowInstance"
 addToDecisions ScheduleVerifyOrderActivity

ELSIF lastEvent = "CompleteVerifyOrderActivity"
 addToDecisions ScheduleChargeCreditCardActivity

ELSIF lastEvent = "CompleteChargeCreditCardActivity"
 addToDecisions ScheduleCompleteShipOrderActivity

ELSIF lastEvent = "CompleteShipOrderActivity"
 addToDecisions ScheduleRecordOrderCompletion

ELSIF lastEvent = "CompleteRecordOrderCompletion"
 addToDecisions CloseWorkflow

ENDIF
```

如果 lastEvent 为 `CompleteVerifyOrderActivity`，您应增加 `ScheduleChargeCreditCardActivity` 活动到决策列表。

在决策程序确定要做出的决策后，可以用适当的决策来响应 Amazon SWF。

## 响应决策
<a name="swf-dg-responding-with-decisions"></a>

在解读工作流历史记录并生成决策列表后，决策程序就可以将这些决策返回 Amazon SWF。

给您的决策程序编程，以从工作流程执行历史中提取出它所需要的数据，然后创建决策以指定工作流程的下一步适当操作。决策程序使用 `RespondDecisionTaskCompleted` 操作将这些决策发送回 Amazon SWF。有关可用[决策类型的](https://docs.amazonaws.cn/amazonswf/latest/apireference/API_Decision.html)列表，请参阅《Amazon Simple Workflow Service API Reference》**。

在电子商务示例中，当决策程序回应其生成的决策集时，还会包括工作流程执行历史中的信用卡输入。然后，活动工作程序会获得其需要的信息来执行活动任务。

当工作流程执行中的所有活动均完成时，决策程序会关闭工作流程执行。

```
https://swf.us-east-1.amazonaws.com
RespondDecisionTaskCompleted
{
  "taskToken" : "12342e17-80f6-FAKE-TASK-TOKEN32f0223",
  "decisions" : [
    {
      "decisionType" :"ScheduleActivityTask",
      "scheduleActivityTaskDecisionAttributes" : {
        "control" :"OPTIONAL_DATA_FOR_DECIDER",
        "activityType" : {
          "name" :"ScheduleChargeCreditCardActivity",
          "version" :"1.1"
        },
        "activityId" :"3e2e6e55-e7c4-beef-feed-aa815722b7be",
        "scheduleToCloseTimeout" :"360",
        "taskList" : { "name" :"CC_TASKS" },
        "scheduleToStartTimeout" :"60",
        "startToCloseTimeout" :"300",
        "heartbeatTimeout" :"60",
        "input" : "4321-0001-0002-1234: 0212 : 234"
      }
    }
  ]
}
```

## 关闭工作流程执行
<a name="swf-dg-closing-workflows"></a>

当决策程序确定业务过程完成也就是没有更多要执行的活动时，决策程序会生成关闭工作流程执行的决策。

若要关闭工作流程执行，请给您的决策程序编程以解析工作流程历史中的事件，从而确定目前为止执行中发生的情况并查看工作流程执行是否应关闭。

如果工作流程已成功完成，则用 `CompleteWorkflowExecution` 决策来调用 `RespondDecisionTaskCompleted` 以关闭工作流程执行。或者，您可以使用 `FailWorkflowExecution` 决策放弃错误的执行。

在电子商务实例中，决策程序审查历史记录并根据协作逻辑增加关闭工作流程执行的决策到其决策列表中，并且用关闭工作流程决策启动 `RespondDecisionTaskCompleted` 操作。

**注意**  
有些情况下关闭工作流程执行的操作会失败。例如，如果在决策程序正关闭工作流程执行时收到信号，关闭决策会失败。要处理这种可能性，请确保决策程序继续轮询决策任务。此外，请确保接收下一个决策任务的决策程序对阻止执行结束的事件（在本例中为信号）做出响应。

您还可以支持取消工作流程执行。这尤其对长时间运行的工作流程有用。若要支持取消，决策程序应处理历史中的 `WorkflowExecutionCancelRequested` 事件。此事件表示已请求取消执行。您的决策程序应执行适当的清除操作，如取消持续进行的活动任务以及用 `CancelWorkflowExecution` 决策来调用 `RespondDecisionTaskCompleted` 操作以关闭工作流程。

以下示例显示的是，调用 `RespondDecisionTaskCompleted` 以指定当前工作流程执行已取消。

```
https://swf.us-east-1.amazonaws.com
RespondDecisionTaskCompleted
{
  "taskToken" : "12342e17-80f6-FAKE-TASK-TOKEN32f0223",
  "decisions" : [
    {
      "decisionType":"CancelWorkflowExecution",
      "CancelWorkflowExecutionAttributes":{
        "Details": "Customer canceled order"
      }
    }
  ]
}
```

Amazon SWF 会进行检查，确保关闭和取消工作流执行的决策是决策程序发送的最后一个决策。也就是说，拥有在关闭工作流程之后还有决策的这样一组决策无效。

## 启动决策程序
<a name="swf-dg-deciders-launch"></a>

完成决策程序开发之后，您就做好了启动一个或多个决策程序的准备。

要启动决策程序，请将您的协作逻辑打包成可执行，以使您能够将其用于您的决策程序平台上。例如，您可以将您的决策程序代码打包为 Java 可执行，以使您能够将其运行于 Linux 和 Windows 计算机上。

启动后，决策程序应开始轮询 Amazon SWF 以获取任务。在您启动工作流执行且 Amazon SWF 安排决策任务之前，这些轮询将会超时并获得空响应。空响应为 `Task` 结构，其中的 `taskToken` 值为空字符串。您的决策程序应只需继续轮询。

Amazon SWF 可确保在任何时候，一个工作流的执行只能有一个决策任务处于活动状态。这会防止决策冲突之类的问题。此外，Amazon SWF 还可确保将单个决策任务分配给单个决策程序，无论正在运行的决策程序有多少。

如果在决定程序处理另一个决策任务时发生了生成决策任务的情况，Amazon SWF 会将新任务排队，直到当前任务完成。当前任务完成后，Amazon SWF 会使新决策任务可用。此外，决策任务是分批进行的，也就是说，如果在决策程序处理决策任务的同时有多个活动完成，Amazon SWF 将只创建一个新决策任务，以应对多个任务完成。但是，每个任务完成都会收到工作流程执行历史中的一个单独事件。

由于轮询是出站请求，决策程序可以在任何可以访问 Amazon SWF 端点的网络上运行。

为了推进工作流程执行，必须运行一个或多个决策程序。您可以根据需要启动任意数量的决策程序。Amazon SWF 支持多个决策程序对同一任务列表进行轮询。