有没有办法制作方法
myMessageService.CreateMessageQueueClient().Publish(myMessage);
向所有接收者广播消息?
答案 0 :(得分:2)
问题是,RegisterHandler<T>
在内部使用T
的类型来构建它侦听的队列名称。因此,唯一的机会就是通过利用自定义扇出交换到多个队列,使用以下解决方案脱离轨道:
var fanoutExchangeName = string.Concat(QueueNames.Exchange,
".",
ExchangeType.Fanout);
在您系统的某个时刻,您必须确保使用以下代码进行交换:
var rabbitMqServer = new RabbitMqServer();
var messageProducer = (RabbitMqProducer) rabbitMqServer.CreateMessageProducer();
var channel = messageProducer.Channel; // you can use any logic to acquire a channel here - this is just a demo
channel.ExchangeDeclare(fanoutExchangeName,
ExchangeType.Fanout,
durable: true,
autoDelete: false,
arguments: null);
现在我们可以向此扇出发布消息:
var message = new Message<T>(yourInstance);
messageProducer.Publish(QueueNames<T>.In, // routing key
message, // message
fanoutExchangeName); // exchange
所以现在消息被发布到我们的交换机,但我们需要将队列绑定到消费组件中的交换,我们这样做:
var rabbitMqServer = new RabbitMqServer();
var messageQueueClient = (RabbitMqQueueClient) rabbitMqServer.CreateMessageQueueClient();
var channel = messageQueueClient.Channel; // you just need to get the channel
var queueName = messageQueueClient.GetTempQueueName();
channel.QueueBind(queueName, // queue
fanoutExchangeName, // exchange
QueueName<T>.In); // routing key
在最后一个(也是唯一的)消费者断开连接后,队列会自动删除,并且在重启RabbitMq后无法生存。
黑客部分现在正在倾听......
var consumer = new RabbitMqBasicConsumer(channel);
channel.BasicConsume(queueName,
false,
consumer);
Task.Run(() =>
{
while (true)
{
BasicGetResult basicGetResult;
try
{
basicGetResult = consumer.Queue.Dequeue();
}
catch (EndOfStreamException endOfStreamException)
{
// this is ok
return;
}
catch (OperationInterruptedException operationInterruptedException)
{
// this is ok
return;
}
catch (Exception ex)
{
throw;
}
var message = basicGetResult.ToMessage<T>();
// TODO processing
}
});
此解决方案不提供任何自动重新连接,过滤器或其他内容。
基本演练是available here。
编辑:
我想到的一件事是:您可以使用ServiceStack.Messaging.MessageHandler<T>
实例轻松提供回复和重试。