下载安装

Erlang

RabbitMQ

启动RabbitMQ管理平台插件

DOS下进入到安装目录\sbin,执行以下命令

rabbitmq-plugins enable rabbitmq_management

当出现以下结果时,重启RabbitMQ服务

set 3 plugins.
Offline change; changes will take effect at broker restart.

访问http://localhost:15672(账号密码:guest)

注意:以下为C#代码,请引用NuGet包:RabbitMQ.Client

参考文章

RabbitMQ快速入门

名词解析

P(Publisher):生产者

C(Consumer):消费者

Channel:信道

Queue:队列

Exchange:信息交换机

简单演示

信息发送端

static void Send()
{
//1. 实例化连接工厂
var factory = new ConnectionFactory() { HostName = "localhost" };
//2. 建立连接
using (var connection = factory.CreateConnection())
{
//3. 创建信道
using (var channel = connection.CreateModel())
{
//4. 声明队列
channel.QueueDeclare(queue: "rabbitmq",
durable: false,
exclusive: false,
autoDelete: false,
arguments: null); //5. 构建字节数据包
var message = "Hello RabbitMQ!";
var body = Encoding.UTF8.GetBytes(message); //6. 发送数据包
channel.BasicPublish(exchange: "",
routingKey: "rabbitmq",
basicProperties: null,
body: body); Console.WriteLine(" [x] Sent {0}", message);
}
}
}

信息接收端

static void Receive()
{
//1. 实例化连接工厂
var factory = new ConnectionFactory() { HostName = "localhost" };
//2. 建立连接
using (var connection = factory.CreateConnection())
{
//3. 创建信道
using (var channel = connection.CreateModel())
{
//4. 声明队列
channel.QueueDeclare(queue: "rabbitmq",
durable: false,
exclusive: false,
autoDelete: false,
arguments: null); //5. 构造消费者实例
var consumer = new EventingBasicConsumer(channel); //6. 绑定消息接收后的事件委托
consumer.Received += (model, ea) =>
{
var message = Encoding.UTF8.GetString(ea.Body);
Console.WriteLine(" [x] Received {0}", message);
};
//7. 启动消费者
channel.BasicConsume(queue: "rabbitmq",
autoAck: true,
consumer: consumer); Console.WriteLine(" Press [enter] to exit.");
Console.ReadLine(); }
}
}

轮询调度

P生产的多个任务进入到队列中,多个C间可以并行处理任务。默认情况下,RabbitMQ把信息按顺序发送给每一个C。平均每个C将获得同等数量的信息。

信息确认

按照最简单的演示来说,信息一旦发送到C中,则该信息就会从队列中移除。一旦中间信息处理异常/失败,C端程序退出等,都将会导致信息未处理完成,而此时队列中已将信息移除了,那么就会导致一系列的问题。我们可以在C端设置手动确认信息,从而解决上述问题的发生。

Receive代码块

//6. 绑定消息接收后的事件委托
consumer.Received += (model, ea) =>
{
var message = Encoding.UTF8.GetString(ea.Body);
Console.WriteLine(" [x] Received {0}", message);
Thread.Sleep(5000);//模拟耗时
Console.WriteLine(" [x] Done"); // 发送信息确认信号(手动信息确认)
channel.BasicAck(ea.DeliveryTag, false);
};
//7. 启动消费者
/*
autoAck参数属性
true:自动信息确认,当C端接收到信息后,自动发送ack信号,不管信息是否处理完毕
false:关闭自动信息确认,通过调用BasicAck方法手动进行信息确认
*/
channel.BasicConsume(queue: "rabbitmq",
autoAck: false,
consumer: consumer);

信息持久化

当RabbitMQ退出或死机时会清空队列和信息。通过将队列和信息标记为持久的,来告知RabbitMQ将信息持久化。

Send代码块

//4. 声明队列
//durable设置为true,表示此队列为持久的。
//注意:RabbitMQ不允许你使用不同的参数重新定义一个已经存在的队列,所以你需要重启服务/更改队列名称
channel.QueueDeclare(queue: "rabbitmq",
durable: true, //标记队列持久
exclusive: false,
autoDelete: false,
arguments: null);
//设置IbasicProperties.SetPersistent属性值为true来标记我们的消息持久化
var properties = channel.CreateBasicProperties();
properties.Persistent = true; //5. 构建字节数据包
var message = "Hello RabbitMQ!";
var body = Encoding.UTF8.GetBytes(message); //6. 发送数据包
channel.BasicPublish(exchange: "",
routingKey: "rabbitmq",
basicProperties: properties, //指定BasicProperties
body: body);

公平调度

上述演示中,如果队列中存在多个信息,在开启多个C的情况下,只有一个C忙个不停,另外的却一直处于空闲状态。通过调用BasicQos,告知RabbitMQ在某个C信息处理完毕,并且已经收到信息确认之后,才可以继续发送信息到这个C。否则,将会把信息分发到另外空闲的C。

Receive代码块

//4. 声明队列
channel.QueueDeclare(queue: "rabbitmq",
durable: true,
exclusive: false,
autoDelete: false,
arguments: null);
////设置prefetchCount为1来告知RabbitMQ在未收到消费端的消息确认时,不再分发消息
channel.BasicQos(prefetchSize: 0,
prefetchCount: 1,
global: false);

发布/订阅

上述中的演示,P推送信息至队列中,C从队列中处理信息。但是如果需要将P推送的信息至每个订阅的C中处理信息,那么我们就可以使用Exchange。

fanout(将信息分发到exchange上绑定的所有队列上)

Send代码块

//1. 实例化连接工厂
var factory = new ConnectionFactory() { HostName = "localhost" };
//2. 建立连接
using (var connection = factory.CreateConnection())
{
//3. 创建信道
using (var channel = connection.CreateModel())
{
//4. 声明信息交换机
channel.ExchangeDeclare(exchange: "fanoutDemo",
type: "fanout"); //5. 构建字节数据包
var message = "Hello RabbitMQ!";
var body = Encoding.UTF8.GetBytes(message); //6. 发布到指定exchange,fanout类型的会忽视routingKey的值,所以无需填写
channel.BasicPublish(exchange: "fanoutDemo",
routingKey: "",
basicProperties: null,
body: body); Console.WriteLine(" [x] Sent {0}", message);
}
}

Receive代码块

//1. 实例化连接工厂
var factory = new ConnectionFactory() { HostName = "localhost" };
//2. 建立连接
using (var connection = factory.CreateConnection())
{
//3. 创建信道
using (var channel = connection.CreateModel())
{
//4. 声明信息交换机
channel.ExchangeDeclare(exchange: "fanoutDemo",
type: "fanout");
//生成随机队列名称
var queueName = channel.QueueDeclare().QueueName;
//绑定队列到指定fanout类型exchange
channel.QueueBind(queue: queueName,
exchange: "fanoutDemo",
routingKey: ""); //5. 构造消费者实例
var consumer = new EventingBasicConsumer(channel); //6. 绑定消息接收后的事件委托
consumer.Received += (model, ea) =>
{
var message = Encoding.UTF8.GetString(ea.Body);
Console.WriteLine(" [x] Received {0}", message);
}; channel.BasicConsume(queue: queueName,
autoAck: true,
consumer: consumer); Console.WriteLine(" Press [enter] to exit.");
Console.ReadLine(); }
}

direct(C绑定的队列名称须和P发布指定的路由名称一致)

Send代码块

//4. 声明信息交换机
channel.ExchangeDeclare(exchange: "directDemo",
type: "direct"); //5. 构建字节数据包
var message = "Hello RabbitMQ!";
var body = Encoding.UTF8.GetBytes(message); //6. 发布到指定exchange
channel.BasicPublish(exchange: "directDemo",
routingKey: "a",
basicProperties: null,
body: body);

Receive代码块

//4. 声明信息交换机
channel.ExchangeDeclare(exchange: "directDemo",
type: "direct");
//生成随机队列名称
var queueName = channel.QueueDeclare().QueueName;
//绑定队列到指定direct类型exchange
channel.QueueBind(queue: queueName,
exchange: "directDemo",
routingKey: "b");

topic(支持通配符的路由规则)

通配字符:

  • *:匹配一个单词
  • #:匹配0个或多个单词
  • .:仅作为分隔符

Send代码块

//4. 声明信息交换机
channel.ExchangeDeclare(exchange: "topicDemo",
type: "topic"); //5. 构建字节数据包
var message = "Hello RabbitMQ!";
var body = Encoding.UTF8.GetBytes(message); //6. 发布到指定exchange
channel.BasicPublish(exchange: "topicDemo",
routingKey: "admin.user.error", //模拟后台用户错误
basicProperties: null,
body: body);

Receive代码块

//4. 声明信息交换机
channel.ExchangeDeclare(exchange: "topicDemo",
type: "topic");
//生成随机队列名称
var queueName = channel.QueueDeclare().QueueName;
//绑定队列到指定topic类型exchange
channel.QueueBind(queue: queueName,
exchange: "topicDemo",
routingKey: "admin.*.#"); //订阅所有后台异常错误

RPC(远程过程调用)

  1. 进行远程调用的客户端需要指定接收远程回调的队列,并申明消费者监听此队列。
  2. 远程调用的服务端除了要申明消费端接收远程调用请求外,还要将结果发送到客户端用来监听的结果的队列中去。

客户端代码块

var factory = new ConnectionFactory() { HostName = "localhost" };
using (var connection = factory.CreateConnection())
{
using (var channel = connection.CreateModel())
{
var correlationId = Guid.NewGuid().ToString();
var replyQueue = channel.QueueDeclare().QueueName; var properties = channel.CreateBasicProperties();
properties.ReplyTo = replyQueue;
properties.CorrelationId = correlationId; string number = args.Length > 0 ? args[0] : "30";
var body = Encoding.UTF8.GetBytes(number);
//发布消息
channel.BasicPublish(exchange: "", routingKey: "rpc_queue", basicProperties: properties, body: body); Console.WriteLine($"[*] Request fib({number})"); // //创建消费者用于消息回调
var callbackConsumer = new EventingBasicConsumer(channel);
channel.BasicConsume(queue: replyQueue, autoAck: true, consumer: callbackConsumer); callbackConsumer.Received += (model, ea) =>
{
if (ea.BasicProperties.CorrelationId == correlationId)
{
var responseMsg = $"Get Response: {Encoding.UTF8.GetString(ea.Body)}"; Console.WriteLine($"[x]: {responseMsg}");
}
}; Console.ReadLine(); }
}

服务端代码块

static void Main(string[] args)
{
var factory = new ConnectionFactory() { HostName = "localhost" };
using (var conection = factory.CreateConnection())
{
using (var channel = conection.CreateModel())
{
channel.QueueDeclare(queue: "rpc_queue", durable: false,
exclusive: false, autoDelete: false, arguments: null); var consumer = new EventingBasicConsumer(channel);
Console.WriteLine("[*] Waiting for message."); consumer.Received += (model, ea) =>
{
var message = Encoding.UTF8.GetString(ea.Body);
int n = int.Parse(message);
Console.WriteLine($"Receive request of Fib({n})");
int result = Fib(n); var properties = ea.BasicProperties;
var replyProerties = channel.CreateBasicProperties();
replyProerties.CorrelationId = properties.CorrelationId; channel.BasicPublish(exchange: "", routingKey: properties.ReplyTo,
basicProperties: replyProerties, body: Encoding.UTF8.GetBytes(result.ToString())); channel.BasicAck(ea.DeliveryTag, false);
Console.WriteLine($"Return result: Fib({n})= {result}"); };
channel.BasicConsume(queue: "rpc_queue", autoAck: false, consumer: consumer); Console.ReadLine();
}
} } private static int Fib(int n)
{
if (n == 0 || n == 1)
{
return n;
}
return Fib(n - 1) + Fib(n - 2);
}

RabbitMQ基础入门篇的更多相关文章

  1. SQLAlchemy 教程 —— 基础入门篇

    SQLAlchemy 教程 -- 基础入门篇 一.课程简介 1.1 实验内容 本课程带领大家使用 SQLAlchemy 连接 MySQL 数据库,创建一个博客应用所需要的数据表,并介绍了使用 SQLA ...

  2. Linux及Arm-Linux程序开发笔记(零基础入门篇)

    Linux及Arm-Linux程序开发笔记(零基础入门篇)  作者:一点一滴的Beer http://beer.cnblogs.com/ 本文地址:http://www.cnblogs.com/bee ...

  3. FPGA基础入门篇(四) 边沿检测电路

    FPGA基础入门篇(四)--边沿检测电路 一.边沿检测 边沿检测,就是检测输入信号,或者FPGA内部逻辑信号的跳变,即上升沿或者下降沿的检测.在检测到所需要的边沿后产生一个高电平的脉冲.这在FPGA电 ...

  4. ASP.NET Core消息队列RabbitMQ基础入门实战演练

    一.课程介绍 人生苦短,我用.NET Core!消息队列RabbitMQ大家相比都不陌生,本次分享课程阿笨将给大家分享一下在一般项目中99%都会用到的消息队列MQ的一个实战业务运用场景.本次分享课程不 ...

  5. 【Linux开发】Linux及Arm-Linux程序开发笔记(零基础入门篇)

    Linux及Arm-Linux程序开发笔记(零基础入门篇) 作者:一点一滴的Beer http://beer.cnblogs.com/ 本文地址:http://www.cnblogs.com/beer ...

  6. JS基础入门篇(三十五)—面向对象(二)

    如果没有面向对象这种抽象概念的小伙伴,建议先看一下我写的JS基础入门篇(三十四)-面向对象(一)

  7. 云小课|DGC数据开发之基础入门篇

    阅识风云是华为云信息大咖,擅长将复杂信息多元化呈现,其出品的一张图(云图说).深入浅出的博文(云小课)或短视频(云视厅)总有一款能让您快速上手华为云.更多精彩内容请单击此处. 摘要:欢迎来到DGC数据 ...

  8. .NET ORM 的 “SOD蜜”--零基础入门篇

    PDF.NET SOD框架不仅仅是一个ORM,但是它的ORM功能是独具特色的,我在博客中已经多次介绍,但都是原理性的,可能不少初学的朋友还是觉得复杂,其实,SOD的ORM是很简单的.下面我们就采用流行 ...

  9. Elasticsearch 7.x 之文档、索引和 REST API 【基础入门篇】

    前几天写过一篇<Elasticsearch 7.x 最详细安装及配置>,今天继续最新版基础入门内容.这一篇简单总结了 Elasticsearch 7.x 之文档.索引和 REST API. ...

随机推荐

  1. Petya and Graph(最小割,最大权闭合子图)

    Petya and Graph http://codeforces.com/contest/1082/problem/G time limit per test 2 seconds memory li ...

  2. JAVA序列化和反序列化 对象<=>IO流 对象<=>字节数组

    http://developer.51cto.com/art/201202/317181.htm http://blog.csdn.net/earbao/article/details/4691440 ...

  3. SVN版本冲突问题

    --------------------siwuxie095 SVN 版本冲突问题 如:Jack 和 Mary 从仓库中将项目下载到本地,然后 Jack 修改了 项目中的一个文件,并上传到仓库中,之后 ...

  4. android环境安装及配置

    直接从网上下载适合当前系统的jdk(eclipse需要一个java虚拟器的环境) 直接从android上下载最新的adt-bundle-windows-x86(64)-xxxxxx.zip(集成好的e ...

  5. css菜鸟学习之text-align属性,行内元素,块级元素居中详解

    一.text-align属性 1.text-align用来设置元素中的的文本对齐方式,例如:如果需要设置图片的对齐方式,需要设置图片的父元素的text-align属性: 2.text-align只对文 ...

  6. 在ecplise中创建一个maven工程

    1.我们首先需要在Ecplise中配置maven环境,详情见我的博客:https://www.cnblogs.com/wyhluckdog/p/10277278.html 2.maven projec ...

  7. 全基因组测序 从头测序(de novo sequencing) 重测序(re-sequencing)

    全基因组测序 全基因组测序分为从头测序(de novo sequencing)和重测序(re-sequencing). 从头测序(de novo)不需要任何参考基因组信息即可对某个物种的基因组进行测序 ...

  8. centos 挂载u盘

    1.创建一个目录来挂载U盘 mkdir /mnt/usb #创建usb目录挂载U盘 2.插上U盘,查看移动设备状态 fdisk -l #(注意:参数是小写字母 l 不是数字 1) 会看到类似这一行:/ ...

  9. 【commons-httpclient】Java中HttpClient工具访问Web请求

    注意jar包是: HttpClient工具使用 HttpClient 是 Apache Jakarta Common 下的子项目,可以用来提供高效的.最新的.功能丰富的支持 HTTP 协议的客户端编程 ...

  10. spring boot web项目在IDEA下热部署解决办法(四步搞定)

    最近在用spring boot 做一个web站点,修改了类.html.js等,刷新页面,没有生效,非要手动去make一下或者重启,大大降低了开发效率. 什么是热部署? 应用启动后会把编译好的Class ...