消息中间件 RabbitMQ 入门篇
消息中间件 RabbitMQ 入门篇
作者:五月君,来源:Nodejs技术栈
从不浪费时间的人,没有工夫抱怨时间不够。—— 杰弗逊
RabbitMQ 是一套开源(MPL)的消息队列服务软件,是由 LShift 提供的一个 Advanced Message Queuing Protocol (AMQP) 的开源实现,由以高性能、健壮以及可伸缩性出名的 Erlang 写成。
作者简介:五月君,Nodejs Developer,慕课网认证作者,热爱技术、喜欢分享的 90 后青年,欢迎关注 Nodejs技术栈 和 Github 开源项目 https://www.nodejs.red
通过本篇能学到什么?
为什么要使用 RabbitMQ?
RabbitMQ 应用场景?
MQ 的空间与时间解耦是什么?
常用的主流消息中间件都有哪些?
如何安装、启动一个 RabbitMQ 服务?
如何构建一个简单的生产者与消费者模型?
为什么要使用 RabbitMQ?
近两年谈的很多的一个概念微服务,在一个大型业务系统架构中,会被拆分成很多小的业务系统,这些业务系统之间如何建立通信呢?大家熟知的 HTTP、RPC 可以实现不同系统、不同语言之间的通信,除了这些往往还会使用消息队列(RabbitMQ、ActiveMQ、Kafafa 等)将这些系统链接起来,达到各系统间的解耦。
另外,在后端使用 Node.js 哪怕开发一个稍微大点的系统,消息队列这些知识也是值得你去关注学习的。例如,生产端我可以使用 Node.js 生产一些数据放到队列中,另一段完全可以根据需要我使用 Python 或者其它语言去实现。
RabbitMQ 应用场景
1. 同步转异步
在项目中对于一些没必要同步处理的,可以借助 MQ 进行异步处理,例如,我们的短信发送就可以通过 MQ 队列来做。
2. 应用解耦
例如商城业务场景中,订单系统与库存系统,下单的同步可能也要去减少库存,将原本耦合在一块的逻辑可以通过消息队列进行,订单系统发布消息,库存系统订阅消息,这样的好处是一般库存系统出现问题也不会影响到订单系统。
3. 流量削峰
流量削峰在一些营销活动、秒杀活动场景中应用还是比较广泛的,如果短时间流量过大,可以通过设置阀值丢弃掉一部分消息或者根据服务的承受能力设置处理消息限制,也就是限流,之后也会单独进行讲解。
MQ 的空间与时间解耦
从空间上来看,消息的生产者无需提前知道消费者的存在,反之消费者亦是,两者之间得到了解耦,不会强依赖,从而实现空间上的解耦。
从时间上来看,消息的生产者只负责生产数据将数据放入队列,之后无需关心消费者什么时间去消费,消费则可以根据自己的业务需要来选择实时消费还是延迟消费,两者都拥有了自己的生命周期,从而实现了时间上的解耦。
主流消息中间件一览
ActiveMQ:Apache 出品,早起很流行主要应用于中小企业,面对大量并发场景会有阻塞、消息堆积问题。
Kafka:是由 Apache 软件基金会开发的一个开源流处理平台,由 Scala 和 Java 编写,是一种高吞吐量的分布式发布订阅消息系统,支持单机每秒百万并发。最开始目的主要用于大数据方向日志收集、传输。0.8 版本开始支持复制,不支持事物,因此对消息的重复、丢失、错误没有严格的要求。
RocketMQ:阿里开源的消息中间件,是一款低延迟、高可靠、可伸缩、易于使用的消息中间件,思路起源于 Kafka。最大的问题商业版收费,有些功能不开放。
RabbitMQ:是一个由 erlang(有着和原生 Socket 一样低的延迟)语言开发基于 AMQP 协议的开源消息队列系统。能保证消息的可靠性、稳定性、安全性。
安装指南
Mac版安装
直接通过 HomeBrew 安装,执行以下命令
brew install rabbitmq
启动 rabbitmq
# 进入安装目录$ /usr/local/Cellar/rabbitmq/3.7.8# 启动$ sbin/rabbitmq-server
浏览器输入 http://localhost:15672/#/ 默认用户名密码 guest
Linux系统安装
安装依赖
apt-get install build-essential openssl openssl-devel unixODBC unixODBC-devel make gcc gcc-c++ kernel-devel m4 ncurses-devel tk tc xz lsof
获取安装包
rabbitmq和erlang安装包一定要对应,具体可以查看对应关系,官网有说明RabbitMQ Erlang Version Requirements
获取erlang安装包
sudo wget http://www.rabbitmq.com/releases/erlang/erlang-18.3-1.el6.x86_64.rpm
获取socat安装包
socat支持多协议,用于协议处理、端口转发,rabbitmq依赖于此。
sudo wget http://repo.iotti.biz/CentOS/7/x86_64/socat-1.7.3.2-5.el7.lux.x86_64.rpm
获取rabbitmq-server安装包 rabbitmq-server
安装包列表
sudo wget http://www.rabbitmq.com/releases/rabbitmq-server/v3.6.5/rabbitmq-server-3.6.5-1.noarch.rpm
开始安装
Centos rpm 一键安装
这里采用rpm一键安装,centos 执行命令 rpm-ivh erlang-18.3-1.el6.x86_64.rpm,在 ubuntu 中不支持此命令 rpm,使用 rpm 提示如下信息:
rpm: RPM should not be used directly install RPM packages, useAlien instead!rpm: However assuming you know what you are doing...error: Failed dependencies:
ubuntu系统 rpm 一键安装解决方案
安装
alien,执行命令sudo apt-getinstall alien转换
rpm包为.deb格式,执行命令sudo alienpackage.rpm其中package.rpm为你的包名通过dpkg安装,
sudo dpkg-ipackage.deb
以下顺序安装(以下是基于 CentOS 系统安装)
rpm -ivh erlang-18.3-1.el6.x86_64.rpmrpm -ivh socat-1.7.3.2-5.el7.lux.x86_64.rpmrpm -ivh rabbitmq-server-3.6.5-1.noarch.rpm
修改配置文件
vim /usr/lib/rabbitmq/lib/rabbitmq_server-3.6.5/ebin/rabbit.app
{loopback_users, [<<"guest">>]}, // 修改为 {loopback_users, [guest]},
运行与启动
开启 rabbitmq
rabbitmqctl start_app
开启管理插件
rabbitmq-plugins enable rabbitmq_management
检查状态
$ lsof -i:5672# 看到以下提示则开启成功COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEbeam 4678 rabbitmq 49uIPv62941580t0 TCP *:amqp (LISTEN)
开启管理通知台 终端更多操作命令,以下有说明,浏览区输入
http://host:15672打开管理控制台

