Is it possible to have a generic WCF service for handling multiple MSMQ endpoints?

让人想犯罪 __ 提交于 2020-01-07 03:06:35

问题


Our team is building a service for processing messages from multiple remote MSMQ queues using WCF (via msmqIntegrationBinding). We would like to have the ability to throttle different groups of queues (via serviceThrottling) based on the amount of resources they typically consume.

My idea is to have a single service type processing messages from multiple queues and determining what to do with them based on the type of message. Unfortunately, I can't figure out a generic way to use MsmqMessage<T> as it's expecting the exact type of the message. MsmqMessage<object> doesn't work because I think it's trying to find a serializer for type object.

Any ideas on how to get this work or alternative approaches? Preferably still using WCF since it has dead-letter handling already built-in.

Example Configuration:

<services>
    <service name="MessageProcessor.LowResourceMsmqReceiverService" behaviorConfiguration="LowResourceMsmqServiceBehavior">
        <endpoint address="msmq.formatname:DIRECT=OS:.\private$\EmailQueue" binding="msmqIntegrationBinding" bindingConfiguration="IncomingMessageBinding" contract="MessageProcessor.IMsmqReceiverService" />
        <endpoint address="msmq.formatname:DIRECT=OS:.\private$\LoggingQueue" binding="msmqIntegrationBinding" bindingConfiguration="IncomingMessageBinding" contract="MessageProcessor.IMsmqReceiverService" />
    </service>
    <service name="MessageProcessor.HighResourceMsmqReceiverService" behaviorConfiguration="HighResourceMsmqServiceBehavior">
        <endpoint address="msmq.formatname:DIRECT=OS:.\private$\DataImportQueue" binding="msmqIntegrationBinding" bindingConfiguration="IncomingMessageBinding" contract="MessageProcessor.IMsmqReceiverService" />
        <endpoint address="msmq.formatname:DIRECT=OS:.\private$\DataExportQueue" binding="msmqIntegrationBinding" bindingConfiguration="IncomingMessageBinding" contract="MessageProcessor.IMsmqReceiverService" />
    </service>
</services>
<behaviors>
    <serviceBehaviors>
        <behavior name="LowResourceMsmqServiceBehavior">
            <serviceThrottling maxConcurrentCalls="50" />
        </behavior>
        <behavior name="HighResourceMsmqServiceBehavior">
            <serviceThrottling maxConcurrentCalls="3" />
        </behavior>
    </serviceBehaviors>
</behaviors>

Example Contract:

[ServiceContract]
[ServiceKnownType(typeof(object))]
public interface IMsmqReceiverService
{
    [OperationContract(IsOneWay = true, Action = "*")]
    void Receive(MsmqMessage<object> message);
}

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, InstanceContextMode = InstanceContextMode.PerCall)]
public abstract class TransactionalMsmqReceiverService : IMsmqReceiverService
{
    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
    [TransactionFlow(TransactionFlowOption.Allowed)]
    public void Receive(MsmqMessage<object> message)
    {
        // TODO: Handle multiple message types here
    }
}

public sealed class LowResourceMsmqReceiverService : TransactionalMsmqReceiverService { }

public sealed class HighResourceMsmqReceiverService : TransactionalMsmqReceiverService { }

回答1:


The issue was not actually caused by MsmqMessage<object>.

When the queued messages are in XML format, the service uses the ServiceKnownTypeAttribute to determine what types are supported by the service for XML (de)serialization. In this case, object isn't really a valid serializable type so it was probably ignored.

In order to support generic processing of XML messages, you can add [ServiceKnownType(typeof(XElement))] to your service contract and accept MsmqMessage<object> as the argument to your service method. This will allow you to check properties of the MsmqMessage<T> object to determine how it should be processed. Another possible option would be to use the overload of the ServiceKnownTypeAttribute that accepts a method parameter to dynamically build a list of your supported types.

The only other serialization format I checked is Binary, so keep in mind they are all likely processed differently. For the Binary format specifically, no ServiceKnownTypeAttribute is required as the type information is included in the binary payload (only tested this with System.Guid). If you intend to use the Binary format, it's important you continue to use MsmqMessage<object> rather than MsmqMessage<XElement> as the actual object type will come through instead of XElement.



来源:https://stackoverflow.com/questions/33152760/is-it-possible-to-have-a-generic-wcf-service-for-handling-multiple-msmq-endpoint

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!