WCF MSMQ 4.0中的毒消息处理

9

我正试图使用MSMQ传输来处理WCF中的毒消息。

我按照以下链接创建了原始服务和毒服务:

http://msdn.microsoft.com/en-us/library/aa395218.aspx

唯一的区别是,我将这两个服务托管在IIS中,使用单个主机项目。以下是两个服务的配置:

<services>
  <service behaviorConfiguration="MainMSMQWCFService.Service1Behavior"
    name="MainMSMQWCFService.OrderProcessorService">
    <endpoint address="net.msmq://localhost/private/servicemodelsamplespoison"
      binding="netMsmqBinding" bindingConfiguration="PoisonBinding"
      contract="MainMSMQWCFService.IOrderProcessor" />
  </service>
  <service behaviorConfiguration="MainMSMQWCFService.PoisonHandlingServiceBehavior"
    name="MainMSMQWCFService.PoisonHandlingService">
    <endpoint address="net.msmq://localhost/private/servicemodelsamplespoison;poison" 
              binding="netMsmqBinding"
              bindingConfiguration="PoisonBinding2"
              contract="MainMSMQWCFService.IOrderProcessor">
    </endpoint>
  </service>
</services>

两个服务都正常运行。

问题在于当消息被放入毒队列时,毒服务没有处理该消息。我观察了毒队列中的消息,它们只针对原始服务。那么毒服务如何处理它们呢?通过查阅MSDN,我了解到通过设置服务行为属性,WCF通道可以解决此问题。以下段落说明了相同的内容。

“毒消息队列中的消息是针对正在处理消息的服务的消息,这可能与毒消息服务端点不同。因此,当毒消息服务从队列中读取消息时,WCF通道层发现端点不匹配并且不会分派该消息。在这种情况下,该消息针对订单处理服务,但由毒消息服务接收。要继续接收消息,即使消息针对不同的端点,我们必须添加ServiceBehavior来过滤匹配标准以匹配消息寄送到的任何服务端点。这是成功处理从毒消息队列中读取的消息所必需的。”

但我的毒服务没有处理受污染的消息?

我无法找出问题所在。


哦,你只能在IIS中托管HTTP绑定。你是指WAS吗? - John Grey
2个回答

4

我有同样的问题。

我在想是否是因为在IIS中托管netMsmq服务时,队列名称必须与服务名称匹配。对于初始消息队列来说,这是可以的(例如队列可能是类似于private/SimpleService/Service1.svc),但毒性队列则被称为private/SimpleService/Service1.svc;poison,显然不符合毒性服务名称。

当自主托管时,我的示例正常工作。这个问题似乎只出现在IIS托管上。

如果这是问题,那么恐怕我没有解决方案...

更新:

来自http://msdn.microsoft.com/en-us/library/ms789042(v=VS.90).aspx的此评论表明问题就像我想的那样:

"基于系统队列(如系统范围内的死信队列或子队列(如毒性子队列))的消息不能激活托管在 WAS 中的应用程序。该产品版本存在此限制"

我认为不可能指定替代的自定义毒性消息队列,因此可选方案为:

1)在服务实现中编写代码,在失败时将消息移动到另一个队列中 2)使用触发器将消息从毒性消息队列转移到另一个队列,并让托管在IIS中的服务监听该队列 3)将您的毒性消息服务托管在自定义EXE而不是IIS中


微软应该在 net.msmq 绑定中添加 自定义毒消息队列 功能。 - Abdul Rauf

2

我最近在使用IIS7时遇到了这个问题。默认情况下,WAS托管的应用程序无法在毒消息队列上运行。然而,我相信有一种方法可以在IIS中托管WCF服务,并检测毒消息。我的想法是,毒消息服务实际上是主WCF服务的子服务,并且在某种程度上依赖于主服务。为了在WCF中托管子服务,我实现了自定义ServiceHostFactory。在ServiceHostFactory内部,我重写了主服务主机的OnOpening和OnClosing事件,以打开和关闭毒消息服务。以下是示例代码:

public class HostFactory : ServiceHostFactory
{ 
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
    {
        SomeServiceHost host = new SomeServiceHost(serviceType, baseAddresses);
        host.PoisonMsmqServiceType = typeof(PoisonHandler);
        return host;
    }
}

public class SomeServiceHost : ServiceHost
{
    private ServiceHost poisonMsmqServiceHost;


    public Type PoisonMsmqServiceType { get; set; }

     public SomeServiceHost(Type serviceType, params Uri[] baseAddresses)
    : base(serviceType, baseAddresses) { }

    protected override void OnOpening()
    {
        base.OnOpening();

        if (this.PoisonMsmqServiceType != null)
        {
            this.poisonMsmqServiceHost = new ServiceHost(this.PoisonMsmqServiceType);
            this.poisonMsmqServiceHost.Open();
        }
    }

    protected override void OnClosing()
    {
        base.OnClosing();

        if (this.poisonMsmqServiceHost != null)
        {
            this.poisonMsmqServiceHost.Close();
            this.poisonMsmqServiceHost = null;
        }
    }
}

接下来,只需在您的 .svc 文件上设置“Factory”属性,并使用自定义主机工厂类,它将为您处理有毒消息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接