几个端口区别说明
5672:通信默认端口号15672:管理控制台默认端口号25672:集群通信端口号
注意: 阿里云 ECS 服务器如果出现 RabbitMQ 安装成功,外网不能访问是因为安全组的问题没有开放端口 解决方案
操作命令
以下列举一些在终端常用的操作命令
whereis rabbitmq:查看 rabbitmq 安装位置
rabbitmqctl start_app:启动应用
whereis erlang:查看erlang安装位置
rabbitmqctl start_app:启动应用
rabbitmqctl stop_app:关闭应用
rabbitmqctl status:节点状态
rabbitmqctl add_user username password:添加用户
rabbitmqctl list_users:列出所有用户
rabbitmqctl delete_user username:删除用户
rabbitmqctl add_vhost vhostpath:创建虚拟主机
rabbitmqctl list_vhosts:列出所有虚拟主机
rabbitmqctl list_queues:查看所有队列
rabbitmqctl -p vhostpath purge_queue blue:清除队列里消息
构建一个简单的生产者与消费者模型
生产者-消费者模型是指一方生产数据一方消费数据。两者之间会有一个缓冲区做为中介,生产者把数据放入缓冲区,消费者从缓冲区取出数据。另外,生产者消费者模式也是是面向过程编程其中的一种设计模式。
构建生产者与消费者步骤
以下列举一下生产者与消费者模型在实现时的一些步骤,各语言在实现的过程中也都是大同小异的。
生产者步骤
创建链接工厂
通过链接工厂创建链接
通过链接创建通道(channel)
通过 channel 发送数据
关闭链接
消费者步骤
创建链接工厂
通过链接工厂创建链接
通过链接创建通道(channel)
声明一个队列
创建消费者
设置 channel
Node.js 版本
amqplib 客户端
Github: https://github.com/squaremo/amqp.node
$ npm install amqplib
构建生产者
生产者发消息的时候必须要指定一个 exchange,若不指定 exchange(为空)会默认指向 AMQPdefault 交换机, AMQPdefault 路由规则是根据 routingKey 和 mq 上有没有相同名字的队列进行匹配路由。
const amqp = require('amqplib');async function producer() {// 1. 创建链接对象const connection = await amqp.connect('amqp://localhost:5672');// 2. 获取通道const channel = await connection.createChannel();// 3. 声明参数const routingKey = 'helloworldQueue';const msg = 'hello world';for(let i=0; i<5; i++) {// 4. 发送消息await channel.publish('', routingKey, Buffer.from(`${msg} 第${i}条消息`));}// 5. 关闭链接await channel.close();}producer();
构建消费者
const amqp = require('amqplib');async function consumer() {// 1. 创建链接对象const connection = await amqp.connect('amqp://localhost:5672');// 2. 获取通道const channel = await connection.createChannel();// 3. 声明参数const queueName = 'helloworldQueue';// 4. 声明队列,交换机默认为 AMQP defaultawait channel.assertQueue(queueName);// 5. 消费await channel.consume(queueName, msg => {console.log('Consumer:', msg.content.toString());channel.ack(msg);});}consumer();
Node.js 示例代码
源码地址如下:https://github.com/Q-Angelo/project-training/tree/master/rabbitmq/helloworld
Java 版本
添加 maven 依赖
在 SpringBoot 项目的 pom.xml 文件中引入 amqp-client 启动器
<dependency><groupId>com.rabbitmq</groupId><artifactId>amqp-client</artifactId><version>5.6.0</version></dependency>
构建生产者
package com.may.rabbitmq.helloworld;import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import com.rabbitmq.client.ConnectionFactory;publicclassProducer{publicstaticvoid main(String[] args) throwsException{// 1. 创建链接工厂ConnectionFactory connectionFactory = newConnectionFactory();connectionFactory.setHost("127.0.0.1");connectionFactory.setPort(5672);connectionFactory.setVirtualHost("/");// 2. 通过链接工厂创建链接Connection connection = connectionFactory.newConnection();// 3. 通过链接创建通道(channel)Channel channel = connection.createChannel();// 4. 通过 channel 发送数据// exchange:交换机,如果不传默认为 AMQP defaultchannel.basicPublish("", "helloworldQueue", null, "hello world".getBytes());// 5. 关闭链接channel.close();connection.close();}}
构建消费者
package com.may.rabbitmq.helloworld;import com.rabbitmq.client.*;import java.io.IOException;import java.util.concurrent.TimeUnit;publicclassConsumer{publicstaticvoid main(String[] args) throwsException{// 1. 创建链接工厂ConnectionFactory connectionFactory = newConnectionFactory();connectionFactory.setHost("127.0.0.1");connectionFactory.setPort(5672);connectionFactory.setVirtualHost("/");// 2. 通过链接工厂创建链接Connection connection = connectionFactory.newConnection();// 3. 通过链接创建通道(channel)Channel channel = connection.createChannel();// 4. 声明一个队列String queueName = "helloworldQueue";channel.queueDeclare(queueName, true, false, false, null);// 5. 创建消费者// springboot 从 1.5.9 升级到 2.0.0,QueueingConsumer 报错(Cannot resolve symbol 'QueueingConsumer')没有这个类,改为使用 DefaultConsumerDefaultConsumer consumer = newDefaultConsumer(channel) {@Overridepublicvoid handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throwsIOException{super.handleDelivery(consumerTag, envelope, properties, body);String message = newString(body, "UTF-8");System.out.printf("in consumer B (delivery tag is %d): %s\n", envelope.getDeliveryTag(), message);// System.out.printf("d%: s%\n", envelope.getDeliveryTag(), message);try{TimeUnit.MILLISECONDS.sleep(200);} catch(InterruptedException e) {}channel.basicAck(envelope.getDeliveryTag(), false);}};// 6. 设置 channelchannel.basicConsume(queueName, false, consumer);System.out.println("消费端启动成功!");}}
运行测试

Java 示例代码
小项目大思想 — SpringBoot实战系列https://github.com/Q-Angelo/SpringBoot-Course源码地址如下:https://github.com/Q-Angelo/SpringBoot-Course/tree/master/chapter8/chapter8-1
在上面的这个 生产者-消费者 例子中,也需你会感到疑惑生产者和消费者之间的消息是如何进行匹配传递的?在之后的一节 RabbitMQ 的交换机详解 中会介绍,它们是如何进行消息的匹配投递工作。
总结
通过本文学习,希望你能掌握什么场景下会应用到 MQ、可以自己尝试下安装一下 MQ 服务并构建一个简单的生产者-消费者模型。因为它很重要,通常也是互联网企业必备的基础组件之一,因此后续也打算写一个系列文章,包含不同交换机的消息投递机制、限流、延迟队列、重试、高可用设计等等敬请关注本公众号 “Nodejs技术栈” 获取最新消息
消息中间件 RabbitMQ 入门篇的更多相关文章
- javaweb消息中间件——rabbitmq入门
概念:RabbitMQ是一款开源的消息中间件系统,由erlang开发,是AMQP的实现. 架构图大概如上. broker是消息队列的服务器,比如在linux上,我们安装的rabbitmq就是一个bro ...
- RabbitMq学习一入门篇(hello world)
简介 RabbitMQ是一个开源的AMQP实现,服务器端用Erlang语言编写,支持多种客户端,如:Python.Ruby..NET.Java,也是众多消息队列中表现不俗的一员,作用就是提高系统的并发 ...
- .NET 环境中使用RabbitMQ RabbitMQ与Redis队列对比 RabbitMQ入门与使用篇
.NET 环境中使用RabbitMQ 在企业应用系统领域,会面对不同系统之间的通信.集成与整合,尤其当面临异构系统时,这种分布式的调用与通信变得越发重要.其次,系统中一般会有很多对实时性要求不高的 ...
- 消息中间件——RabbitMQ(五)快速入门生产者与消费者,SpringBoot整合RabbitMQ!
前言 本章我们来一次快速入门RabbitMQ--生产者与消费者.需要构建一个生产端与消费端的模型.什么意思呢?我们的生产者发送一条消息,投递到RabbitMQ集群也就是Broker. 我们的消费端进行 ...
- RabbitMQ入门与使用篇
介绍 RabbitMQ是一个由erlang开发的基于AMQP(Advanced Message Queue)协议的开源实现.用于在分布式系统中存储转发消息,在易用性.扩展性.高可用性等方面都非常的优秀 ...
- 分布式系统消息中间件——RabbitMQ的使用基础篇
分布式系统消息中间件——RabbitMQ的使用基础篇
- 分布式系统消息中间件——RabbitMQ的使用思考篇
分布式系统消息中间件--RabbitMQ的使用思考篇 前言 前面的两篇文章分布式系统消息中间件--RabbitMQ的使用基础篇与分布式系统消息中间件--RabbitMQ的使用进阶篇,我们简单介 ...
- 分布式系统消息中间件——RabbitMQ的使用进阶篇
分布式系统消息中间件--RabbitMQ的使用进阶篇 前言 上一篇文章 (https://www.cnblogs.com/hunternet/p/9668851.html) 简单总结了分布式系 ...
- RabbitMQ入门看这一篇就够了
一文搞懂 RabbitMQ 的重要概念以及安装 一 RabbitMQ 介绍 这部分参考了 <RabbitMQ实战指南>这本书的第 1 章和第 2 章. 1.1 RabbitMQ 简介 Ra ...
随机推荐
- Oracle使用expdp/impdp迁移数据
Oracle使用expdp/impdp迁移数据 1.#以下步骤在开发库执行(expdp导出) 一.创建逻辑目录,该命令不会在操作系统创建真正的目录,最好以system等管理员创建. sqlplus / ...
- Docker08-网络管理
目录 桥接网络 Bridge Network 相关操作命令 实例演示:容器之间通过自定义bridge通讯 宿主网络 Host Network Overlay Network 相关操作命令 实例演示:容 ...
- springboot 打包太大,打包瘦身,打包thin
pom文件修改: <build> <resources> <resource> <directory>src/main/resources</di ...
- 详解Linux操作系统的进程
系统 计算机运行起来以后,就是由内核和运行在内核之上的众多进程来实现的(kernel+process) 内存分为 : 线性内存: 物理内存: 计算机的所有运行都只在内存和CPU中运行! 内核空间 ...
- Httpd服务进阶知识-基于FASTCGI实现的LAMP架构
Httpd服务进阶知识-基于FASTCGI实现的LAMP架构 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.httpd+php结合的方式 module: php fastcgi ...
- MySQL利用IF查询不同条件并分别统计记录数
数据库记录如下: 现在要查询统计出每个'name'的'result'分别为'success'和'fail'的次数: 利用IF条件判断满足条件为1,不满足为0,再用SUM函数求和,最后通过'name'分 ...
- [转]etcdctl v2 v3 使用指南
原文:https://blog.csdn.net/kozazyh/article/details/79586530 ------------------------------------------ ...
- ArcGIS Server 注册托管数据库
需要已经安装好ArcGIS for Desktop.ArcGIS for Server和ArcSDE,并且已经创建了地理数据库 我试了用管理网站添加,总是不成功,后来用ArcCatalog添加成功.这 ...
- loj10017. 「一本通 1.2 练习 4」传送带(三分套三分)
题目描述 在一个2维平面上有两条传送带,每一条传送带可以看成是一条线段.两条传送带分别为线段AB和线段CD.lxhgww在AB上的移动速度为P,在CD上的移动速度为Q,在平面上的移动速度R.现在lxh ...
- BZOJ - 3242 :快餐店 (基环树DP) 最小化半径
题意:给定N点N边的无向连通图,现在让你在图中找一点作为餐厅,使得最远点距离这点最近. 思路:为了保留整数,我们求最小直径,最后去除2. 直径来源于两部分: 1,在外向树中: 那么就是树的直接,一棵 ...