RabbitMQ基础学习笔记(C#代码示例)
一、定义:
MQ是MessageQueue,消息队列的简称(是流行的开源消息队列系统,利用erlang语言开发)。MQ是一种应用程序对应用程序的通信方法。应用程序通过读写入队和出队的消息来通信,无需专用连接来链接它们。
消息传递是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,一般应用于远程过程调用的技术。
排队指的是应用程序通过队列来通信。应用队列避免接收和发送数据的同时进行。
二、特点:
MQ是消费者-生产者模型的代表。一端往消息队列中写入消息,另一端可以读取或者订阅队列中的消息。MQ遵循的是AMQP协议(高级消息队列协议:使得遵从该规范的客户端应用和消息中间件服务器的全功能互操作成为可能)的具体实现和产品。
三、应用:
在使用MQ时,我们不需要实时的返回信息。获取信息和返回信息进行异步处理。例如:在项目中,我们需要从汽车系统中利用CAN总线实时的获取汽车的相关信息,但是没有必要给汽车返回信息。如,获取汽车的轮胎气压,但是我们不需要给汽车一个返回的信息或结果。
C#项目要利用RabbitMQ来获取实时数据的话,需要先安装客户端的库文件:RabbitMQ.Client.dll,下载地址如下:
http://download.csdn.net/detail/qq_30507287/9599941
四、RabbitMQ的结构图:
五、基本概念:
Broker:消息队列服务器实体。
Exchange:消息交换机,指定消息按照什么规则,路由到哪个队列。可以理解成具有路由表的程序。每个消息都有一个成为路由键(routing key)的属性。交换机中有一系列的绑定(binding)即路由规则。
Queue:消息队列载体,每个消息都会被投入到一个或多个队列。消息一直在里面,直到有客户端(消费者)连接到这个队列并且将其取走为止。队列是有消费者通过程序建立的。
Binding:绑定,作用:把exchange和queue按照路由规则绑定起来。
Routing Key:路由关键字,exchange根据这个关键字进行消息投递。
Vhost(virtualhost):虚拟主机,一个broker里可以开设多个vhost,用作不同用户的权限分离。
producer:消息生产者,就是投递消息的程序。
consumer:消息消费者,就是接受消息的程序。
channel:消息通道,在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务。
注1:比较重要的四个:vhost,exchange,queue,binding。一个虚拟主机持有一组交换机、队列和绑定。
注2:消费者程序要负责创建交换机们(不止一个)?因为每个交换机在自己独立的进程当中执行,增加多个交换机就是增加多个进程,可以充分利用服务器上的CPU的核来提高效率。(一个8核服务上,可以用5核来创建5个交换机,剩余的3个用来处理消息。)
注3:一个绑定(binding)就是一个基于路由键将交换机和队列连接起来的路由规则。
六、消息队列的使用过程大概如下:
(1)客户端连接到消息队列服务器,打开一个channel。
(2)客户端声明一个exchange,并设置相关属性。
(3)客户端声明一个queue,并设置相关属性。
(4)客户端使用routingkey,在exchange和queue之间建立好绑定关系。
(5)客户端投递消息到exchange。
说明:exchange接收到消息后,就根据消息的key和已经设置的binding,进行消息路由,将消息投递到一个或多个队列里。
七、Exchange(交换机的类型)的类型:
1)Direct交换机:
(处理路由键)完全根据key进行投递。需要将一个队列绑定到交换机上,要求该消息与一个特定的路由键完全匹配。
绑定时设置了routing key为“abc”,那么客户端提交的消息,只有设置了key为“abc”的才会投递到队列。
2)Topic交换机:
(将路由键和某模式进行匹配)此时队列需要绑定到一个模式上,对key进行模式匹配后进行投递。
“#”匹配一个或多个词,“*”匹配正好一个词。“abc.#”匹配“abc.def.ghi”,“abc.*”只匹配“abc.def”。
3)Fanout交换机:(不处理路由键)不需要key值,采用广播模式,消息进来时,投递到与该交换机绑定的所有队列。
八、队列消息的持久化:
1、为什么会有持久化?
花费大量时间来创建队列,交换机和绑定,如果服务器出现意外或外界故障,那么队列,交换机和绑定就会清空。RabbitMQ重启之后就会清空原来的东西。因此在创建队列和交换机时就会指定一个标志durable来控制。当然,durable表示的含义:含有该标志的队列和交换机在重启之后会重新建立,而不是,在队列中的消息会重启后恢复。
2、消息队列持久化包括3个部分:
(1)exchange持久化,在声明时指定durable => 1;
(2)queue持久化,在声明时指定durable => 1;
(3)消息持久化,在投递时指定delivery_mode=> 2(1是非持久化,2表示persistent,持久化);
如果exchange和queue都是持久化的,那么它们之间的binding也是持久化的。如果exchange和queue两者之间有一个持久化,一个非持久化,就不允许建立绑定。
说明:delivery mode(投递模式)
3、绑定(binding)的持久化:
绑定在创建的时候无法设置durable,那么绑定的持久化是靠队列和交换机来实现的。如果绑定一个durable的队列和一个durable的交换机,RabbitMQ会自动保留这个绑定。只要队列和交换机之一不是durable,那么依赖它们的绑定就会自动删除。
九、.NET/C#客户端中的RabbitMQ
(1)主要的命名空间,接口和类
核心的API接口和类都定义在命名空间为RabbitMQ.Client中。
using RabbitMQ.Client;
核心的接口和类是:
IModel: representsan AMQP 0-9-1 channel, and provides most of the operations (protocol methods).代表通道,提供协议方法。
IConnection:represents an AMQP 0-9-1 connection
ConnectionFactory:constructs IConnection instances
IBasicConsumer:represents a message consumer表示消息的消费者。
其他的接口和类:
DefaultBasicConsumer:commonly used base class for consumers
其他公共的RabbitMQ.Client命名空间还包括:
RabbitMQ.Client.Events:various events and event handlers that are part of the client library,including EventingBasicConsumer, a consumer implementation built around C#event handlers.
RabbitMQ.Client.Exceptions:exceptions visible to the user.
(2)连接代理
连接到RabbitMQ,必须要实例化一个ConnectionFactory和configure一个RabbitMQ到主机,虚拟机或认证的设备上。下面的代码是在主机上连接RabbitMQ结点。
ConnectionFactory factory = newConnectionFactory();
factory.Uri = "amqp://user:pass@hostName:port/vhost";
IConnection conn = factory.CreateConnection();
然后用iconnection接口可以用来打开一个通道:
IModel channel = conn.CreateModel();
(3)使用交换机和队列
model.ExchangeDeclare(exchangeName,ExchangeType.Direct);
model.QueueDeclare(queueName,false,false,false,null);
model.QueueBind(queueName, exchangeName, routingKey,null);
(4)发布消息
利用交换机(exchange)发送消息,使用的是IModel.BasicPublish
byte[]messageBodyBytes = System.Text.Encoding.UTF8.GetBytes("Hello, world!");
model.BasicPublish(exchangeName, routingKey,null,messageBodyBytes);
对于细节,可以用重载变量来指定标志或特殊的消息属性:
byte[]messageBodyBytes = System.Text.Encoding.UTF8.GetBytes("Hello, world!");
IBasicProperties props = model.CreateBasicProperties();
props.ContentType = "text/plain";
props.DeliveryMode = 2;
model.BasicPublish(exchangeName,routingKey, props, messageBodyBytes);
发送自定义的消息:
byte[]messageBodyBytes = System.Text.Encoding.UTF8.GetBytes("Hello, world!");
IBasicProperties props = model.CreateBasicProperties();
props.ContentType = "text/plain";
props.DeliveryMode = 2;
props.Headers = new Dictionary<string,object>();
props.Headers.Add("latitude", 51.5252949);
props.Headers.Add("longitude",-0.0905493);
model.BasicPublish(exchangeName, routingKey, props, messageBodyBytes);
十、(C#实例解析)生产者应用程序解析
(1)从生产者应用程序来看,建立一个使用默认设置的连接,创建连接并创建一个通道:
namespaceProducer
{
classProgram
{
staticvoidMain(string[] args)
{
var connectionFactory =newConnectionFactory();
IConnection connection =connectionFactory.CreateConnection();
IModel channel = connection.CreateModel();
}
}
}
(2)声明一个交换机并发布消息
channel.ExchangeDeclare("direct-exchange-example",ExchangeType.Direct);
第二个参数表名了参数的类型,可以选择direct,fanout,topic,或者headers。
(3)调用方法,产生一个返回值,本例中调用的是DoSomethingInteresting(),并且返回一个字符串的值。
string value = DoSomethingInteresting();
(4)dosomethinginteresting()实施可以返回一个新的GUID字符串值
staticstringDoSomethingInteresting()
{
returnGuid.NewGuid().ToString();
}
(5)利用返回值来创建一个日志消息:
string logMessage =string.Format("{0}: {1}", TraceEventType.Information, value);
(6)将日志消息转换为字节数组,并将消息发布到新的交换机上:
byte[]message =Encoding.UTF8.GetBytes(logMessage);
channel.BasicPublish("direct-exchange-example","",null,message);
(7)最后,要关闭通道和连接
channel.Close();
connection.Close();
十一、(C#实例解析)消费者应用程序解析
(1)和生成者一样创建消费者
using RabbitMQ.Client; namespace Consumer
{
classProgram
{
staticvoidMain(string[] args)
{
varconnectionFactory = new ConnectionFactory();
IConnection connection = connectionFactory.CreateConnection();
IModel channel = connection.CreateModel(); channel.ExchangeDeclare("direct-exchange-example",ExchangeType.Direct);
}
}
}
(2)声明一个队列去绑定交换机,队列的名字为“logs”
channel.QueueDeclare("logs",false,false,true,null);
(3)绑定“logs”队列,利用QueueBind()
channel.QueueBind("logs","direct-exchange-example","");
(4)声明消费者对象
var consumer =newQueueingBasicConsumer(channel)
(5)推送消息
channel.BasicConsume(“logs”, true,consumer);
(6)任何消息都将被自动检索,并放置在内存队列的本地内存队列中。
var eventArgs =(BasicDeliverEventArgs)consumer.Queue.Dequeue();
将eventArgs转换成字符串并打印输出
var message =Encoding.UTF8.GetString(eventArgs.Body);
Console.WriteLine(message);
(7)关闭通道和连接
channel.Close();
connection.Close();
十二、(C#实例代码)生产-消费模式的完整代码
(1)
using System;
using System.Diagnostics;
using System.Text;
using System.Threading;
using RabbitMQ.Client; namespace Producer
{
classProgram
{
staticvoidMain(string[] args)
{
Thread.Sleep(1000);
varconnectionFactory = new ConnectionFactory();
IConnection connection = connectionFactory.CreateConnection();
IModel channel = connection.CreateModel(); channel.ExchangeDeclare("direct-exchange-example",ExchangeType.Direct);
stringvalue = DoSomethingInteresting();
stringlogMessage = string.Format("{0}:{1}",TraceEventType.Information,value); byte[]message = Encoding.UTF8.GetBytes(logMessage);
channel.BasicPublish("direct-exchange-example","",null,message); channel.Close();
connection.Close();
} staticstringDoSomethingInteresting()
{
returnGuid.NewGuid().ToString();
}
}
}
(2)
using System;
using System.Text;
using RabbitMQ.Client;
using RabbitMQ.Client.Events; namespace Consumer
{
classProgram
{
staticvoidMain(string[] args)
{
varconnectionFactory = new ConnectionFactory();
IConnection connection = connectionFactory.CreateConnection();
IModel channel = connection.CreateModel(); channel.ExchangeDeclare("direct-exchange-example",ExchangeType.Direct);
channel.QueueDeclare("logs",false,false,true,null);
channel.QueueBind("logs","direct-exchange-example",""); varconsumer = new QueueingBasicConsumer(channel);
channel.BasicConsume("logs",true,consumer); vareventArgs = (BasicDeliverEventArgs)consumer.Queue.Dequeue(); stringmessage = Encoding.UTF8.GetString(eventArgs.Body);
Console.WriteLine(message); channel.Close();
connection.Close();
Console.ReadLine();
}
}
}
转载:
http://blog.csdn.net/qq_30507287/article/details/52176603
RabbitMQ基础学习笔记(C#代码示例)的更多相关文章
- C#RabbitMQ基础学习笔记
RabbitMQ基础学习笔记(C#代码示例) 一.定义: MQ是MessageQueue,消息队列的简称(是流行的开源消息队列系统,利用erlang语言开发).MQ是一种应用程序对应用程序的通信方法. ...
- 尚学堂JAVA基础学习笔记
目录 尚学堂JAVA基础学习笔记 写在前面 第1章 JAVA入门 第2章 数据类型和运算符 第3章 控制语句 第4章 Java面向对象基础 1. 面向对象基础 2. 面向对象的内存分析 3. 构造方法 ...
- 【C#编程基础学习笔记】4---Convert类型转换
2013/7/24 技术qq交流群:JavaDream:251572072 教程下载,在线交流:创梦IT社区:www.credream.com [C#编程基础学习笔记]4---Convert类型转换 ...
- 1.C#基础学习笔记3---C#字符串(转义符和内存存储无关)
技术qq交流群:JavaDream:251572072 教程下载,在线交流:创梦IT社区:www.credream.com ------------------------------------- ...
- Java基础学习笔记(一)
Java基础学习笔记(一) Hello World 基础代码学习 代码编写基础结构 class :类,一个类即一个java代码,形成一个class文件,写于每个代码的前端(注意无大写字母) XxxYy ...
- handlebars.js基础学习笔记
最近在帮学校做个课程网站,就有人推荐用jquery+ajax+handlebars做网站前端,刚接触发现挺高大上的,于是就把一些基础学习笔记记录下来啦. 1.引用文件: jquery.js文件下载:h ...
- 基础学习笔记之opencv(6):实现将图片生成视频
基础学习笔记之opencv(6):实现将图片生成视频 在做实验的过程中.难免会读视频中的图片用来处理,相反将处理好的图片又整理输出为一个视频文件也是非经常常使用的. 以下就来讲讲基于opencv的C+ ...
- Oracle基础学习笔记
Oracle基础学习笔记 最近找到一份实习工作,有点头疼的是,有阶段性考核,这...,实际想想看,大学期间只学过数据库原理,并没有针对某一数据库管理系统而系统的学习,这正好是一个机会,于是乎用了三天时 ...
- C++基础 学习笔记之一:源代码的格式化
C++基础 学习笔记之一:源代码的格式化 1. 源代码中的标记与空白 C++中的语句是以分号表示语句的结束.在C++中空格和回车以及制表符均为相同作用,即三者通常可以互相替代. 例如可以将一个简单的m ...
随机推荐
- Corn Fields 状压动归入门题
#include<cstdio> using namespace std; const int N=15; int dp[N][1<<N],v[1<<N],M[N] ...
- npm run build 打包项目,图片等资源使用相对路径会出现路径错误的问题
在build下的utils.js中,3使用 ‘vue-style-loader’ 依赖的地方添加 publicPath: '../../' , 如图:
- [luogu 1270] “访问”美术馆 (树形dp)
传送门 Description 经过数月的精心准备,Peer Brelstet,一个出了名的盗画者,准备开始他的下一个行动.艺术馆的结构,每条走廊要么分叉为两条走廊,要么通向一个展览室.Peer知道每 ...
- 03.IO读写-1.IO介绍
1 文件操作介绍 in: 输入,读入.从硬盘中读到内存 out: 输出.从内存写到硬盘 文件的作用: 数据存储 2 文件的打开与关闭 2.1 打开文件 在Python,使用open函数,可以打开一个已 ...
- idea debug打得断点第一次可以进入,第二次不能进入
- test/exec/match
1) test 检查指定的字符串是否存在var data = “123123″;var reCat = /123/gi;alert(reCat.test(data)); //true//检查字符是 ...
- [SharePoint2010开发入门经典]9创建更好的用户体验----silverlight
本章概要: 1.了解Silverlight 2.理解为什么使用Silverlight 3.介绍如何集成SharePoint和Silverlight
- PDF转EPUB格式电子书经验总结
依据本人将PDF转换为EPUB电子书的经验,总结整理了这篇文章.因本人水平有限,难免有错误和不足之处,望大家及时批评指正. 写这篇文章时,假定读者已经会使用文中所列出软件的基本操作,比方如何用No ...
- 金蝶KIS标准版与金蝶K3的差别
一.数据库 金蝶KIS标准版使用MS Access数据库.该数据库适用于小规模的数据处理,是比較经济的数据库解决方式,但当单个表的数据记录超过5万条时.执行的速度和稳定性都将受到一定程序的影响. K ...
- java基础——transient
今天在看struts1源代码的时候,发如今ActionForm中首先声明了两个transient类型的protected变量. 之前没有接触过该transient类型,所以就查了查. transien ...