RabbitMQ 的行为艺术

  好像,今天已经是 2 月 28 号了。

  听说,29、30、31 号放假。

  据说,有图,有真相。

目录

  • 简介

  • 环境搭建

  • 示例一:简单的 Hello World

  • 示例二:发布/订阅模式

  • 尝试发现 - 新物种 EasyNetQ

简介

  RabbitMQ:一个消息系统,基于 AMQP 系统协议,由 Erlang 语言开发。

  优点:健壮、使用简单、开源和支持各种流行的语言(如 Python、java、.NET)等。

  MQ(Message Queue):消息队列的简称,是一种应用程序之间的通信机制。

  作用:将部分无需立即回调获取结果,并且耗时的操作,使用异步处理的方式提高服务器的吞吐量及性能。如:日志记录。

图:简单的通信方式,及加入 MQ 后的变化

 
     A 端:生产者将消息写(插)入队列;
     MQ(队列) :中间件,消息的载体;
     B 端:消费者从队列读(取)出消息。
 
  MQ 特点:消费者 - 生产者模型的一种表现形式。
 

环境搭建

  1.官网下载安装包:http://www.rabbitmq.com/ ;

  2.安装时会提示你下载 Erlang 语言环境;

  3.启动安装完的服务:RabbitMQ;

  4.在 cmd 中指向 sbin 目录,并输入以下命令,才能打开 WEB 管理界面:

rabbitmq-plugins enable rabbitmq_management

  5.默认 url:http://localhost:15672/#/

示例一:简单的 Hello World

  P(Producer):生产者,意味着发送;

  Queue:队列,本质上是一个无限的缓冲区,可以储存尽可能多的信息;

  C(Consumer):消费者,等待并接收消息。

  【备注】生产者和消费者不需要驻留在同一台服务器上。

  Producer.cs

     public class Producer  
{
public static void Send()
{
var factory = new ConnectionFactory { HostName = "localhost" }; //创建连接对象,基于 Socket
using (var connection = factory.CreateConnection())
{
//创建新的渠道、会话
using (var channel = connection.CreateModel())
{
//声明队列
channel.QueueDeclare(queue: "hello", //队列名
durable: false, //持久性
exclusive: false, //排他性
autoDelete: false, //自动删除
arguments: null); const string message = "Hello World!";
var body = Encoding.UTF8.GetBytes(message); channel.BasicPublish(exchange: "", //交换机名
routingKey: "hello", //路由键
basicProperties: null,
body: body);
}
}
}
}

  【备注】队列名如果已存在,将不会重复创建。假设队列已存在,修改 channel.QueueDeclare() 方法内的参数后启动会出现异常。

  【备注】消息内容是一个字节数组。

 
  Consumer.cs
     class Consumer
{
public static void Receive()
{
var factory = new ConnectionFactory() { HostName = "localhost" }; using (var connection = factory.CreateConnection())
{
using (var channel = connection.CreateModel())
{
channel.QueueDeclare(queue: "hello",
durable: false,
exclusive: false,
autoDelete: false,
arguments: null); //创建基于该队列的消费者,绑定事件
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
var body = ea.Body; //消息主体
var message = Encoding.UTF8.GetString(body);
Console.WriteLine(" [x] Received {0}", message);
}; //启动消费者
channel.BasicConsume(queue: "hello", //队列名
noAck: true, //false:手动应答;true:自动应答
consumer: consumer); Console.Read();
}
}
}
}

  【疑问】在消费者的类里面为什么会再次声明队列(channel.QueueDeclare())呢?-- 因为接收方可能会在发送方启动前启动,这是出于保险起见。

示例二:发布/订阅模式

 
 

  1.Exchange 交换机和 Exchange Type 交换类型  

  RabbitMQ 消息传递模型的核心思想是,生产者不会直接将消息发给队列。

  这里我们将引入新的名词 Exchange(交换机)。交换机传递消息的类型也有很多种:direct, topic, headers(不常用) 和 fanout,我们称之为交换类型。

图:Direct

图:Fanout

图:Topic

--上述 3 张图来源:http://m.blog.csdn.net/article/details?id=52262850

  

  这里,创建一个名为 “logs” 的交换机,它的类型为广播类型(fanout:可以将收到的所有消息,广播给所有已知的队列)。

channel.ExchangeDeclare(exchange: "logs",   //交换机名
type: "fanout"); //交换类型

  

  2.临时队列

  作为消费者,我们有时候只需要一些新的(或者空的)队列,此时,更好的方式就是让它自动生成一个随机名字的队列;其次,当队列连接中断时会选择自动删除对应的消费者。

  创建一个非持久,有排他性和自动删除特性的队列(无参时)。

var queueName = channel.QueueDeclare().QueueName;

  3.Binding 绑定

  【疑问】有了 Exchange 和 channel,这时,还需要什么东西呢?-- 我们要创建 Exchange 和 channel 关系的桥梁,这个桥梁称之为 Binding(绑定)。

channel.QueueBind(queue: queueName,
exchange: "logs",
routingKey: "");
 
     class Producer
{
public static void Send()
{
var factory = new ConnectionFactory()
{
HostName = "localhost",
Port = ,
UserName = "guest",
Password = "guest"
}; using (var connection = factory.CreateConnection())
{
using (var channel = connection.CreateModel())
{
channel.ExchangeDeclare(exchange: "logs", //交换机名
type: "fanout"); //交换类型 // Guid
var message = Guid.NewGuid().ToString();
var body = Encoding.UTF8.GetBytes(message);
channel.BasicPublish(exchange: "logs",
routingKey: "",
basicProperties: null,
body: body); Console.WriteLine(" [x] Sent {0}", message);
} Console.WriteLine(" Press [enter] to exit.");
Console.ReadLine();
}
}
}

Producer.cs //生产者

     class Reciver
{
public static void Recive()
{
var factory = new ConnectionFactory()
{
HostName = "localhost",
Port = ,
UserName = "guest",
Password = "guest"
}; using (var connection = factory.CreateConnection())
using (var channel = connection.CreateModel())
{
channel.ExchangeDeclare(exchange: "wen_logs", //交换机名
type: "fanout"); //交换类型 //创建队列
var queueName = channel.QueueDeclare().QueueName;
channel.QueueBind(queue: queueName,
exchange: "wen_logs",
routingKey: ""); Console.WriteLine(" [*] Waiting for logs."); var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
var body = ea.Body;
var message = Encoding.UTF8.GetString(body);
Console.WriteLine(" [x] {0}", message);
};
channel.BasicConsume(queue: queueName,
noAck: true,
consumer: consumer); Console.WriteLine(" Press [enter] to exit.");
Console.ReadLine();
}
}
}

Reciver.cs //接收者

尝试发现 - 新物种 EasyNetQ

  这都不是事!EasyNetQ,看名字就知道,搞定 MQ,So easy!

  连接 RabbitMQ 代理:

var bus = RabbitHutch.CreateBus("host=localhost");

  发布:

bus.Publish(message);

  订阅:

bus.Subscribe<MyMessage>("my_subscription_id", msg => Console.WriteLine(msg.Text));

  下面我们通过 Demo 来感受一下 Easy 的程度吧,创建项目(效果图如下,附 Demo 下载):

  Wen.EasyNetQDemo.Model:类库

  Wen.EasyNetQDemo.Publisher,Wen.EasyNetQDemo.Subscriber:控制台应用程序,都使用 Nuget 直接安装 EasyNetQ 包,都引用类库 Model。

 
  Demo.cs

    public class Demo
{
public string Message { get; set; }
}

  Publisher

 using System;
using EasyNetQ;
using Wen.EasyNetQDemo.Model; namespace Wen.EasyNetQDemo.Publisher
{
internal class Program
{
private static void Main(string[] args)
{
using (var bus = RabbitHutch.CreateBus("host=localhost"))
{
string input;
Console.WriteLine("请输入信息。 如果是“esc” 将退出当前窗口。"); while ((input = Console.ReadLine()) != "esc")
{
bus.Publish(new Demo
{
Message = input
});
} }
}
}
}

  【备注】RabbitHutch.CreateBus() 方法可以创建一个简单的发布/订阅和包含请求/响应 API 的消息总线。

  Subscriber

 using System;
using EasyNetQ;
using Wen.EasyNetQDemo.Model; namespace Wen.EasyNetQDemo.Subscriber
{
internal class Program
{
private static void Main(string[] args)
{
using (var bus = RabbitHutch.CreateBus("host=localhost"))
{
bus.Subscribe<Demo>("test", HandleDemo); Console.WriteLine("监听信息中...输入“return”将退出当前窗口!");
Console.ReadLine();
}
} private static void HandleDemo(Demo demo)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"Got message: {demo.Message}");
Console.ResetColor();
}
}
}

图:效果图

「世事洞明皆学问 人情练达即文章」

【博主】反骨仔

