下载安装

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. 149. Max Points on a Line (Array; Greedy)

    Given n points on a 2D plane, find the maximum number of points that lie on the same straight line. ...

  2. python2.7中可以使用到的一些模块地址

    1.reportlab:由很多部分组成且允许用户使用多种方法创建输出,地址: 下载ReportLab https://pypi.python.org/simple/reportlab/ http:// ...

  3. 二叉树的层次遍历 · Binary Tree Level Order Traversal

    [抄题]: 给出一棵二叉树,返回其节点值的层次遍历(逐层从左往右访问) [思维问题]: [一句话思路]: 用queue存每一层 [输入量]:空: 正常情况:特大:特小:程序里处理到的特殊情况:异常情况 ...

  4. 分析maven的优点

    1.依赖管理: 就是对jar包的管理. 2.项目的一键构建: 编译--->测试--->运行--->打包--->安装 运行一个maven工程(web工程)只需要一个命令:toma ...

  5. 将对象转为json,加入到HttpResponseMessage中

    需要引用程序集: System.Net.Http System.Web System.Web.Extensions Code: using System; using System.Collectio ...

  6. Electronic Trading[z]

    This article is to discuss the operation model between Fund Managers(Client) and Broker Firms. They ...

  7. Codeforces 677C. Vanya and Label 位操作

    C. Vanya and Label time limit per test:1 second memory limit per test:256 megabytes input:standard i ...

  8. 用Notepad++在文本文件里快速在每行头尾都加上指定的内容(转载)

  9. php 事务处理,ActiveMQ的发送消息,与处理消息

    可以通过链式发送->处理->发送...的方式处理类似事务型业务逻辑 比如 发送一个注册消息,消息队列处理完注册以后,紧接着发送一个新手优惠券赠送,赠送完再发一个其它后续逻辑处理的消息等待后 ...

  10. Basic4android v3.80 beta 发布

    增加了条件编译,共享模块,部分支持jar 文件直接访问.还有其他一些更新. I'm happy to release B4A v3.80 BETA. This version includes sev ...