IT技术互动交流平台

SharePointWorkflowTroubleShooting(一)Task被锁住或者卡住

发布日期:2015-01-13 19:36:39

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

 

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

这篇文章由SPFarmer翻译。

 

前四篇地址:

宿主服务(HostService): SPWinOeHostService

SharePoint 和Workflow Runtime的结合

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

Workflow 事件处理(Event Processing)


Locked/StuckTasks

锁住或者卡住的task是很多人在workflow里很常见的问题。人们问我,当一个task被锁定之后,如何解锁呢?我总是这样回答:为什么这个task会被锁住呢?很多人真的不知道,是什么导致task被锁定了,而是简单想去解锁,并且希望这个能够解决问题。事实是这个只会让问题更糟糕!

实际上,是没有一个合适的方法来解锁task的。本质上,锁定task是通过把“WorkflowVersion”列设置成1来实现的(在以前的博客里我们提到过,1代表未被锁定)。 尝试解锁带来的问题是,它不知道Workflow实例到底发生了什么,Workflow实例是在哪里停止的,workflow是否期待你刚刚解锁的task有更新,等等。

因此,我们再来看一下,一个task是如何被卡主或者锁住的。首先,我们已经知道,如果一个用户通过task表单提交了一个task,这个task就会进去到锁定状态。这个锁定状态会一直持续到workflow 实例处理完 OnTaskChanged 事件 (如果你不明白为什么,那么请阅读本系列第一部分). 因此,如果你尝试重新提交这个task,无论是通过代码还是页面,你就会得到“这个task已经被锁住”的异常。你等待几个小时或者几天之后,重新提交这个task,还是会得到同样的异常,为什么呢?

下面是原因:

#1 ItemUpdated 还没有被workflow实例处理.因此task仍然处于锁定状态。

#2 ItemUpdated 从来没有到达workflow引擎 (EventDeliveryFailedException). 同样,workflow没有处理这个事件,因此task仍然处于锁定状态。

#3 workflow 已经处理了 ItemUpdated 事件,但是task仍然没有解锁(被要求这样)

#1: 让我们先来弄清楚,用户提交一个task的时候,都发生了什么。首先,我们知道一个event receiver被触发了。它会尝试输送事件到workflow。SPWorkflowManager 需要加载workflow 实例到runtime来传输这个事件。然后,如果workflow 实例处于锁定状态,SPWorkflowManager 就不能够传输这个事件了。一个 WorkItem 会被加到内容数据库的的队列里(ScheduledWorkItems 表), timer job 会重新处理它。如果timer job没有运行,那么就没有人来处理这个事件。

#2: EventDeliveryFailedException是workflow里最著名(或者最不臭名昭著)的异常。取决于内部的异常,实际上有不同的原因会导致这个异常。最通常的情况如下:

EngineRunWorkflow: System.Workflow.Activities.EventDeliveryFailedException:

Event "OnTaskChanged" on interface type "Microsoft.SharePoint.Workflow.ITaskService" for instance id "84f908b6-0357-497c-b7cc-8021798dc706" cannot be delivered.

--->System.Workflow.Runtime.QueueException: Event Queue operation failed withMessageQueueErrorCode QueueNotFound for queue 'Message Properties InterfaceType:Microsoft.SharePoint.Workflow.ITaskService Method Name:OnTaskChanged CorrelationValues: ff5aa7b7-b6e4-4efb-84ef-27750b17b8ca '.

atSystem.Workflow.Runtime.WorkflowQueuingService.GetQueue(IComparable queueID)

Windows SharePointServices Workflow Infrastructure Engine RunWorkflow:

System.Workflow.Activities.EventDeliveryFailedException:Event "OnTaskChanged" on interface type "Microsoft.SharePoint.Workflow.ITaskService" for instance id

"4565fe7f-6043-4e8b-8896-4565fe7f9058" can not be delivered. --->

System.NullReferenceException:Object reference not set to an instance of an object. atMicrosoft.SharePoint.Workflow.SPWorkflowHostServiceBase.LoadInstanceData (GuidinstanceId, Boolean& compressedData)

EventDeliveryFailedExceptionwith QueueNotFound

