HelloWorldWorkflowAsync 应用程序 - AWS Flow Framework 适用于 Java

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

HelloWorldWorkflowAsync 应用程序

有时,最好让工作流程在本地执行某些任务,而不是使用活动。不过,工作流程任务通常涉及处理 Promise<T> 对象表示的值。如果将 Promise<T> 对象传递给一个同步工作流程方法,该方法将立即执行,但无法访问 Promise<T> 对象的值,直到该对象准备就绪。您可以轮询 Promise<T>.isReady,直到它返回 true,但这样做的效率非常低,并且该方法可能会阻止很长时间。更好的方法是使用异步方法

异步方法的实现与标准方法类似,通常是作为工作流实现类的成员,并在工作流实现的上下文中运行。您可以应用 @Asynchronous 注释将其指定为异步方法,这会指示框架像对待活动一样处理它。

  • 在工作流程实现调用异步方法时,它将立即返回。异步方法通常返回一个 Promise<T> 对象,在该方法完成时,该对象将变为就绪状态。

  • 如果为异步方法传递一个或多个 Promise<T> 对象,它将推迟执行,直到所有输入对象准备就绪。因此,异步方法可以访问其输入 Promise<T> 值,而不会出现引发异常的风险。

注意

鉴于适用于 Java 的 AWS Flow Framework 执行工作流的方式,异步方法通常会执行多次,因此,您只能将其用于快速的低开销任务。您应该使用活动执行时间较长的任务,如规模较大的计算。有关详细信息,请参阅AWS Flow Framework 基本概念:分布式执行

本主题是对 HelloWorldWorkflowAsync 的一次演练,它是 HelloWorldWorkflow 的改版,将其中一个活动替换为异步方法。要实现该应用程序,请在您的项目目录中创建 helloWorld.HelloWorldWorkflow 程序包的副本,并将其命名为 helloWorld.HelloWorldWorkflowAsync。

注意

本主题以 HelloWorld 应用程序HelloWorldWorkflow 应用程序主题中提供的概念和文件为基础。熟悉这些文件和中介绍的概念,这些主题,然后再继续。

以下几节介绍了如何修改原始 HelloWorldWorkflow 代码以使用异步方法。

HelloWorldWorkflowAsync 活动实现

HelloWorldWorkflowAsync 在 GreeterActivities 中实现其活动工作线程接口,如下所示:

import com.amazonaws.services.simpleworkflow.flow.annotations.Activities; import com.amazonaws.services.simpleworkflow.flow.annotations.ActivityRegistrationOptions; @Activities(version="2.0") @ActivityRegistrationOptions(defaultTaskScheduleToStartTimeoutSeconds = 300, defaultTaskStartToCloseTimeoutSeconds = 10) public interface GreeterActivities { public String getName(); public void say(String what); }

该接口类似于 HelloWorldWorkflow 使用的接口,但存在以下差异:

  • 它忽略 getGreeting 活动;该任务现在由异步方法进行处理。

  • 版本号设置为 2.0。在 Amazon SWF 注册活动接口后,您无法对其进行修改,除非更改版本号。

其余活动方法实现与 HelloWorldWorkflow 完全相同。只需从 GreeterActivitiesImpl 中删除 getGreeting

HelloWorldWorkflowAsync 工作流程实现

HelloWorldWorkflowAsync 按如下方式定义工作流程接口:

import com.amazonaws.services.simpleworkflow.flow.annotations.Execute; import com.amazonaws.services.simpleworkflow.flow.annotations.Workflow; import com.amazonaws.services.simpleworkflow.flow.annotations.WorkflowRegistrationOptions; @Workflow @WorkflowRegistrationOptions(defaultExecutionStartToCloseTimeoutSeconds = 3600) public interface GreeterWorkflow { @Execute(version = "2.0") public void greet(); }

该接口与 HelloWorldWorkflow 完全相同,但具有新的版本号。与活动一样,如果要更改注册的工作流程,您必须更改其版本。

HelloWorldWorkflowAsync 按如下方式实现工作流程:

import com.amazonaws.services.simpleworkflow.flow.annotations.Asynchronous; import com.amazonaws.services.simpleworkflow.flow.core.Promise; public class GreeterWorkflowImpl implements GreeterWorkflow { private GreeterActivitiesClient operations = new GreeterActivitiesClientImpl(); @Override public void greet() { Promise<String> name = operations.getName(); Promise<String> greeting = getGreeting(name); operations.say(greeting); } @Asynchronous private Promise<String> getGreeting(Promise<String> name) { String returnString = "Hello " + name.get() + "!"; return Promise.asPromise(returnString); } }

HelloWorldWorkflowAsync 将 getGreeting 活动替换为 getGreeting 异步方法,但 greet 方法的工作方式基本相同:

  1. 执行 getName 活动,这会立即返回 Promise<String> 对象 name,它表示名称。

  2. 调用 getGreeting 异步方法并为其传递 name 对象。getGreeting 立即返回 Promise<String> 对象 greeting,它表示问候语。

  3. 执行 say 活动并为其传递 greeting 对象。

  4. getName 完成时,name 会变为就绪状态,getGreeting 将使用它的值构建问候语。

  5. getGreeting 完成时,greeting 会变为就绪状态,say 会将字符串输出到控制台。

不同之处在于,greet 调用异步 getGreeting 方法,而不是调用活动客户端来执行 getGreeting 活动。实际结果是相同的,但 getGreeting 方法的工作方式与 getGreeting 活动略有不同。

  • 工作流程工作线程使用标准函数调用语义来执行 getGreeting。不过,活动异步执行是由 Amazon SWF 协调的。

  • getGreeting 在工作流程实现的进程中运行。

  • getGreeting 返回一个 Promise<String> 对象,而不是 String 对象。要获取 Promise 保留的字符串值,您需要调用其 get() 方法。不过,由于活动是异步运行的,其返回值可能不会立即可用;get() 将提出异常,直到异步方法的返回值可用。

    有关 Promise 如何工作的更多信息,请参阅 AWS Flow Framework 基本概念:活动与工作流之间的数据交换

getGreeting 将问候语字符串传递给静态 Promise.asPromise 方法以创建返回值。该方法创建一个具有相应类型的 Promise<T> 对象,设置对象值,然后将其置于就绪状态。

HelloWorldWorkflowAsync 工作流程及活动主机和启动程序

HelloWorldWorkflowAsync 实现 GreeterWorker 以作为工作流程和活动实现的主机类。它与 HelloWorldWorkflow 实现完全相同,唯一的区别是 taskListToPoll 名称,它设置为“HelloWorldAsyncList”。

import com.amazonaws.ClientConfiguration; import com.amazonaws.auth.AWSCredentials; import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflow; import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflowClient; import com.amazonaws.services.simpleworkflow.flow.ActivityWorker; import com.amazonaws.services.simpleworkflow.flow.WorkflowWorker; public class GreeterWorker { public static void main(String[] args) throws Exception { ClientConfiguration config = new ClientConfiguration().withSocketTimeout(70*1000); String swfAccessId = System.getenv("AWS_ACCESS_KEY_ID"); String swfSecretKey = System.getenv("AWS_SECRET_KEY"); AWSCredentials awsCredentials = new BasicAWSCredentials(swfAccessId, swfSecretKey); AmazonSimpleWorkflow service = new AmazonSimpleWorkflowClient(awsCredentials, config); service.setEndpoint("https://swf.us-east-1.amazonaws.com"); String domain = "helloWorldWalkthrough"; String taskListToPoll = "HelloWorldAsyncList"; ActivityWorker aw = new ActivityWorker(service, domain, taskListToPoll); aw.addActivitiesImplementation(new GreeterActivitiesImpl()); aw.start(); WorkflowWorker wfw = new WorkflowWorker(service, domain, taskListToPoll); wfw.addWorkflowImplementationType(GreeterWorkflowImpl.class); wfw.start(); } }

HelloWorldWorkflowAsync 在 GreeterMain 中实现工作流程启动程序;它与 HelloWorldWorkflow 实现完全相同。

要执行工作流程,请运行 GreeterWorkerGreeterMain,就像 HelloWorldWorkflow 一样。