Poison Message Handling in WCF MSMQ 4.0
I am trying to handle the poison messages in WCF with MSMQ transport.
I followed the below link for creating the original and poison services.
http://msdn.microsoft.com/en-us/library/aa395218.aspx
The only difference is instead of self hosting , I hosted the 2 servces in IIS 开发者_Python百科with a single host project.
The configuration of both the services is below.
<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>
Both services are running properly.
The issue is when the message is put into the poison queue, the poison service is not processing the message. I observed the messages in Poison queue, they are targeting to original service only. then how the poison service can process them? after going through MSDN , I got to know that by setting Service behavior attribute , WCF channel takes care this issue. The following paragraoh explains the same.
"Messages in the poison message queue are messages that are addressed to the service that is processing the message, which could be different from the poison message service endpoint. Therefore, when the poison message service reads messages from the queue, the WCF channel layer finds the mismatch in endpoints and does not dispatch the message. In this case, the message is addressed to the order processing service but is being received by the poison message service. To continue to receive the message even if the message is addressed to a different endpoint, we must add a ServiceBehavior to filter addresses where the match criterion is to match any service endpoint the message is addressed to. This is required to successfully process messages that you read from the poison message queue."
But my poison service is not processing the poisoned messages?
I am not able to figure out the issue.
I have the same problem.
I was wondering if it is because when hosting netMsmq services in IIS, the queue name has to match the service name. In the case of the initial message queue, this is OK (e.g. the queue would be something like private/SimpleService/Service1.svc), but then the poison queue is called private/SimpleService/Service1.svc;poison, which obviously does not match the poison service name.
I have had samples working fine when self-hosted. This problem only seems to be with IIS hosting.
If this is the problem, then I have no solution I'm afraid...
Update:
This comment from
http://msdn.microsoft.com/en-us/library/ms789042(v=VS.90).aspx
Suggests that the problem is as I thought:
"A WAS-hosted application cannot be activated based on messages in a system queue, such as the system-wide dead-letter queue, or sub-queues, such as poison sub-queues. This is a limitation for this version of the product"
I don't think it is possible to specify an alternative custom poison message queue, so the alternatives are:
1) Write code in the service implementation to move messages to an alternative queue on failure 2) Use a trigger to transfer messages from the poison message queue to another queue and have an IIS hosted service listen to that 3) Host your poison message service in a custom EXE instead of IIS
I recently ran into this with IIS7. Yes, by default, WAS-hosted application don't work on poison queues However, I believe there is a way to host WCF service in IIS that would detect poison messages. The way I think about it is that poison message service is really sub-service of the main WCF service and it's sort of dependent on the main service. To host the sub-service in WCF, I implemented custom ServiceHostFactory. Inside ServiceHostFactory, I override OnOpening and OnClosing events of the main service host to open and close the poison message service. Here is a sample code:
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;
}
}
}
After that, just set the 'Factory' attribute on you .svc file with your custom host factory class and it should take care of the poison message handling for you.
精彩评论