RabbitMQ学习
遵循tcp/ip协议,互通性
跨平台
介绍
为什么需要使用消息中间件
具体地说,中间件屏蔽了底层操作系统的复杂性,使程序开发人员面对一个简单而统一的开发环境,减少程序设计的复杂性,将注意力集中在自己的业务上,不必再为程序在不同系统软件上的移植而重复工作,从而大大减少了技术上的负担。中间件带给应用系统的,不只是开发的简便、开发周期的缩短,也减少了系统的维护、运行和管理的工作量,还减少了计算机总体费用的投入。
中间件特点
为解决分布异构问题,人们提出了中间件(middleware)的概念。中间件是位于平台(硬件和操作系统)和应用之间的通用服务,如下图所示,这些服务具有标准的程序接口和协议。针对不同的操作系统和硬件平台,它们可以有符合接口和协议规范的多种实现。
安装RabbitMQ
官网:https://www.rabbitmq.com/
什么是RabbitMQ,官方给出来这样的解释
RabbitMQ是部署最广泛的开源消息代理。
RabbitMQ拥有成千上万的用户,是最受欢迎的开源消息代理之一。从T-Mobile 到Runtastic,RabbitMQ在全球范围内的小型初创企业和大型企业中都得到使用。
RabbitMQ轻巧,易于在内部和云中部署。它支持多种消息传递协议。RabbitMQ可以部署在分布式和联合配置中,以满足大规模,高可用性的要求。
RabbitMQ可在许多操作系统和云环境上运行,并为大多数流行语言提供了广泛的开发人员工具。
简单概述:
RabbitMQ是一个开源的遵循AMQP协议实现的基于Erlang语言编写,支持多种客户端(语言)。用于在分布式系统中存储消息,转发消息,具有高可用,高可扩性,易用性等特征。
https://www.erlang.org/
什么是消息中间件
消息中间件基于队列模型实现异步/同步传输数据
作用:可以实现支撑高并发、异步解耦、流量削峰、降低耦合度。
传统的http请求存在那些缺点
1.Http请求基于请求与响应的模型,在高并发的情况下,客户端发送大量的请求达到
服务器端有可能会导致我们服务器端处理请求堆积。
2.Tomcat服务器处理每个请求都有自己独立的线程,如果超过最大线程数会将该请求缓存到队列中,如果请求堆积过多的情况下,有可能会导致tomcat服务器崩溃的问题。
所以一般都会在nginx入口实现限流,整合服务保护框架。
3.http请求处理业务逻辑如果比较耗时的情况下,容易造成客户端一直等待,阻塞等待
过程中会导致客户端超时发生重试策略,有可能会引发幂等性问题。
注意事项:接口是为http协议的情况下,最好不要处理比较耗时的业务逻辑,耗时的业务逻辑应该单独交给多线程或者是mq处理。
MQ应用场景
-
异步发送短信
-
异步发送新人优惠券
-
处理一些比较耗时的操作
MQ与多线程之间的关系
- MQ可以实现异步/解耦/流量削峰问题;
- 多线程也可以实现异步,但是消耗到cpu资源,没有实现解耦。
MQ消息中间件名词
- Producer 生产者:投递消息到MQ服务器端;
- Consumer 消费者:从MQ服务器端获取消息处理业务逻辑;
- Broker MQ服务器端
- Topic 主题:分类业务逻辑发送短信主题、发送优惠券主题
- Queue 存放消息模型 队列 先进先出 后进后出原则 数组/链表
- Message 生产者投递消息报文:json
docker run -d --restart=always --hostname rabbit-host --name rabbitmq001 -e RABBITMQ_DEFAULT_USER=user -e RABBITMQ_DEFAULT_PASS=password -p 15672:15672 -p 5672:5672 rabbitmq:3.7.7-management
user/password
特性 | ActiveMQ | RabbitMQ | RocketMQ | kafka |
---|---|---|---|---|
开发语言 | java | erlang | java | scala |
单机吞吐量 | 万级 | 万级 | 10万级 | 10万级 |
时效性 | ms级 | us级 | ms级 | ms级以内 |
可用性 | 高(主从架构) | 高(主从架构) | 非常高(分布式架构) | 非常高(分布式架构) |
功能特性 | 成熟的产品,在很多公司得到应用;有较多的文档;各种协议支持较好 | 基于erlang开发,所以并发能力很强,性能极其好,延时很低管理界面较丰富 | MQ功能比较完备,扩展性佳 | 只支持主要的MQ功能,像一些消息查询,消息回溯等功能没有提供,毕竟是为大数据准备的,在大数据领域应用广。 |
生产者投递消息给MQ服务器端,MQ服务器端需要缓存该消息
如果mq服务器端宕机之后,消息如何保证不丢失
- 持久化机制
如果mq接收到生产者投递消息,如果消费者不在的情况下,该消息是否会丢失?
不会丢失,消息确认机制 必须要消费者消费该消息成功之后,在通知给mq服务器端
删除该消息。
Mq服务器端将该消息推送消费者:
消费者已经和mq服务器保持长连接。
消费者主动拉取消息:
消费者第一次刚启动的时候
Mq如何实现抗高并发思想
Mq消费者根据自身能力情况 ,拉取mq服务器端消息消费。
默认的情况下是取出一条消息。
缺点:存在延迟的问题
需要考虑mq消费者提高速率的问题:
如何消费者提高速率:消费者实现集群、消费者批量获取消息即可。
什么是netty
就是将客户端和服务器端进行通讯
RabbitMQ
基本介绍
RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件),RabbitMQ服务器是用Erlang语言编写的。
RabitMQ官方网站:
https://www.rabbitmq.com/
- 点对点(简单)的队列
- 工作(公平性)队列模式
- 发布订阅模式
- 路由模式Routing
- 通配符模式Topics
- RPC
https://www.rabbitmq.com/getstarted.html
RabbitMQ环境的基本安装
1.下载并安装erlang,下载地址:http://www.erlang.org/download
2.配置erlang环境变量信息
新增环境变量ERLANG_HOME=erlang的安装地址
将%ERLANG_HOME%\bin加入到path中
3.下载并安装RabbitMQ,下载地址:http://www.rabbitmq.com/download.html
注意: RabbitMQ 它依赖于Erlang,需要先安装Erlang。
https://www.rabbitmq.com/install-windows.html
net start RabbitMQ
启动Rabbitmq常见问题
如果rabbitmq 启动成功无法访问 管理平台页面
进入到F:\path\rabbitmq\rabbitmq\rabbitmq_server-3.6.9\sbin>
执行
rabbitmq-plugins enable rabbitmq_management
rabbitmqctl start_app
Windows控制台指令
netstat -ano:查看端口占用情况
netstat -ano | findstr xxxx:查看某个端口被占用情况 //xxxx为查询的端口号
tasklist | findstr xxxx:查看使用指定端口的应用程序 //xxxx指的是pid
taskkill /pid xxxx -t -f //xxxx指的是pid
或者:taskkill /f /t /im QQ.exe:结束指定进程
Rabbitmq管理平台中心
RabbitMQ 管理平台地址 http://127.0.0.1:15672
默认账号:guest/guest 用户可以自己创建新的账号
Virtual Hosts:
像mysql有数据库的概念并且可以指定用户对库和表等操作的权限。那RabbitMQ呢?
RabbitMQ也有类似的权限管理。在RabbitMQ中可以虚拟消息服务器VirtualHost,每
个VirtualHost相当月一个相对独立的RabbitMQ服务器,每个VirtualHost之间是相互
隔离的。exchange、queue、message不能互通。
默认的端口15672:rabbitmq管理平台端口号
默认的端口5672: rabbitmq消息中间内部通讯的端口
默认的端口号25672 rabbitmq集群的端口号
RabbitMQ常见名词
/Virtual Hosts—分类
/队列 存放我们消息
Exchange 分派我们消息在那个队列存放起来 类似于nginx
15672—rabbitmq控制台管理平台 http协议
25672rabbitmq 集群通信端口号
Amqp 5672 rabbitmq内部通信的一个端口号
使用RabbitMq需要导入的依赖
<dependencies>
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>3.6.5 </version>
</dependency>
</dependencies>
创建RabbitMQ的步骤
- 在RabbitMQ平台创建一个队列
- 编写生产者代码
- 编写消费者代码
点对点通信
创建连接
public class RabbitMQConection {
//获取连接
public static Connection getConnection() throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
//1.设置连接 virtualHost 分类
connectionFactory.setVirtualHost("/chenVirtualHost");
//2.设置账号和密码
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
//3.MQ连接消息地址
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort(5672);
return connectionFactory.newConnection();
}
}
创建生产者
public class Producer {
private static final String QUEUE_NAME="chen-queues";
public static void main(String[] args) throws IOException, TimeoutException {
//获取到连接
Connection connection = RabbitMQConection.getConnection();
//创建通道
Channel channel = connection.createChannel();
//创建要发送的信息
String msg="你好,小七";
//通过通道发送消息 投放信息到哪一个队列中
channel.basicPublish("",QUEUE_NAME,null,msg.getBytes());
//3.关闭通道和连接 先开后关
channel.close();
connection.close();
}
}
创建消费者
public class Consumer {
private static final String QUEUE_NAME = "chen-queues";
public static void main(String[] args) throws IOException, TimeoutException {
// 1.创建连接
Connection connection = RabbitMQConection.getConnection();
// 2.设置通道
Channel channel = connection.createChannel();
DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String msg = new String(body, "UTF-8");
System.out.println("消费者获取消息:" + msg);
}
};
// 3.监听队列 自动签收 手动签收模式
channel.basicConsume(QUEUE_NAME, true, defaultConsumer);
}
}
RabbitMQ如何保证信息不丢失
Mq如何保证消息不丢失:
1.生产者角色
确保生产者投递消息到MQ服务器端成功。
Ack 消息确认机制
同步或者异步的形式
方式1:Confirms
方式2:事务消息
2.消费者角色
在rabbitmq情况下:
必须要将消息消费成功之后,才会将该消息从mq服务器端中移除。
在kafka中的情况下:
不管是消费成功还是消费失败,该消息都不会立即从mq服务器端移除。
3.Mq服务器端 在默认的情况下 都会对队列中的消息实现持久化
持久化硬盘。
1.使用消息确认机制+持久技术
A.消费者确认收到消息机制
channel.basicConsume(QUEUE_NAME, false, defaultConsumer);
注:第二个参数值为false代表关闭RabbitMQ的自动应答机制,改为手动应答。
在处理完消息时,返回应答状态,true表示为自动应答模式。
channel.basicAck(envelope.getDeliveryTag(), false);
B.生产者确认投递消息成功 使用Confirm机制 或者事务消息
RabbitMQ交换机类型
Direct exchange(直连交换机)
Fanout exchange(扇型交换机)
Topic exchange(主题交换机)
Headers exchange(头交换机)
/Virtual Hosts—区分不同的团队
----队列 存放消息
----交换机 路由消息存放在那个队列中 类似于nginx
—路由key 分发规则
RabbitMQ Fanout发布订阅
生产者发送一条消息,经过交换机转发到多个不同的队列,多个不同的队列就多个不同的消费者。
原理:
-
需要创建两个队列 ,每个队列对应一个消费者;
-
队列需要绑定我们交换机
-
生产者投递消息到交换机中,交换机在将消息分配给两个队列中都存放起来;
-
消费者从队列中获取这个消息。
Direct路由模式
当交换机类型为direct类型时,根据队列绑定的路由建转发到具体的队列中存放消息
Topic主题模式
当交换机类型为topic类型时,根据队列绑定的路由建模糊转发到具体的队列中存放。
#号表示支持匹配多个词