基于RabbitMQ几种Exchange 模式详解
AMQP协议中的核心思想就是生产者和消费者隔离,生产者从不直接将消息发送给队列。生产者通常不知道是否一个消息会被发送到队列中,只是将消息发送到一个交换机。先由Exchange来接收,然后Exchange按照特定的策略转发到Queue进行存储。同理,消费者也是如此。Exchange 就类似于一个交换机,转发各个消息分发到相应的队列中。 RabbitMQ提供了四种Exchange模式:fanout,direct,topic,header 。 header模式在实际使用中较少,本文只对前三种模式进行比较。 一. Fanout Exchange 所有发送到Fanout Exchange的消息都会被转发到与该Exchange 绑定(Binding)的所有Queue上。 Fanout Exchange 不需要处理RouteKey 。只需要简单的将队列绑定到exchange 上。这样发送到exchange的消息都会被转发到与该交换机绑定的所有队列上。类似子网广播,每台子网内的主机都获得了一份复制的消息。 所以,Fanout Exchange 转发消息是最快的。 /// <summary> /// 生产者 /// </summary> /// <param name="change"></param> private static void ProducerMessage(MyMessage msg) { var advancedBus = CreateAdvancedBus(); if (advancedBus.IsConnected) { var exchange = advancedBus.ExchangeDeclare("user",ExchangeType.Fanout); advancedBus.Publish(exchange,"",false,new Message<MyMessage>(msg)); } else { Console.WriteLine("Can't connect"); } } /// <summary> /// 消费者 /// </summary> private static void ConsumeMessage() { var advancedBus = CreateAdvancedBus(); var exchange = advancedBus.ExchangeDeclare("user",ExchangeType.Fanout); var queue = advancedBus.QueueDeclare("user.notice.wangwu"); advancedBus.Bind(exchange,queue,"user.notice.wangwu"); advancedBus.Consume(queue,registration => { registration.Add<MyMessage>((message,info) => { Console.WriteLine("Body: {0}",message.Body); }); }); } 适用场景: 第一:大型玩家在玩在线游戏的时候,可以用它来广播重大消息。这让我想到电影微微一笑很倾城中,有款游戏需要在世界上公布玩家重大消息,也许这个就是用的MQ实现的。这让我不禁佩服肖奈,人家在大学的时候就知道RabbitMQ的这种特性了。 第二:体育新闻实时更新到手机客户端。 第三:群聊功能,广播消息给当前群聊中的所有人。 二. Direct Exchange 所有发送到Direct Exchange的消息被转发到RouteKey中指定的Queue。 Direct模式,可以使用rabbitMQ自带的Exchange:default Exchange 。所以不需要将Exchange进行任何绑定(binding)操作 。消息传递时,RouteKey必须完全匹配,才会被队列接收,否则该消息会被抛弃。 /// <summary> /// 生产者 /// </summary> /// <param name="change"></param> private static void ProducerMessage(MyMessage msg) { var advancedBus = CreateAdvancedBus(); if (advancedBus.IsConnected) { var queue = advancedBus.QueueDeclare("user.notice.zhangsan"); advancedBus.Publish(Exchange.GetDefault(),queue.Name,new Message<MyMessage>(msg)); } else { Console.WriteLine("Can't connect"); } } /// <summary> /// 消费者 /// </summary> private static void ConsumeMessage() { var advancedBus = CreateAdvancedBus(); var exchange = advancedBus.ExchangeDeclare("user",ExchangeType.Direct); var queue = advancedBus.QueueDeclare("user.notice.lisi"); advancedBus.Bind(exchange,"user.notice.lisi"); advancedBus.Consume(queue,info) => { Console.WriteLine("Body: {0}",message.Body); }); }); } 三. Topic Exchange 所有发送到Topic Exchange的消息被转发到所有关心RouteKey中指定Topic的Queue上, Exchange 将RouteKey 和某Topic 进行模糊匹配。此时队列需要绑定一个Topic。可以使用通配符进行模糊匹配,符号“#”匹配一个或多个词,符号“*”匹配不多不少一个词。因此“log.#”能够匹配到“log.info.oa”,但是“log.*” 只会匹配到“log.error”。 所以,Topic Exchange 使用非常灵活。 /// <summary> /// 生产者 /// </summary> /// <param name="change"></param> private static void ProducerMessage(MyMessage msg) { //// 创建消息bus IBus bus = CreateBus(); try { bus.Publish(msg,x => x.WithTopic(msg.MessageRouter)); } catch (EasyNetQException ex) { //处理连接消息服务器异常 } bus.Dispose();//与数据库connection类似,使用后记得销毁bus对象 } /// <summary> /// 消费者 /// </summary> private static void ConsumeMessage(MyMessage msg) { //// 创建消息bus IBus bus = CreateBus(); try { bus.Subscribe<MyMessage>(msg.MessageRouter,message => Console.WriteLine(msg.MessageBody),x => x.WithTopic("user.notice.#")); } catch (EasyNetQException ex) { //处理连接消息服务器异常 } } 使用场景: 新闻的分类更新 同意任务多个工作者协调完成 同一问题需要特定人员知晓 Topic Exchange的使用场景很多,我们公司就在使用这种模式,将足球事件信息发布,需要使用这些事件消息的人只需要绑定对应的Exchange就可以获取最新消息。 以上这篇基于RabbitMQ几种Exchange 模式详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持编程小技巧。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |