使用ServiceStack广播rabbitMq消息

时间:2014-05-08 11:11:34

标签: servicestack rabbitmq

有没有办法制作方法

myMessageService.CreateMessageQueueClient().Publish(myMessage);

向所有接收者广播消息?

1 个答案:

答案 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>实例轻松提供回复和重试。