让我们先讨论QueueNotFound。 QueueNotFound 是一个workflow runtime 异常。他的意思是说,workflow并没有在等待你尝试传输给它的事件。另一种说法,对于你提交的这个task,workflow并没有等待发生在它身上的任何事件。这个还可能表示,workflow在等待task A,但是你在提交task B。简单的来说,workflow实例并没有得到它想要的事件。

那究竟发生了什么?有好几种原因可能导致这个问题:

1. Workflow实例并没有正确的持久化。Workflow通常在没有其他事情需要处理的时候被持久化。尤其是当它运行到 OnTaskChanged activity. 持久化服务会尝试保存workflow 实例到内容数据库里。如果在持久化过程中出了问题,那么存到数据库里的是workflow实例的前一个状态。这样就完全错了。如果你在workflow里面创建了一个新的task,workflow完全不知道这是在干什么,因为最新状态的workflow实例没有被保存到数据库里。这就好像workflow 穿越到了没有创建task之前。现在,你尝试提交这个task,workflow不知道你要做什么。因此你就得到了QueueNotFound 的EventDeliveryFailedException 异常。

2. 另外一种情况就是,workflow在等待Task A,但是你提交了task B。可能导致这种情况的是correlation 参数乱套了。还记得在workflow里,你为每一个task创建了一个TaskId吗?是的,这个就是每个会话的唯一标示。每一个CreateTask 和OnTaskChanged 对需要和其他task不一样的,单独的TaskId。我们看到的最通常的情况是,人们为每一对CreateTask/OnTaskChanged使用了共享的变量。如果你的所有task都是顺次执行的,不会出问题。但是如果你的task是并行运行的,你的这种设计就肯定有问题了。Task之间共享TaskId参数会导致竞争状态。一个TaskId会被同时分配给task A和B(因为是并行的)。出现问题的几率可能比较低,但是如果你随机的得到EventDeliveryFailedException,你最好检查一下你是否使用了一个共享的TaskId。

3. Before August 2011 CU for 在SharePoint 2010的2011年8月份的CU之前, SharePoint处理事件的过程有一些问题,会导致workflow持久化到一个错误的状态。在2011年8月份的CU中,处理事件的过程更加健壮,但是在处理事件的过程中,你可能会感觉到一些延迟。因此如果你没有别的选择了,请务必保证你安装了2011年8月份的CU。

EventDeliveryFailedExceptionwith NullReferenceException

注意到,调用堆栈显示“SPWorkflowHostServiceBase.LoadInstanceData” 方法失败的了。这个是SharePoint持久化服务的一部分。 在SharePoint workflow runtime传输事件到workflow实例之前,它需要加载workflow实例到内存里。这个异常显示,workflow实例没有被正确的持久化,因为一些对象看起来是null。在2011年8月份的 CU里,我们添加了更多的诊断log到ULS里面,用来查找和持久化服务有关的问题。下面是一个例子。因此如果你不确认你的workflow是否在持久化上有问题,请在ULS里面查找下面的Log。

Failed to persistworkflow instance: 3c489d77-355c-4beb-86d4-1f106f26113c with error code: 5,

instance datasize: 34505, internal state: Running, processing id:4db2b5e9-cf02-479f-83fc-db106a432ba4 15bfccd3-663b-449e-8d37-113494e4f892

有可能导致这个异常的原因之一,是workflow执行的时间太长了。SharePoint有一个硬性的要求,如果workflow运行了20分钟还没有达到下一个持久化点,它的状态会被fail-over 的timer job重新设置。 我们以前提到过,timer job 会检测workflow是否中途出问题了(死了)。如果是这样的话,他会把窗台重新设置解锁。fail-over timer job 检测死workflow的方法是,检测这个workflow运行了多久。因为绝大多数的workflow,应该用几分钟甚至几秒钟的时间完成它的工作。因此如果在数据库里,显示这个workflow已经运行了20分钟以上,它实际上可能什么都没干(卡住了)。

延伸阅读:

  • 专题推荐

About IT165 - 广告服务 - 隐私声明 - 版权申明 - 免责条款 - 网站地图 - 网友投稿 - 联系方式
本站内容来自于互联网,仅供用于网络技术学习,学习中请遵循相关法律法规