RabbitMQ消息队列(五):Routing 消息路由 2[原]
上一篇文章使用的是Direct的Exchange,但是没有指定Queue的名字,这样只能是先运行Consumer之后,Producer在运行发消息Consumer才能收到,否则先运行Producer发送消息,在运行Consumer是收不到之前Producer发送的消息,因为Queue的名字像是这样的:amq.gen-X-XSTaseUmil42zrawBVsw都是临时,如果Consumer关闭之后,这个Queue就会自动被RabbitMQ删掉。
如果想创建可以先执行Producer的Direct的Exchnage呢?因为在实际工作中我们可能需要发送端有消息就会一直发给接收端,不管接收端是否已经运行。如果我们需要指定名称的Queue,并且使用Direct的Exchange方式,我们需要使用Binding的方式。上一篇和第一篇文章中都解释了绑定的含义:绑定其实就是关联了exchange和queue。
多个routing key指定同一个queue,不管如何指定routing key的名字,发送端发送一次信息,接收端按启动顺序循环执行接收,每次接收一个消息。例子:
Producer.cs
/// <summary>
/// 多个routing key指定同一个queue
/// 指定Queue的名称,好处就是可以持久化Queue
/// </summary>
/// <param name="args">
/// SendDemo51.exe direct_custom_routing_key_hello1
/// SendDemo51.exe direct_custom_routing_key_hello2
/// 不管如何指定routing key的名字,发送端发送一次信息,接收端按启动顺序循环执行每次接收一个消息。
/// </param>
static void Main(string[] args)
{
if (args.Length < )
{
Console.Error.WriteLine("请指定一个新的Routing Key名称", Environment.GetCommandLineArgs()[]);
Environment.ExitCode = ;
return;
}
var factory = new ConnectionFactory() { HostName = "localhost" };
using (var connection = factory.CreateConnection())
{
using (var channel = connection.CreateModel())
{
const string EXCHANGE_NAME = "direct_logs";
channel.ExchangeDeclare(EXCHANGE_NAME, "direct");//Direct :如果 routing key 匹配, 那么Message就会被传递到相应的queue中。 const string QUEUE_NAME = "direct_same_queue_name_hello";//使用我们自己指定Queue的名称
bool durable = true;
channel.QueueDeclare(QUEUE_NAME, durable, false, false, null); var routingKey = args[];//指定Routing Key的名称
channel.QueueBind(QUEUE_NAME, EXCHANGE_NAME, routingKey);//通过绑定将指定的Queue名称、不同的RoutingKey名称使用Direct的Exchange方式进行关联 var message = "Hello World! " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); var body = Encoding.UTF8.GetBytes(message); var properties = channel.CreateBasicProperties();
properties.SetPersistent(true);//需要持久化Message,即在Publish的时候指定一个properties channel.BasicPublish(EXCHANGE_NAME, routingKey, properties, body);
Console.WriteLine(" [x] Sent '{0}':'{1}'", routingKey, message); Console.Read();
}
}
}
Producer.cs
Consumer.cs
/// <summary>
/// 多个routing key指定同一个queue
/// 指定Queue的名称,好处就是可以持久化Queue
/// ReceiveDemo51.exe direct_custom_routing_key_hello1
/// ReceiveDemo51.exe direct_custom_routing_key_hello2
/// 不管如何指定routing key的名字,发送端发送一次信息,接收端按启动顺序循环执行每次接收一个消息。
/// </summary>
class Program
{
static void Main(string[] args)
{
if (args.Length < )
{
Console.Error.WriteLine("请指定一个新的Routing Key名称", Environment.GetCommandLineArgs()[]);
Environment.ExitCode = ;
return;
}
var factory = new ConnectionFactory() { HostName = "localhost" };
using (var connection = factory.CreateConnection())
{
using (var channel = connection.CreateModel())
{
const string EXCHANGE_NAME = "direct_logs";
channel.ExchangeDeclare(EXCHANGE_NAME, "direct"); const string QUEUE_NAME = "direct_same_queue_name_hello";//使用我们自己指定Queue的名称
bool durable = true;
channel.QueueDeclare(QUEUE_NAME, durable, false, false, null); string routingKey = args[];//指定Routing Key的名称
channel.QueueBind(QUEUE_NAME, EXCHANGE_NAME, routingKey);//通过绑定将指定的Queue名称、不同的RoutingKey名称使用Direct的Exchange方式进行关联 Console.WriteLine(" [*] Waiting for messages. " + "To exit press CTRL+C"); var consumer = new QueueingBasicConsumer(channel);
channel.BasicConsume(QUEUE_NAME, true, consumer); while (true)
{
var ea = (BasicDeliverEventArgs)consumer.Queue.Dequeue(); var body = ea.Body;
var message = Encoding.UTF8.GetString(body);
var routingkey = ea.RoutingKey;
Console.WriteLine(" [x] Received '{0}':'{1}'", routingkey, message);
}
}
}
}
}
Consumer.cs
多个Queue关联同一个routing key,多个queue通过routing key可以同时得到发送的内容,例子如下:
Producer.cs
/// <summary>
/// 多个Queue关联一个routing key,通过routingkey可以拿到多个queue里面的内容;
/// 如果得到消息的Queue不是指定名称的Queue(此时这个例子是通过routing key得到消息),那么它是不会自动从Queue中删除接收到的消息,
/// 只有是指定名称的Queue收到消息之后才会把Queue中的消息删除。
/// SendDemo52.exe direct_custom_queue_name_hello1
/// SendDemo52.exe direct_custom_queue_name_hello2
/// 发送端发送一次信息,多个接收端同时接收到消息
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
if (args.Length < )
{
Console.Error.WriteLine("请指定一个新的Queue名称", Environment.GetCommandLineArgs()[]);
Environment.ExitCode = ;
return;
}
var factory = new ConnectionFactory() { HostName = "localhost" };
using (var connection = factory.CreateConnection())
{
using (var channel = connection.CreateModel())
{
const string EXCHANGE_NAME = "direct_logs";
channel.ExchangeDeclare(EXCHANGE_NAME, "direct");//Direct :如果 routing key 匹配, 那么Message就会被传递到相应的queue中。 string queueName = args[];//得到我们自己指定Queue的名称
channel.QueueDeclare(queueName, true, false, false, null); const string ROUTING_KEY = "direct_same_routing_key";
channel.QueueBind(queueName, EXCHANGE_NAME, ROUTING_KEY);//通过绑定将不同的Queue名称、相同的Routing Key名称采用Direct的Exchange方式进行关联 var message = "Hello World! " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); var body = Encoding.UTF8.GetBytes(message); var properties = channel.CreateBasicProperties();
properties.SetPersistent(true);//需要持久化Message,即在Publish的时候指定一个properties channel.BasicPublish(EXCHANGE_NAME, ROUTING_KEY, properties, body);
Console.WriteLine(" [x] Sent '{0}':'{1}'", ROUTING_KEY, message); Console.Read();
}
}
}
Producer.cs
Consumer.cs
/// <summary>
/// 多个Queue关联一个routing key,通过routingkey可以拿到多个queue里面的内容;
/// 如果得到消息的Queue不是指定名称的Queue(此时这个例子是通过routing key得到消息),那么它是不会自动从Queue中删除接收到的消息,
/// 只有是指定名称的Queue收到消息之后才会把Queue中的消息删除。
/// ReceiveDemo52.exe direct_custom_queue_name_hello1
/// ReceiveDemo52.exe direct_custom_queue_name_hello2
/// 发送端发送一次信息,多个接收端同时接收到消息
/// </summary>
class Program
{
static void Main(string[] args)
{
if (args.Length < )
{
Console.Error.WriteLine("请指定一个新的Queue名称", Environment.GetCommandLineArgs()[]);
Environment.ExitCode = ;
return;
}
var factory = new ConnectionFactory() { HostName = "localhost" };
using (var connection = factory.CreateConnection())
{
using (var channel = connection.CreateModel())
{
const string EXCHANGE_NAME = "direct_logs";
channel.ExchangeDeclare(EXCHANGE_NAME, "direct"); string queueName = args[];//得到我们自己指定Queue的名称
channel.QueueDeclare(queueName, true, false, false, null); const string ROUTING_KEY = "direct_same_routing_key";
channel.QueueBind(queueName, EXCHANGE_NAME, ROUTING_KEY);//通过绑定将不同的Queue名称、相同的Routing Key名称采用Direct的Exchange方式进行关联 Console.WriteLine(" [*] Waiting for messages. " + "To exit press CTRL+C"); var consumer = new QueueingBasicConsumer(channel);
channel.BasicConsume(queueName, true, consumer); while (true)
{
var ea = (BasicDeliverEventArgs)consumer.Queue.Dequeue(); var body = ea.Body;
var message = Encoding.UTF8.GetString(body);
string routingKeyRe = ea.RoutingKey;
Console.WriteLine(" [x] Received '{0}':'{1}'", routingKeyRe, message);
}
}
}
}
}
Consumer.cs
特别注意:
本例子是支持多个Queue名称同时发送和接收的,Consumer通过routing key可以拿到属于这个routing key里面的多个queue的内容;
如果Consumer一旦接收到消息,分两种情况:
1、接收的Consumer不是指定名称的Queue(此时这个Consumer是通过routing key得到Producer发送的消息),那么这个Consumer是不会自动从Queue中删除接收到的消息;
2、接收的Consumer是指定名称的Queue,那么这个Consumer是会自动从Queue中删除接收到的消息。
总结:只有当指定名称的Queue收到消息之后才会把Queue中的这条消息删除。
RabbitMQ消息队列(五):Routing 消息路由 2[原]的更多相关文章
- 消息队列之事务消息,RocketMQ 和 Kafka 是如何做的?
每个时代,都不会亏待会学习的人. 大家好,我是 yes. 今天我们来谈一谈消息队列的事务消息,一说起事务相信大家都不陌生,脑海里蹦出来的就是 ACID. 通常我们理解的事务就是为了一些更新操作要么都成 ...
- 几种MQ消息队列对比与消息队列之间的通信问题
消息队列 开发语言 协议支持 设计模式 持久化支持 事务支持 负载均衡支持 功能特点 缺点 RabbitMQ Erlang AMQP,XMPP,SMTP,STOMP 代理(Broker)模式(消息在发 ...
- 译:4.RabbitMQ Java Client 之 Routing(路由)
在上篇博文 译:3.RabbitMQ 之Publish/Subscribe(发布和订阅) 我们构建了一个简单的日志系统 我们能够向许多接收者广播日志消息. 在本篇博文中,我们将为其添加一个功能 - ...
- 分布式消息队列RocketMQ--事务消息--解决分布式事务
说到分布式事务,就会谈到那个经典的”账号转账”问题:2个账号,分布处于2个不同的DB,或者说2个不同的子系统里面,A要扣钱,B要加钱,如何保证原子性? 一般的思路都是通过消息中间件来实现“最终一致性” ...
- Java使用Rabbitmq惊喜队列queue和消息内容的本地持久化核心方法。(内容存储在硬盘)
_Channel.queueDeclare(queue, true, false, false, null); _Channel.basicPublish(_ExchangeName, queue,M ...
- 分布式消息队列RocketMQ&Kafka -- 消息的“顺序消费”
在说到消息中间件的时候,我们通常都会谈到一个特性:消息的顺序消费问题.这个问题看起来很简单:Producer发送消息1, 2, 3... Consumer按1, 2, 3...顺序消费. 但实际情况却 ...
- C#消息队列(RabbitMQ)零基础从入门到实战演练
一.课程介绍 如果您从工作中之听过但未有接触过消息对队列(MQ),如果你接触过一点关于MQ的知识,如果没有这么的多如果的话......,那么阿笨将通过本次<C#消息队列零基础从入门到实战演练&g ...
- RabbitMQ消息队列应用
RabbitMQ消息队列应用 消息通信组件Net分布式系统的核心中间件之一,应用与系统高并发,各个组件之间解耦的依赖的场景.本框架采用消息队列中间件主要应用于两方面:一是解决部分高并发的业务处理:二是 ...
- RabbitMQ 消息队列 二
一:查看MQ的用户角色 rabbitmqctl list_users 二:添加新的角色,并授予权限 rabbitmqctl add_user xiaoyao 123456 rabbitmqctl se ...
- RabbitMQ,Apache的ActiveMQ,阿里RocketMQ,Kafka,ZeroMQ,MetaMQ,Redis也可实现消息队列,RabbitMQ的应用场景以及基本原理介绍,RabbitMQ基础知识详解,RabbitMQ布曙
消息队列及常见消息队列介绍 2017-10-10 09:35操作系统/客户端/人脸识别 一.消息队列(MQ)概述 消息队列(Message Queue),是分布式系统中重要的组件,其通用的使用场景可以 ...
随机推荐
- C 语言:返回两个数组中第一个相同元素的指针(我用了loop 、goto loop标签)
// // main.c // Pointer_search // // Created by ma c on 15/8/2. // 要求:通过指针查找,实现比较两个有序数组中的元素,输出两个 ...
- socket函数send和recv函数
转自:http://www.cppblog.com/aaxron/archive/2012/04/27/172891.html 在发送端,一次发送4092个字节,在接收端,一次接收4092个字节,但是 ...
- 【转载】关于大数据库的一些不错的GitHub项目
优秀大数据GitHub项目一览 http://blog.csdn.net/YaoXTao/article/details/50540485
- 附 5 springboot之配置文件
本文转载自http://www.jianshu.com/p/80621291373b,作者:龙白一梦 我的boss 代码从开发到测试要经过各种环境,开发环境,测试环境,demo环境,线上环境,各种环境 ...
- Android中XML解析-SAX解析
昨天由于时间比较匆忙只写了Android中的XML解析的Dom方式,这种方式比较方便,很容易理解,最大的不足就是内容多的时候,会消耗内存.SAX(Simple API for XML)是一个解析速度快 ...
- python3 操作sqlSever
相关代码如下: #coding =utf-8 import os import pyodbc import time class SqlDb: def __init__(self, server='D ...
- Windows下创建文件的权限问题
在Windows下如果在某个目录下建立一个文件,那么新建立的文件会默认继承该目录的所有权限(父子关系) 如果将一个文件从一个目录移动到到另一个目录下,那么该文件的权限并不会继承自新目录的权限而是还保留 ...
- 我对REST的理解
1:rest的由来 REST即表述性状态传递(英文:Representational State Transfer,简称REST) 通俗点说:资源在网络中以某种表现形式进行状态转移. 源于REST之父 ...
- [Backbone] Working with forms
Our first step is to add a template to the AppointmentForm below. Have the template produce a form w ...
- [Javascipt] Immediately-Invoker 2
Now the people at Poplar Puzzles would like you to treat an array of functions like a Queue, passing ...