【问题标题】:Broken WF4 workflow rehydration损坏的 WF4 工作流程补液
【发布时间】:2013-08-27 12:52:50
【问题描述】:

考虑一个在 IIS 中运行的 WF4 项目,它具有一个工作流定义 (xamlx) 和一个用于持久性的 SqlInstanceStore。 我们不是直接托管 xamlx,而是托管一个 WorkflowServiceHostFactory,它为每个客户在单独的端点上启动一个专用的 WorkflowServiceHost。

这已经运行了一段时间,直到我们需要新版本的工作流定义,所以现在在 Flow.xamlx 之上我有 Flow1.xamlx。 由于与工作流服务的所有交互都使用足够智能的业务逻辑来识别所需版本,因此这种自制版本控制适用于新启动的工作流(在 Flow.xamlx 和 Flow1.xamlx 上)。

但是,在此更改之前启动的工作流无法重新激活(在帖子中,服务主机会引发 UnknownMessageReceived 异常)。 由于 WF 在告诉您为什么它不能重新激活工作流(错误版本、未找到实例、锁定等)方面并不过分冗长,我们将 SQL 分析器附加到数据库。

事实证明,WorkflowServiceHost 在其查询中使用的“WorkflowServiceType”与存储实例的 WorkflowServiceType 不同。可能这就是它无法检测到持久实例的原因。

因为我很确定我实例化了同一个 xamlx,所以我不明白这个值是从哪里来的。计算此 Guid 的参数有哪些,环境是否重要(站点名称),我可以做些什么来重新激活工作流?

【问题讨论】:

    标签: wcf persistence workflow workflow-foundation-4 workflowservice


    【解决方案1】:

    最后我反编译了 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,它的本地名称等于服务文件,命名空间等于 [站点名称]/[路径]/。

    最后 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));
    

    底线:显然,只有当服务文件名、站点名和路径与启动时相同(区分大小写)时,工作流才能重新水化

    【讨论】:

    • 我发现了一些看起来很有希望的事情:如果我有 .xamlx 托管实例并移动到 .svc,然后更改 servicedeployments 表中的路径,我可以进入 AppFabric 管理控制台并尝试暂停工作流程。然后,我得到一个非常明确的消息,即主机对象与显示的两个主机的地址不匹配。主机字符串很可能存储在实例表中的一个 blob 中。也许您可以更改存储的数据,使其看起来好像是在 .svc 主机上启动的。
    • Ruurd,我遇到了类似的问题。 InstancesTable 中的 WorkflowHostType guid 与我在代码中生成的不同。我需要看看它是如何计算 WorkflowHostType 的。您是如何让源/调试符号进入 computeHash 函数的?
    • 我没有进入 computeHash 函数。因为我只是想知道哈希计算的输入 - 相同的输入 => 相同的输出 - 以及堆栈中更高的参数,所以打破函数条目就足够了。如果您想查看计算,请查看参考来源:referencesource.microsoft.com/#System.ServiceModel.Internals/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多