Возможно ли иметь общий сервис WCF для обработки нескольких конечных точек MSMQ?
Наша команда создает сервис для обработки сообщений из нескольких удаленных очередей MSMQ с использованием WCF (через msmqIntegrationBinding). Мы хотели бы иметь возможность регулировать различные группы очередей (через 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 { }
1 ответ
Проблема на самом деле не была вызвана MsmqMessage<object>
,
Когда сообщения в очереди находятся в формате XML, служба использует ServiceKnownTypeAttribute
определить, какие типы поддерживаются сервисом для XML (де) сериализации. В этом случае, object
на самом деле не является допустимым сериализуемым типом, поэтому он, вероятно, был проигнорирован.
Для поддержки общей обработки сообщений XML вы можете добавить [ServiceKnownType(typeof(XElement))]
к вашему контракту на обслуживание и принимаю MsmqMessage<object>
в качестве аргумента для вашего метода обслуживания. Это позволит вам проверить свойства MsmqMessage<T>
объект, чтобы определить, как это должно быть обработано. Другим возможным вариантом будет использование перегрузки ServiceKnownTypeAttribute
который принимает параметр метода для динамического построения списка поддерживаемых типов.
Единственный другой формат сериализации, который я проверил, Binary
Имейте в виду, что все они обрабатываются по-разному. Для Binary
формат конкретно нет ServiceKnownTypeAttribute
требуется, поскольку информация о типе включена в двоичную полезную нагрузку (проверяется только с System.Guid
). Если вы собираетесь использовать Binary
формат, важно продолжать использовать MsmqMessage<object>
скорее, чем MsmqMessage<XElement>
как фактический тип объекта будет проходить вместо XElement
,