RabbitMQ学习之:(九)Headers Exchange (转贴+我的评论)
From: http://lostechies.com/derekgreer/2012/05/29/rabbitmq-for-windows-headers-exchanges/
RabbitMQ for Windows: Headers Exchanges
This is the eighth and final installment to the series: RabbitMQ for Windows. In thelast installment, we walked through creating a topic exchange example. As the last installment, we’ll walk through a headers exchange example.
Headers exchanges examine the message headers to determine which queues a message should be routed to. As discussed earlier in this series, headers exchanges are similar to topic exchanges in that they allow you to specify multiple criteria, but offer a bit more flexibility in that the headers can be constructed using a wider range of data types (1).
To subscribe to receive messages from a headers exchange, a dictionary of headers is specified as part of the binding arguments. In addition to the headers, a key of “x-match” is also included in the dictionary with a value of “all”, specifying that messages must be published with all the specified headers in order to match, or “any”, specifying that the message needs to only have one of the specified headers specified.
As our final example, we’ll create a Producer application which publishes the message “Hello, World!” using a headers exchange. Here’s our Producer code:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Threading;
using RabbitMQ.Client;
using RabbitMQ.Client.Framing.v0_9_1; namespace Producer
{
class Program
{
const string ExchangeName = "header-exchange-example"; static void Main(string[] args)
{
var connectionFactory = new ConnectionFactory();
connectionFactory.HostName = "localhost"; IConnection connection = connectionFactory.CreateConnection();
IModel channel = connection.CreateModel();
channel.ExchangeDeclare(ExchangeName, ExchangeType.Headers, false, true, null);
byte[] message = Encoding.UTF8.GetBytes("Hello, World!"); var properties = new BasicProperties();
properties.Headers = new Dictionary<string, object>();
properties.Headers.Add("key1", "12345");
TimeSpan time = TimeSpan.FromSeconds(10);
var stopwatch = new Stopwatch();
Console.WriteLine("Running for {0} seconds", time.ToString("ss"));
stopwatch.Start();
var messageCount = 0; while (stopwatch.Elapsed < time)
{
channel.BasicPublish(ExchangeName, "", properties, message);
messageCount++;
Console.Write("Time to complete: {0} seconds - Messages published: {1}\r", (time - stopwatch.Elapsed).ToString("ss"), messageCount);
Thread.Sleep(1000);
} Console.Write(new string(' ', 70) + "\r");
Console.WriteLine("Press any key to exit");
Console.ReadKey();
message = Encoding.UTF8.GetBytes("quit");
channel.BasicPublish(ExchangeName, "", properties, message);
connection.Close();
}
}
}
In the Producer, we’ve used a generic dictionary of type Dictionary<string, object> and added a single key “key1” with a value of “12345”. As with our previous example, we’re using a stopwatch as a way to publish messages continually for 10 seconds.
For our Consumer application, we can use an “x-match” argument of “all” with the single key/value pair specified by the Producer, or we can use an “x-match” argument of “any” which includes the key/value pair specified by the Producer along with other potential matches. We’ll use the latter for our example. Here’s our Consumer code:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using RabbitMQ.Client;
using RabbitMQ.Client.Events; namespace Consumer
{
class Program
{
const string QueueName = "header-exchange-example";
const string ExchangeName = "header-exchange-example"; static void Main(string[] args)
{
var connectionFactory = new ConnectionFactory();
connectionFactory.HostName = "localhost"; IConnection connection = connectionFactory.CreateConnection();
IModel channel = connection.CreateModel();
channel.ExchangeDeclare(ExchangeName, ExchangeType.Headers, false, true, null);
channel.QueueDeclare(QueueName, false, false, true, null); IDictionary specs = new Dictionary();
specs.Add("x-match", "any");
specs.Add("key1", "12345");
specs.Add("key2", "123455");
channel.QueueBind(QueueName, ExchangeName, string.Empty, specs);
// 注意,这个StartConsume是我们写的函数,其实他是在一个循环内反复调用CallBack函数。
channel.StartConsume(QueueName, MessageHandler);
connection.Close();
} public static void MessageHandler(IModel channel, DefaultBasicConsumer consumer, BasicDeliverEventArgs eventArgs)
{
string message = Encoding.UTF8.GetString(eventArgs.Body);
Console.WriteLine("Message received: " + message);
foreach (object headerKey in eventArgs.BasicProperties.Headers.Keys)
{
Console.WriteLine(headerKey + ": " + eventArgs.BasicProperties.Headers[headerKey]);
} if (message == "quit")
channel.BasicCancel(consumer.ConsumerTag);
}
}
}
Rather than handling our messages inline as we’ve done in previous examples, this example uses an extension method named StartConsume() which accepts a callback to be invoked each time a message is received. Here’s the extension method used by our example:
using System;
using System.IO;
using System.Threading;
using RabbitMQ.Client;
using RabbitMQ.Client.Events; namespace Consumer
{
public static class ChannelExtensions
{
public static void StartConsume(this IModel channel, string queueName, Action<IModel, DefaultBasicConsumer, BasicDeliverEventArgs> callback)
{
var consumer = new QueueingBasicConsumer(channel);
channel.BasicConsume(queueName, true, consumer); while (true)
{
try
{
var eventArgs = (BasicDeliverEventArgs)consumer.Queue.Dequeue();
new Thread(() => callback(channel, consumer, eventArgs)).Start();
}
catch (EndOfStreamException)
{
// The consumer was cancelled, the model closed, or the connection went away.
break;
}
}
}
}
}
Setting our solution to run both the Producer and Consumer applications upon startup, running our example produces output similar to the following:
Producer
Running for 10 seconds
Time to complete: 08 seconds - Messages published: 2
Consumer
Message received: Hello, World!
key1: 12345
Message received: Hello, World!
key1: 12345
That concludes our headers exchange example as well as the RabbitMQ for Windows series. For more information on working with RabbitMQ, see the documentation athttp://www.rabbitmq.com or the purchase the book RabbitMQ in Action by Alvaro Videla and Jason Williams. I hope you enjoyed the series.
Footnotes:
1 – See http://www.rabbitmq.com/amqp-0-9-1-errata.html#section_3 andhttp://hg.rabbitmq.com/rabbitmq-dotnet-client/diff/4def852523e2/projects/client/RabbitMQ.Client/src/client/impl/WireFormatting.csfor supported field types.
RabbitMQ学习之:(九)Headers Exchange (转贴+我的评论)的更多相关文章
- rabbitmq学习(九) —— 关于消息队列的选型
转自http://cmsblogs.com/?p=3846 在IM这种讲究高并发.高消息吞吐的互联网场景下,MQ消息中间件是个很重要的基础设施,它在IM系统的服务端架构中担当消息中转.消息削峰.消息交 ...
- (九)RabbitMQ消息队列-通过Headers模式分发消息
原文:(九)RabbitMQ消息队列-通过Headers模式分发消息 Headers类型的exchange使用的比较少,以至于官方文档貌似都没提到,它是忽略routingKey的一种路由方式.是使用H ...
- RabbitMQ学习之:(六)Direct Exchange (转贴+我的评论)
From: http://lostechies.com/derekgreer/2012/04/02/rabbitmq-for-windows-direct-exchanges/ RabbitMQ fo ...
- RabbitMQ入门教程(九):首部交换机Headers
原文:RabbitMQ入门教程(九):首部交换机Headers 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog ...
- RabbitMQ学习系列(四): 几种Exchange 模式
上一篇,讲了RabbitMQ的具体用法,可以看看这篇文章:RabbitMQ学习系列(三): C# 如何使用 RabbitMQ.今天说些理论的东西,Exchange 的几种模式. AMQP协议中的核心思 ...
- RabbitMQ headers Exchange
Headers Exchange headers也是一种交换机类型,但是在rabbitmq官网中的教程中并没有说到.资料也很少,但是找一找总会有的. headers与direct的模式不同,不是使用r ...
- RabbitMQ学习总结 第六篇:Topic类型的exchange
目录 RabbitMQ学习总结 第一篇:理论篇 RabbitMQ学习总结 第二篇:快速入门HelloWorld RabbitMQ学习总结 第三篇:工作队列Work Queue RabbitMQ学习总结 ...
- (转)RabbitMQ学习之Headers交换类型(java)
http://blog.csdn.net/zhu_tianwei/article/details/40923131 Headers类型的exchange使用的比较少,它也是忽略routingKey的一 ...
- RabbitMQ学习之:(七)Fanout Exchange (转贴+我的评论)
From:http://lostechies.com/derekgreer/2012/05/16/rabbitmq-for-windows-fanout-exchanges/ PunCha: Ther ...
随机推荐
- 使用Google Thumbnails 压缩图片
背景说明:最近项目中需要用到一些图片文件的上传 ,但是有些图片很大,比如轮播图,大有的有几兆,这样加载一个首页都要很久,显然这样对用户体验是非常不友好的,对服务器资源将是一种浪费. 为了解决这个问题, ...
- Oralce问题之ORA-12560:TNS协议适配器错误
在Windows系统中,通过CMD命令打开命令窗口,通过命令:sqlplus / as sysdba回车后提示 协议适配器错误 可能原因: (1).Oralce数据库监听服务没启动起来 通过开始-&g ...
- 蓝桥杯BASIC-13 数列排序
问题描述 给定一个长度为n的数列,将这个数列按从小到大的顺序排列.1<=n<=200 输入格式 第一行为一个整数n. 第二行包含n个整数,为待排序的数,每个整数的绝对值小于10000. 输 ...
- 编译原理实战——使用Lex/Flex进行编写一个有一定词汇量的词法分析器
编译原理实战--使用Lex/Flex进行编写一个有一定词汇量的词法分析器 by steve yu 2019.9.30 参考文档:1.https://blog.csdn.net/mist14/artic ...
- bat wmic python 获取进程的所在路径
bat wmic python 获取进程的所在路径 doc: wmic process where name="process-name" get executablepath w ...
- 使用ADB命令写Android自动化测试脚本
使用脚本来执行测试的特点: ●书写方便 ●基本上可以实现90%以上的功能性覆盖 ●测试结果需要通过自己观察整个过程和日志文件来得出的 ●有些外部的动作,脚本是无法实现的,比如录入指纹 ●只适配特定尺寸 ...
- Centos6.5 下安装配置Apache+PHP+Mysql环境
1.准备工作 # yum -y update && yum -y install vim make cmake gcc gcc-c++ bison bison-devel ncurse ...
- IDEA中配置Jetty Server
首先去 Eclipse官网下载Jetty jar包 鼠标移到Jetty上时 点击 Git it (得到它) 点击 .zip等待下载完成 然后 解压出来 接下就让我们 开始 使用IDEA了(创建一个We ...
- SpringBoot+Mybatis-Plus两种分页方法
用到的依赖: <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus ...
- 【luogu2668斗地主】模拟
题目描述: 输入格式: 输出格式: 输入样例: 1: 1 8 7 4 8 4 9 1 10 4 11 1 5 1 1 4 1 1 2: 1 17 12 3 4 3 2 3 5 4 10 2 3 3 1 ...