[.NET] RabbitMQ 的行为艺术的更多相关文章

  1. RabbitMQ 的行为艺术

    RabbitMQ 的行为艺术 目录 简介 环境搭建 示例一:简单的 Hello World 示例二:发布/订阅模式 尝试发现 - 新物种 EasyNetQ 简介 RabbitMQ:一个消息系统,基于 ...

  2. Redis 小白指南(三)- 事务、过期、消息通知、管道和优化内存空间

    Redis 小白指南(三)- 事务.过期.消息通知.管道和优化内存空间 简介 <Redis 小白指南(一)- 简介.安装.GUI 和 C# 驱动介绍> 讲的是 Redis 的介绍,以及如何 ...

  3. 【框架学习与探究之消息队列--EasyNetQ(1)】

    前言 本文欢迎转载,实属原创,本文原始链接地址:http://www.cnblogs.com/DjlNet/p/7603554.html 废话 既然都是废话了,所以大家就可以跳过了,这里是博主有事没事 ...

  4. Open Source

    资源来源于http://www.cnblogs.com/Leo_wl/category/246424.html RabbitMQ 安装与使用 摘要: RabbitMQ 安装与使用 前言 吃多了拉就是队 ...

  5. 消息队列——RabbitMQ学习笔记

    消息队列--RabbitMQ学习笔记 1. 写在前面 昨天简单学习了一个消息队列项目--RabbitMQ,今天趁热打铁,将学到的东西记录下来. 学习的资料主要是官网给出的6个基本的消息发送/接收模型, ...

  6. 读书笔记:JavaScript DOM 编程艺术(第二版)

    读完还是能学到很多的基础知识,这里记录下,方便回顾与及时查阅. 内容也有自己的一些补充. JavaScript DOM 编程艺术(第二版) 1.JavaScript简史 JavaScript由Nets ...

  7. RabbitMq应用二

    在应用一中,基本的消息队列使用已经完成了,在实际项目中,一定会出现各种各样的需求和问题,rabbitmq内置的很多强大机制和功能会帮助我们解决很多的问题,下面就一个一个的一起学习一下. 消息响应机制 ...

  8. 如何优雅的使用RabbitMQ

    RabbitMQ无疑是目前最流行的消息队列之一,对各种语言环境的支持也很丰富,作为一个.NET developer有必要学习和了解这一工具.消息队列的使用场景大概有3种: 1.系统集成,分布式系统的设 ...

  9. 有趣的 CSS 像素艺术

    原文地址:https://css-tricks.com/fun-times-css-pixel-art/#article-header-id-4 译者:nzbin 友情提示:由于国内网络的原因,Cod ...

随机推荐

  1. 谈谈NIO和IO

    Channel,Buffer 和 Selector 构成了核心的API. 其它组件,如Pipe和FileLock,只不过是与三个核心组件共同使用的工具类. Channel和Buffer 基本上,所有的 ...

  2. n皇后问题 [随机化算法,拉斯维加斯算法]

    问题: 如何能够在 n×n 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行.纵行或斜线上. 分析: 这题常规的解法应该是回溯法, ...

  3. $(function(){})和$(document).ready(function(){}) 的区别

    document.ready和onload的区别——JavaScript文档加载完成事件 页面加载完成有两种事件 一是ready,表示文档结构已经加载完成(不包含图片等非文字媒体文件) 二是onloa ...

  4. Repository 设计模式介绍(转)

    在DDD设计中大家都会使用Repository pattern来获取domain model所需要的数据. 1.什么事Repository? "A Repository mediates b ...

  5. Struts2文件的上传

    一.单文件的上传  表单的enctype属性: application/x-www-form-urlencoded:默认的编码方式. multipart/form-data:会以二进制的方式处理表单数 ...

  6. MySQL导出以H开头的表

    情景:我有上百张以H开头的表,我需要备份出这些以H开头的表. mysqldump不支持*或者%这种通配符,所以没法实现备份以xx开头的表这种,这里算是个小技巧,利用文本编辑器来实现. [root@HE ...

  7. C# 程序集 和 反射

    .Net反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为.Net的反射机 ...

  8. HTML5获取当前的经纬度坐标

    使用IE10可以查看出结果:chrome和ff都没有正确显示: <!DOCTYPE html> <html lang="en"> <head> ...

  9. python bottle 简介

    bottle是一个轻量级的python web框架, 可以适配各种web服务器,包括python自带的wsgiref(默认),gevent, cherrypy,gunicorn等等.bottle是单文 ...

  10. [盘点]现今热门的h5网游

    各位好久不见,过年的休息时间已经结束,大家休息了一周,又要开始新的一年的奋斗了!于是小编从回来的第一天就开始花时间自己整理了一篇文章,所有各位是不是应该夸一夸小编呢?因为小编又要开始分享“干货”了.( ...