工作流引擎外部任务(External Tasks)下
处理外部任务(External Tasks)
要处理外部任务,必须在BPMN XML中声明它们。在运行时,可以通过Java和REST API访问外部任务实例。以下说明了API概念,并重点介绍了Java API。REST API通常更适合这种情况,特别是当使用不同的技术实现在不同环境中运行的工作程序时。
BPMN
在流程定义的BPMN XML中,可以使用属性pangubpm:type和声明服务任务由外部工作人员执行pangubpm:topic。例如,可以将服务任务验证地址配置为提供该主题的外部任务实例,AddressValidation如下所示:
<serviceTask id="validateAddressTask"
name="Validate Address"
pangubpm:type="external"
pangubpm:topic="AddressValidation" />
可以通过使用表达式而不是常量值来定义主题名称。
此外,可以使用外部任务模式来实现其他类似服务任务的元素,例如发送任务,业务规则任务和引发消息事件。有关详细信息,请参见BPMN 2.0实现参考。
Rest API
有关如何通过HTTP访问API操作的信息,请参阅REST API文档。
长时间轮询以获取和锁定外部任务
无论请求的信息是否可用,服务器都会立即回答普通的HTTP请求。这不可避免地导致客户端必须执行多个重复请求,直到信息可用(轮询)。就资源而言,这种方法显然很昂贵。
在长时间轮询的帮助下,如果没有外部任务可用,服务器将挂起一个请求。一旦发生新的外部任务,该请求就会重新激活并执行响应。暂停被限制为可配置的时间段(超时)。
长轮询显着减少了请求数量,并使服务器和客户端都能更有效地使用资源。
当心!
该功能基于JAX-RS 2.0,因此在IBM WebSphere Application Server 8.5上不可用。
独特的工人要求
默认情况下,多个工作人员可以使用相同的workerId。为了确保workerId服务器端的唯一性,可以激活“唯一工人请求”标志。该配置标志仅影响长轮询请求,而不影响普通的“获取并锁定”请求。如果激活了“唯一工作人员请求”标志,workerId则在收到新请求时,具有该请求的未决请求将被取消。
为了使“独特的工人请求”标志,则engine-rest/WEB-INF/web.xml包含在文件引擎休息 神器需要通过设置环境参数调整fetch-and-lock-unique-worker-request到true。请考虑以下配置片段:
<!-- ... -->
<context-param>
<param-name>fetch-and-lock-unique-worker-request</param-name>
<param-value>true</param-value></context-param>
<!-- ... -->
Java API
用于外部任务的Java API的入口点是ExternalTaskService。可以通过访问processEngine.getExternalTaskService()。
以下是一个交互示例,该交互可提取10个任务,循环处理这些任务,并且对于每个任务,要么完成任务,要么将其标记为失败。
List<LockedExternalTask> tasks = externalTaskService.fetchAndLock(10, "externalWorkerId")
.topic("AddressValidation", 60L * 1000L)
.execute();
for (LockedExternalTask task : tasks) {
try {
String topic = task.getTopicName();
// work on task for that topic
...
// if the work is successful, mark the task as completed
if(success) {
externalTaskService.complete(task.getId(), variables);
}
else {
// if the work was not successful, mark it as failed
externalTaskService.handleFailure(
task.getId(),
"externalWorkerId",
"Address could not be validated: Address database not reachable",
1, 10L * 60L * 1000L);
}
}
catch(Exception e) {
//... handle exception
}}
以下各节ExternalTaskService将更详细地介绍不同的交互。
抓取任务
为了实现轮询工作程序,可以使用方法执行获取操作ExternalTaskService#fetchAndLock。此方法返回一个流畅的构建器,该构建器允许定义一组主题以为其提取任务。考虑以下代码片段:
List<LockedExternalTask> tasks = externalTaskService.fetchAndLock(10, "externalWorkerId")
.topic("AddressValidation", 60L * 1000L)
.topic("ShipmentScheduling", 120L * 1000L)
.execute();
for (LockedExternalTask task : tasks) {
String topic = task.getTopicName();
// work on task for that topic
...}
此代码最多可提取主题AddressValidation和的10个任务ShipmentScheduling。结果任务只为ID为的工作人员锁定externalWorkerId。锁定意味着从获取时间开始为该工作者保留任务一定时间,并防止在锁定有效时其他工作者可以获取同一任务。如果锁到期并且任务尚未完成,则其他工作人员可以获取该锁,以使发生故障的工作人员不会无限期地阻止执行。确切的持续时间在单个主题访存说明中给出:的任务AddressValidation被锁定60秒(60L * 1000L毫秒),而的任务ShipmentScheduling被锁定120秒(120L * 1000L毫秒)。锁定到期时间不应短于预期的执行时间。如果这意味着太长的超时时间(如果在工作人员无提示的情况下重试任务),则该时间也不应太高。
可以与任务一起获取执行任务所需的变量。例如,假设AddressValidation任务需要一个address变量。使用此变量获取任务可能类似于:
List<LockedExternalTask> tasks = externalTaskService.fetchAndLock(10, "externalWorkerId")
.topic("AddressValidation", 60L * 1000L).variables("address")
.execute();
for (LockedExternalTask task : tasks) {
String topic = task.getTopicName();
String address = (String) task.getVariables().get("address");
// work on task for that topic
...}
然后,结果任务将包含所请求变量的当前值。请注意,变量值是从外部任务的执行在作用域层次结构中可见的值。有关详细信息,请参见“ 可变范围和可变可见性 ”一章。
为了获取所有变量,variables()应省略对方法的调用
List<LockedExternalTask> tasks = externalTaskService.fetchAndLock(10, "externalWorkerId")
.topic("AddressValidation", 60L * 1000L)
.execute();
for (LockedExternalTask task : tasks) {
String topic = task.getTopicName();
String address = (String) task.getVariables().get("address");
// work on task for that topic
...}
为了对序列化变量值(通常是存储自定义Java对象的变量)进行反序列化,必须调用enableCustomObjectDeserialization()。否则,一旦从变量映射中检索到序列化变量,就会引发一个异常,即该对象未反序列化。
List<LockedExternalTask> tasks = externalTaskService.fetchAndLock(10, "externalWorkerId")
.topic("AddressValidation", 60L * 1000L)
.variables("address")
.enableCustomObjectDeserialization()
.execute();
for (LockedExternalTask task : tasks) {
String topic = task.getTopicName();
MyAddressClass address = (MyAddressClass) task.getVariables().get("address");
// work on task for that topic
...}
外部任务优先级
技术支持:盘古BPM工作流平台
相关教程
- 2020-04-28
- 2020-04-27
- 2020-04-26
- 2020-04-25
- 2020-04-24
- 2020-04-23
- 2020-04-22
- 2020-04-18
- 2020-04-16
- 2020-04-14