简体   繁体   English

是否可以使用通用WCF服务来处理多个MSMQ端点?

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

Our team is building a service for processing messages from multiple remote MSMQ queues using WCF (via msmqIntegrationBinding ). 我们的团队正在构建一项服务,以使用WCF(通过msmqIntegrationBinding )处理来自多个远程MSMQ队列的消息。 We would like to have the ability to throttle different groups of queues (via serviceThrottling ) based on the amount of resources they typically consume. 我们希望有能力根据通常消耗的资源量来限制不同的队列组(通过serviceThrottling )。

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<T>的通用方法,因为它期望消息的确切类型。 MsmqMessage<object> doesn't work because I think it's trying to find a serializer for type object . MsmqMessage<object>不起作用,因为我认为它正在尝试为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. 最好仍使用WCF,因为它已内置了死信处理功能。

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 { }

The issue was not actually caused by MsmqMessage<object> . 该问题实际上不是由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. 当排队的消息为XML格式时,服务将使用ServiceKnownTypeAttribute来确定服务支持XML(反序列化)的类型。 In this case, object isn't really a valid serializable type so it was probably ignored. 在这种情况下, object实际上不是有效的可序列化类型,因此它可能被忽略了。

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. 为了支持XML消息的常规处理,可以将[ServiceKnownType(typeof(XElement))]到服务协定中,并接受MsmqMessage<object>作为服务方法的参数。 This will allow you to check properties of the MsmqMessage<T> object to determine how it should be processed. 这将使您可以检查MsmqMessage<T>对象的属性,以确定应如何处理它。 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. 另一个可能的选择是使用ServiceKnownTypeAttribute重载 ,该重载接受方法参数来动态构建所支持类型的列表。

The only other serialization format I checked is Binary , so keep in mind they are all likely processed differently. 我检查的唯一其他序列化格式Binary ,因此请记住,它们的处理方式可能都不同。 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 ). 特别是对于Binary格式,不需要ServiceKnownTypeAttribute ,因为类型信息包含在二进制有效负载中(仅使用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 . 如果打算使用Binary格式,则继续使用MsmqMessage<object>而不是MsmqMessage<XElement>是很重要的,因为实际的对象类型将代​​替XElement通过。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM