是否可以使用通用 WCF 服务来处理多个 MSMQ 端点?
Is it possible to have a generic WCF service for handling multiple MSMQ endpoints?
我们的团队正在构建一项服务,用于根据消息通常消耗的资源量使用 WCF(通过 msmqIntegrationBinding). We would like to have the ability to throttle different groups of queues (via serviceThrottling)处理来自多个远程 MSMQ 队列的消息。
我的想法是让单一服务类型处理来自多个队列的消息,并根据消息类型确定如何处理它们。不幸的是,我无法找到使用 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 { }
问题实际上并非由 MsmqMessage<object>
引起。
当排队消息采用 XML 格式时,服务使用 ServiceKnownTypeAttribute
来确定服务支持哪些类型以进行 XML(反)序列化。在这种情况下,object
并不是真正有效的可序列化类型,因此它可能被忽略了。
为了支持 XML 消息的通用处理,您可以将 [ServiceKnownType(typeof(XElement))]
添加到您的服务合同中,并接受 MsmqMessage<object>
作为您服务方法的参数。这将允许您检查 MsmqMessage<T>
对象的属性以确定应如何处理它。另一种可能的选择是使用接受方法参数的 ServiceKnownTypeAttribute
的 overload 来动态构建支持的类型列表。
我检查过的唯一其他 serialization format 是 Binary
,因此请记住它们的处理方式可能各不相同。具体来说,对于 Binary
格式,不需要 ServiceKnownTypeAttribute
,因为二进制有效负载中包含类型信息(仅使用 System.Guid
测试过)。如果您打算使用 Binary
格式,请务必继续使用 MsmqMessage<object>
而不是 MsmqMessage<XElement>
,因为实际的对象类型将通过而不是 XElement
.
我们的团队正在构建一项服务,用于根据消息通常消耗的资源量使用 WCF(通过 msmqIntegrationBinding). We would like to have the ability to throttle different groups of queues (via serviceThrottling)处理来自多个远程 MSMQ 队列的消息。
我的想法是让单一服务类型处理来自多个队列的消息,并根据消息类型确定如何处理它们。不幸的是,我无法找到使用 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 { }
问题实际上并非由 MsmqMessage<object>
引起。
当排队消息采用 XML 格式时,服务使用 ServiceKnownTypeAttribute
来确定服务支持哪些类型以进行 XML(反)序列化。在这种情况下,object
并不是真正有效的可序列化类型,因此它可能被忽略了。
为了支持 XML 消息的通用处理,您可以将 [ServiceKnownType(typeof(XElement))]
添加到您的服务合同中,并接受 MsmqMessage<object>
作为您服务方法的参数。这将允许您检查 MsmqMessage<T>
对象的属性以确定应如何处理它。另一种可能的选择是使用接受方法参数的 ServiceKnownTypeAttribute
的 overload 来动态构建支持的类型列表。
我检查过的唯一其他 serialization format 是 Binary
,因此请记住它们的处理方式可能各不相同。具体来说,对于 Binary
格式,不需要 ServiceKnownTypeAttribute
,因为二进制有效负载中包含类型信息(仅使用 System.Guid
测试过)。如果您打算使用 Binary
格式,请务必继续使用 MsmqMessage<object>
而不是 MsmqMessage<XElement>
,因为实际的对象类型将通过而不是 XElement
.