本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
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
方法的工作方式基本相同:
-
执行
getName
活动,这会立即返回Promise<String>
对象name
,它表示名称。 -
调用
getGreeting
异步方法并为其传递name
对象。getGreeting
立即返回Promise<String>
对象greeting
,它表示问候语。 -
执行
say
活动并为其传递greeting
对象。 -
在
getName
完成时,name
会变为就绪状态,getGreeting
将使用它的值构建问候语。 -
在
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 实现完全相同。
要执行工作流程,请运行 GreeterWorker
和 GreeterMain
,就像 HelloWorldWorkflow 一样。