【问题标题】:Poison Message Handling in WCF MSMQ 4.0WCF MSMQ 4.0 中的中毒消息处理
【发布时间】:2010-12-26 21:52:29
【问题描述】:

我正在尝试使用 MSMQ 传输处理 WCF 中的有害消息。

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

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

唯一的区别是我在 IIS 中使用单个主机项目托管了 2 个服务,而不是自托管。

这两个服务的配置如下。

<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?

标签: wcf msmq


【解决方案1】:

我也有同样的问题。

我想知道是不是因为在 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绑定中添加自定义毒消息队列功能
【解决方案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 文件上设置“工厂”属性,它就会为您处理有害消息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-02
    • 2015-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多