破碎的WF4工作流程补液
考虑在IIS中运行的WF4项目,使用单个工作流定义(xamlx)和SqlInstanceStore来实现持久性。 我们没有直接托管xamlx,而是托管一个WorkflowServiceHostFactory,为每个客户在独立的端点上分配一个专用的WorkflowServiceHost。
这一直运行良好,直到我们需要一个新版本的工作流定义,所以现在在Flow.xamlx之上我有Flow1.xamlx。 由于与工作流服务的所有交互都包含了足够智能以识别所需版本的业务逻辑,因此这种自制版本对新启动的工作流程(在Flow.xamlx和Flow1.xamlx上)均可正常工作。
但是,在此更改无法重新激活之前启动的工作流(在servicehost引发UnknownMessageReceived异常之后)。 由于WF在告诉你为什么不能重新激活工作流(错误的版本,没有找到的实例,锁等),我们将一个SQL分析器附加到数据库中。
事实证明,WorkflowServiceHost在其查询中使用的“WorkflowServiceType”与存储实例的WorkflowServiceType不同。 可能这就是为什么它无法检测到持久实例。
由于我很确定我使用了相同的xamlx,所以我无法理解这个值是从哪里来的。 计算这个Guid的参数是什么,环境是否重要(sitename),以及我能做些什么来重新激活工作流程?
最后我反编译System.Activities.DurableInstancing。 SqlWorkflowInstanceStore上WorkflowHostType的唯一设置程序位于ExtractWorkflowHostType中:
private void ExtractWorkflowHostType(IDictionary<XName, InstanceValue> commandMetadata)
{
InstanceValue instanceValue;
if (commandMetadata.TryGetValue(WorkflowNamespace.WorkflowHostType, out instanceValue))
{
XName xName = instanceValue.Value as XName;
if (xName == null)
{
throw FxTrace.Exception.AsError(new InstancePersistenceCommandException(SR.InvalidMetadataValue(WorkflowNamespace.WorkflowHostType, typeof(XName).Name)));
}
byte[] bytes = Encoding.Unicode.GetBytes(xName.ToString());
base.Store.WorkflowHostType = new Guid(HashHelper.ComputeHash(bytes));
this.fireRunnableInstancesEvent = true;
}
}
我无法清楚地分辨调用代码路径,所以我必须在运行时找到WinDbg / SOS到IIS并打破HashHelper.ComputeHash。
我能够检索进入散列计算的XName,它的localname等于servicefile,名称空间等于[sitename] / [path] /。
最后,WorkflowHostType计算归结为:
var xName = XName.Get("Flow.xamlx.svc", "/examplesite/WorkflowService/1/");
var bytes = Encoding.Unicode.GetBytes(xName.ToString());
var WorkflowHostType = new Guid(HashHelper.ComputeHash(bytes));
底线:显然工作流只能在服务文件名,网站名和路径都与启动时相同(区分大小写)的情况下进行补充
链接地址: http://www.djcxy.com/p/17171.html上一篇: Broken WF4 workflow rehydration
下一篇: Specify address at runtime for generated workflow activities