【问题标题】:Is it possible to have a generic WCF service for handling multiple MSMQ endpoints?是否可以使用通用 WCF 服务来处理多个 MSMQ 端点?
【发布时间】:2016-01-14 03:51:24
【问题描述】:

我们的团队正在构建一个服务,用于使用 WCF(通过 msmqIntegrationBinding)处理来自多个远程 MSMQ 队列的消息。我们希望能够根据它们通常消耗的资源量来限制不同的队列组(通过serviceThrottling)。

我的想法是让单一服务​​类型处理来自多个队列的消息,并根据消息类型确定如何处理它们。不幸的是,我无法找到使用MsmqMessage<T> 的通用方法,因为它期望消息的确切类型。 MsmqMessage<object> 不起作用,因为我认为它正在尝试为类型 object 查找序列化程序。

关于如何完成这项工作或替代方法的任何想法?最好仍然使用 WCF,因为它已经内置了死信处理。

示例配置:

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

合同示例:

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

【问题讨论】:

    标签: c# wcf msmq msmqintegrationbinding


    【解决方案1】:

    这个问题实际上并不是由MsmqMessage&lt;object&gt; 引起的。

    当排队消息为 XML 格式时,服务使用ServiceKnownTypeAttribute 来确定服务支持哪些类型进行 XML(反)序列化。在这种情况下,object 并不是真正有效的可序列化类型,因此它可能被忽略了。

    为了支持对 XML 消息的通用处理,您可以将 [ServiceKnownType(typeof(XElement))] 添加到您的服务合同中,并接受 MsmqMessage&lt;object&gt; 作为您的服务方法的参数。这将允许您检查MsmqMessage&lt;T&gt; 对象的属性以确定应如何处理它。另一种可能的选择是使用ServiceKnownTypeAttribute 中的overload,它接受一个方法参数来动态构建您支持的类型列表。

    我检查过的唯一其他serialization formatBinary,所以请记住,它们的处理方式可能都不同。对于Binary 格式,不需要ServiceKnownTypeAttribute,因为类型信息包含在二进制有效负载中(仅使用System.Guid 进行了测试)。如果您打算使用Binary 格式,请务必继续使用MsmqMessage&lt;object&gt; 而不是MsmqMessage&lt;XElement&gt;,因为实际的对象类型将通过而不是XElement

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-05
      • 2010-09-27
      • 2015-08-20
      • 2012-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多