`

.Net下RabbitMQ的使用(5) -- 路由机制

 
阅读更多

理清路由机制是了解RabbitMQ来龙去脉的关键。在前面的例子中我们常常遇见这三个概念:exchange,routingKey 和 queue。真正地消息传输流程是消息先到exchange,然后exchange根据对应的routingKey放入queue,如果routingKey不匹配则丢弃。网上网友的一张图很好的展示了这个流程:

 

 

0.9 版本的AMQP协议的exchange有如下4中类型:fanout,direct,topic 和 headers。RabbitMQ服务会在启动以后预先建立4个exchange,分别对应于4中类型:

 

image

 

默认的exchange

如果用空字符串去申明一个exchange,那么系统就会使用"amq.direct"这个exchange。我们在创建一个queue的时候,默认的都会有一个和新建queue同名的routingKey绑定到这个默认的exchange上去。就像我们在发送和接收例子中,发送者的发送代码:

channel.BasicPublish("", "TaskQueue", properties, bytes);

因为在第一个参数选择了默认的exchange,而我们申明的队列叫TaskQueue,所以默认的,它在新建一个也叫TaskQueue的routingKey,并绑定在默认的exchange上,导致了我们可以在第二个参数routingKey中写TaskQueue,这样它就会找到定义的同名的queue,并把消息放进去。

 

Direct Exchange

direct exchange 发送消息是要看routingKey的。举个例子,定义了一个direct exchange 名字是X1,然后一个queue名字为Q1 用routingKey=K1 绑定到exchange X1上,当一个routeKey为 K2 的消息到达X1上,那么只有K1=K2的时候,这个消息才能到达Q1上。代码例子如下:

 

channel.ExchangeDeclare("X1", "direct");
channel.QueueDeclare("Q1", true, false, false, null);
channel.QueueBind("Q1", "X1", "K1");
channel.BasicPublish("X1", "K1", null, bytes);

 

这样Q1才能收到消息。

如果有两个接收程序都是用了同一个的queue和相同的routingKey去绑定direct exchange的话,分发的行为是负载均衡的,也就是说第一个是程序1收到,第二个是程序2收到,以此类推。

如果有两个接收程序用了各自的queue,但使用相同的routingKey去绑定direct exchange的话,分发的行为是复制的,也就是说每个程序都会收到这个消息的副本。行为相当于fanout类型的exchange。

官方图片展示direct exchange:

image

 

Fanout Exchange

fanout类型的exchange就比较好理解。就是简单的广播,而且是忽略routingKey的。所以只要是有queue绑定到fanout exchange上,通过这个exchange发送的消息都会被发送到那些绑定的queue中,不管你有没有输入routingKey。

您可以需要广播消息或分布式系统的消息同步等场景中广泛使用到它。

官方图片展示:

image

 

 

Topic Exchange

Topic类型的exchange给与我们更大的灵活性。通过定义routingKey可以有选择的订阅某些消息,此时routingKey就会是一个表达式。exchange会通过匹配绑定的routingKey来决定是否要把消息放入对应的队列中。有两种表达式符号可以让我们选择:#和*。

*(星号):代表任意的一个词。 例:*.a会匹配a.a,b.a,c.a等

#(井号):代码任意的0个或多个词。 例:#.a会匹配a.a,aa.a,aaa.a等

topic exchange 有时候的行为会像其他类型的exchange,比如说:

当routingKey只是有#号的时候,它的行为和fanout的行为是一样的。

当routingKey什么的没有,空字符串的时候,它的行为是和direct是一样的。

 

要注意的是,符号代表的是词不是字符。RabbitMQ中在表达式中词的定义是以.(点号)分隔的。

 

对于一个queue绑定到exchange,是可以多次绑定的:

channel.QueueBind(queue_name, "X1", "lazy.#");
channel.QueueBind(queue_name, "X1", "*.*.rabbit");
 

如上面的代码,表示这个queue即可以收lazy.开头的,又可以收.rabbit结尾的。

大家可以通过一些测试来理解这里面的规则,但是在测试的时候需要注意,每次修改表达式后,需要重置一下RabbitMQ。因为是可以多次绑定的,所以之前你改的所有的表达式都会记录下来,都会被尝试匹配。

重置的命令(RabbitMQ以控制台的形式运行):

image

 

Headers Exchange

Headers类型的exchange使用的比较少,它也是忽略routingKey的一种路由方式。是使用Headers来匹配的。Headers是一个键值对,可以定义成Hashtable。发送者在发送的时候定义一些键值对,接收者也可以再绑定时候传入一些键值对,两者匹配的话,则对应的队列就可以收到消息。匹配有两种方式all和any。这两种方式是在接收端必须要用键值"x-mactch"来定义。all代表定义的多个键值对都要满足,而any则代码只要满足一个就可以了。之前的几种exchange的routingKey都需要要字符串形式的,而headers exchange则没有这个要求,因为键值对的值可以是任何类型。代码示例如下:

发送端:

channel.ExchangeDeclare("X1", "headers");
 
IBasicProperties properties = channel.CreateBasicProperties();
properties.Headers = new Hashtable();
properties.Headers.Add("Key1", 123);
properties.Headers.Add("Key2", 345);
 
XmlSerializer xs = new XmlSerializer(typeof(RequestMessage));
MemoryStream ms = new MemoryStream();
xs.Serialize(ms, message);
byte[] bytes = ms.ToArray();
 
channel.BasicPublish("X1", "", properties, bytes);

接收端:

channel.ExchangeDeclare("X1", "headers");
//随机创建一个队列
string queue_name = channel.QueueDeclare("headerssubscriber2", true, false, false, null);
//绑定
IDictionary ht = new Hashtable();
ht.Add("x-match", "any");
ht.Add("Key1", 12345);
ht.Add("Key2", 34567);
channel.QueueBind(queue_name, "X1", "", ht);
//定义这个队列的消费者
QueueingBasicConsumer consumer = new QueueingBasicConsumer(channel);
channel.BasicConsume(queue_name, true, consumer);
 
while (true)
{
    BasicDeliverEventArgs ea =
        (BasicDeliverEventArgs)consumer.Queue.Dequeue();
 
    byte[] bytes = ea.Body;
 
    XmlSerializer xs = new XmlSerializer(typeof(RequestMessage));
    using (MemoryStream ms = new MemoryStream(bytes))
    {
        RequestMessage message = (RequestMessage)xs.Deserialize(ms);
        Console.WriteLine("Receive a Message, Id:" + message.MessageId + " Message:" + message.Message);
    }
}

 

 

分享到:
评论

相关推荐

    rabbitmq-server-3.8.0.exe + otp_win64_22.0.exe.zip

    5. 多种客户端库:支持多种编程语言,如Java、Python、Ruby、.NET等,方便不同平台的应用集成。 OTP则是Erlang的基石,它的主要特性包括: 1. 分布式计算:OTP提供了进程间通信(IPC)和分布式进程模型,使得构建...

    rabbitmq-dotnet-client-3.6.4-dotnet-4.6.1.rar

    5. **发送消息**:使用`channel.BasicPublish()`方法将消息发布到指定的交换机,消息会被路由到绑定的队列。 6. **接收消息**:使用`channel.BasicConsume()`方法启动一个后台线程来消费队列中的消息,`...

    rabbitmq-server-3.7.14.zip

    在本文中,我们将深入探讨 RabbitMQ 的核心概念、功能、安装与配置,以及如何在实际项目中使用它。 ### 1. 核心概念 - **消息**:消息是通过 RabbitMQ 进行传输的数据单元,可以是任何格式,通常以 JSON 或 XML ...

    rabbitmq-server-windows-3.7.10.zip

    Erlang是一种并发并行计算的语言,特别适合构建分布式系统,其内置的故障恢复机制和热代码升级功能使得RabbitMQ能够实现高可用性。因此,在安装和运行RabbitMQ之前,确保系统已经装有Erlang环境是非常重要的。 解压...

    rabbitmq-server-3.8.9.zip

    4. 配置环境变量,以便在命令行中直接使用RabbitMQ命令。 5. 访问默认的HTTP管理端点(http://localhost:15672),用默认的guest/guest用户登录(仅限本地连接,生产环境需更改)。 为了更好地利用RabbitMQ,开发者...

    .Net使用RabbitMQ即时发消息Demo

    以上就是.NET环境下使用RabbitMQ发送即时消息的详细解释和关键知识点。开发者可以通过这个基础,进一步学习RabbitMQ的高级特性,如工作队列、发布/订阅模式、死信队列等,以适应更复杂的应用场景。

    rabbitmq-server-windows-3.8.19.zip

    最后,RabbitMQ提供了丰富的客户端库,支持多种编程语言,如Java、Python、Ruby、.NET等,方便开发者在不同平台上使用RabbitMQ进行异步通信。 总之,RabbitMQ是一个强大且灵活的消息中间件,适用于构建可扩展、可靠...

    rabbitmq-dotnet-client-3.6.14-dotnet-4.5

    1. LICENSE:这通常包含该软件的许可协议,允许用户在特定条件下使用、修改和分发该软件。在 RabbitMQ 的上下文中,这可能指的是该客户端库的开源许可信息。 2. LICENSE-APACHE2:Apache License Version 2.0 是一个...

    rabbitmq-service3.7.14.rar

    总的来说,RabbitMQ 3.7.14是一个强大的消息中间件,它提供的可靠消息传递机制使得分布式系统之间的通信变得更加简单和高效。无论是初学者还是经验丰富的开发者,都应该掌握其基本使用和配置,以便在实际项目中发挥...

    rabbitmq的.net驱动

    在RabbitMQ的.NET驱动中,bin目录下可能包含已编译的客户端库,供开发者在项目中引用和使用。 通过RabbitMQ的.NET驱动,开发者可以实现以下关键知识点: - **连接管理**:建立和维护到RabbitMQ服务器的安全连接。 -...

    rabbitmq-server-3.8.3.zip

    5. **多语言支持**:RabbitMQ提供了多种编程语言的客户端库,如Java、Python、Ruby、.NET等,方便不同平台的应用集成。 **三、安装与配置** - **下载与安装**:`rabbitmq-server-3.8.3.exe` 是RabbitMQ服务器的...

    rabbitmq-server-2.8.5.tar.gz

    1. **消息队列**:RabbitMQ的核心机制,用于存储和转发消息。消息发送到队列后,消费者可以从队列中取出并处理。 2. **交换器(Exchange)**:负责将生产者发送的消息路由到适当的队列,根据预设的绑定规则进行操作...

    windows版的rabbitmq-server-3.8.27 配合Erlang otp 23.3以上版本使用

    在Windows环境下,使用RabbitMQ时,需要搭配Erlang OTP(Open Telephony Platform)环境,因为RabbitMQ是用Erlang编程语言开发的,OTP提供了运行Erlang应用程序所需的运行时系统。 本案例中,我们关注的是`rabbitmq...

    .Net Core Net6.0 RabbitMQ

    在设计系统时,考虑使用死信队列处理错误消息,或者通过交换机和路由键实现消息路由,可以帮助构建更加健壮和灵活的消息传递架构。同时,监控 RabbitMQ 的运行状态和性能指标也是运维过程中不可或缺的一部分。 总之...

    rabbitmq.net各种实例

    3. **应答(RPC,Remote Procedure Call)模式**:在.NET中,RabbitMQ可以通过回调函数实现客户端的应答机制。生产者发送一个带有唯一ID的消息,消费者接收到消息后处理并返回结果,生产者通过监听特定的响应队列来...

    ASP.NET RabbitMQ Demo

    ASP.NET RabbitMQ Demo是一个示例项目,展示了如何在ASP.NET应用程序中集成并使用RabbitMQ。RabbitMQ是一个流行的开源消息代理,它基于AMQP(Advanced Message Queuing Protocol)协议,用于实现应用间的异步通信和...

    NET Core 使用RabbitMQ源码.rar

    .NET Core使用RabbitMQ是一个广泛应用于微服务架构中的消息队列技术,用于实现应用程序之间的异步通信和解耦。RabbitMQ是一个开源的消息代理,它遵循Advanced Message Queuing Protocol(AMQP)标准,允许不同语言的...

    Windows c++中RabbitMQ-c特殊消息队列的保姆教程(csdn)————程序.pdf

    在Windows环境下,使用C++与RabbitMQ进行通信,我们需要首先了解RabbitMQ的基本概念,它是一个开源的消息代理和队列服务器,常用于处理异步任务和分布式系统中的消息传递。RabbitMQ-c是一个C语言编写的轻量级...

    rabbitmq测试程序(.net core)

    本文将重点讨论如何在.NET Core环境下使用RabbitMQ进行开发,参考了CSDN博主yysyangyangyangshan的文章。 首先,我们需要理解.NET Core与RabbitMQ结合的基本概念。.NET Core是一个跨平台的开源开发框架,它允许我们...

    C# RabbitMQ Helper 帮助类

    总之,C# RabbitMQ Helper是一个实用的工具,它降低了.NET开发者使用RabbitMQ的门槛,使你可以专注于业务逻辑,而不是底层通信细节。通过合理利用这个类库,你可以构建出高效、稳定的分布式系统。

Global site tag (gtag.js) - Google Analytics