首页 > 代码库 > SharePoint Workflow架构(二)Workflow 事件处理(Event Processing)

SharePoint Workflow架构(二)Workflow 事件处理(Event Processing)

[译者按]Andy Li这篇文章,是我看过的最好的,最透彻的关于SharePoint Workflow架构的文章。通过阅读他的文章,我才清楚的了解了SharePoint Workflow的运作机制,并且在遇到问题的时候,知道如何下手查找问题。因此翻译过来,希望对Workflow的开发人员有帮助。


这篇博客是由Andy Li贡献的,他是SharePoint开发人员支持组的处理疑难问题的工程师。原文地址。这个关于Workflow的系列,是他贡献给社区的,帮助大家更好的理解Workflow运行时的内部机制,以及如何和SharePoint交互。

这篇文章由SPFarmer翻译。


前三篇地址:

宿主服务(HostService): SPWinOeHostService

SharePoint 和Workflow Runtime的结合

Workflow 事件处理管道(Event Processing Pipeline)


High Level Event Processing

大多数workflow都是事件驱动型的workflow。当workflow到达特定的需要从外部输入的Activitiesworkflow runtime就会调用SharePoint持久化服务,把workflow实例的数据保存到内容数据库里。下面的数据流图表简要的描述了SharePoint workflow是如何响应外部的event的。

技术分享

1. Eventreceiver 响应用户操作

就像我们之前说的,有几种 workflow event receivers可以响应用户操作SPWinOEItemEventReceiver 响应 task list item 事件, 比如 ItemUpdated andItemDeleted这些事件包含如下信息:

- 和这个事件关联的task或者 list item.

- 有改动的Task或者List itemBeforeProperties AfterProperties.

- 事件类型,可以是 ItemAdded, ItemUpdatedItemDeleted orSharePoint event receiver处理的任何类型的事件.

Event receiver 发送事件数据给SPWorkflowManager.

2. En-queuing event

SPWorkflowManager会尝试运送事件给对应的workflow实例(每一个task都有一个“WorkflowInstanceID”属性,这也是SharePoint如何知道应该把事件发送给哪个workflow实例).

SPWorkflowManager在把事件传递之前,以WorkItem的形式,把事件加到内容数据库的队列里(ScheduleWorkItem). 这个是因为,实际上,事件传递过程可能是长,并且可能失败。因此加到队列里,很简单是为了能够容错。如果传递这个事件出错,我们可以重新获取这个事件,然后重新尝试传递。 我们会介绍如何通过读取数据库来查找workflow事件传递失败的原因。

3. Delivering event

SPWorkflowManager通过把事件发送给SharePoint workflow runtime (SPWinOeHostService)来继续传输事件。宿主服务负责加载workflow实例到runtime里,并且提交事件到workflow实例里。这个时候,就会调用OnTaskChanged activityMethodInvoked 方法。

4. Dequeuing event

如果workflow实例成功的处理了事件,我们会在ScheduleWorkItems表里面删除这个事件,并把这个事件管道标记成结束。

Event Pipeline

为了更好的了解这些组件是如何在一起工作的,让我们看一下SharePoint处理task相关的activity的典型的情景。这个过程过程始于 workflow 运行CreateTask activity. 结束于workflow完成CompleteTask activity.

技术分享

1. CreateTask activity继承了CallExternalMethodActivity. 这个 activityworkflow instanceSharePoint开始数据交换会话的地方。  TaskId也是在这个时候初始化的。

2. Workflowruntime 调用SPWinOeTaskService.CreateTask来创建一个真正的task item. 记住SPListeitem只是在内存里面被创建了,并且没有被提交到数据库里。真正的提交是在workflow持久化之前,由WorkBatch service实现的。

3. Workflow的下一个activity OnTaskChanged activity  Workflow runtime会调用 Subscription Service,它会在我们刚才创建的task上,建立一个用来处理ItemUpdated时间的event receiver

4. Workflowruntime会创建一个event sink来响应OnTaskChanged 事件。

5. 现在workflow实例没有其他事情要做了,因为他在等待用户提交task。持久化服务会调用,保存workflow实例到内容数据库。记住,内存里的SPListitem也是在这个时候被提交。

6. 用户通过Task表单提交对task的修改。Task表单实际上一个apsx页面,通过调用Object Module来更新task item.  Task表单调用的是SPWorkflowTask.AlterTask() API来提交对task的修改。这个会触发以前注册上来的event receiverItemUpdated事件。

NOTE: 你可能会初一到,每一个workflow task都有一个特别的field“WorkflowVersion”. 这个列的值,被SPWorkflowTask.AlterTask()设置成一个大一1的值(表示这个tasklock),这个表示这个task上面有一个更新,并且需要相应的workflow实例来做一些action。这个同时也意味着,在被workflow实例处理之前,这个task被保持在lock状态。

问题:如果我多次调用了AlterTask() API,我收到了一个“taskloack”的异常,为什么呢?

答案: AlterTask API内部调用了SPListItem.Update(). 如果他检测到这个task属于一个正在运行的workflow instance, 它会把“WorkflowVersion”列的值设置成一个大于1的值。现在如果你尝试再次调用SPListItem.Update() ,他会检测 “WorkflowVersion”这个列,如果他的值大于1,我们停止更新,并且抛出这个异常。通过这种方式,我们在workflow处理完OnTaskChange事件之前,阻止对于item的任何修改。 只有在OnTaskChanged activityworkflow实例处理完之后, “WorkflowVersion”会被设置成1,表示这个task被解锁(unlock)了。

7. 现在我们继续。Event receiver会响应SPListItem.Update()并且通过调用SPWorkflowManager.RunWorkflow尝试把事件传输给workflow runtime

8.SPWorkflowManager 生成一个 WorkItem 并且把它放到数据库里(enqueuing, ScheduledWorkItems).  WorkItem记录的是,在workflow实例处理之前的,处于pending状态的taskItemUpdate事件。我们保存这个事件在内容数据库里是为了容错处理。如果因为任何原因,这个事件没有传递成功,workflowtimer job可以从数据库里找到这个WorkItem,并且继续处理他。

9.SPWorkflowManager 继续传输这个事件到SharePoint workflow runtime(SPWinOeHostService).  SPWinOeHostService检查这个事件,并且从这个事件获取两个数据: WorkflowInstanceID TaskID.  It加载workflow实例到 workflow runtime. 并且提交OnTaskChanged 事件到 workflow 实例,你的OnTaskChanged.OnInvoked() 里面的自定义代码在这个时期被调用。

问题:TaskId存储在哪里?

答案:每一个workflow task都有一个列叫做“GUID”,这个就是 TaskID.

10. workflowruntime 执行完 OnTaskChanged activity之后,他把 WorkItem 从数据库里面删掉。Task “WorkflowVersion”列会被设置成 “1” (unlocked)然后 event receiver is deleted from the tasklist.

关于Workflow Timer Jobs

我们曾经说过,当SPWorkflowManager尝试去传送事件到宿主服务(SPWinOEHostService),他需要检查几个条件。 其中的一个条件是确认workflow没有锁住并且没有在其他地方运行。一个SharePoint场环境,可以有多个前端服务器(web frontend servers)workflow runtime可以寄宿在其中的任何一个server。我们需要确保workflow instance在任何时间内,只被其中的一个workflow runtime 处理。SharePoint的机制是在数据库里设置一个flag,来标识锁定状态。SPWorkflowManager可以简单的查出workflow是否被锁定。如果这个workflow被锁定了, SPWorkflowManager会把 WorkItem放到数据库的队列里,timer job会异步处理这个事件。

Workflow timerjob 负责处理队列里的WorkItems. 这种情况下timer service就是 workflow runtime的宿主。这里有3个和workflow相关的timer job,它们处理不同的作业。下面的表格列出了它们的主要的功能:

Job

Description

SPWorkflowFailOverJobDefinition

一个workflow可能因为多种原因失败。如果他在中途失败,他会被锁定并且不能够重新启动。Fail-over timer job的作用是解锁这些workflow,使它们能继续运行。

SPWorkflowJobDefinition

处理ScheduleWorkItem队列里的WorkItems.  w3wp.exe总是尝试在第一时间传输事件到workflow。但是如果workflow被别的进程锁住了,它会把事件放到数据库队列里。默认情况下,这个 timer job 会处理这些事件。

SPWorkflowAutoCleanJobDefinition

清楚数据库里的旧的workflow instances。默认情况下,这个job会清楚60天之前完成的workflows。你可以通过修改SPWorkflowAssociation.AutoCleanupDays属性来设置默认值 

每五分钟,SPWorkflowJobDefinition被唤醒并且在数据库里查找 WorkItems。数据库里的WorkItem记录包含了所有pending状态的工作。比如workflow instance ID, task item ID, event type等等。对于每一个WorkItems, timer job通过WorkItem记录重新组装 SPWorkflowEvents对象。他调用SPWorkflowManager.RunWorkflow() 并且把事件传递给Workflow实例。


未完待续。

SharePoint Workflow架构(二)Workflow 事件处理(Event Processing)