什么是中间件呢?
中间件是一类连接软件组件和应用的计算机软件,它包括一组服务。以便于运行在一台或多台机器上的多个软件通过网络进行交互。该技术所提供的互操作性,推动了一致分布式体系架构的演进,该架构通常用于支持并简化那些复杂的分布式应用程序,它包括web服务器、事务监控器和消息队列软件。 – 百度百科
其实也就是我们可以通过中间件和计算机底层的CPU、内存、磁盘进行交互,比如mysql中间件,我们通过mysql中间件来和磁盘进行交互,将数据存储到磁盘上面。
那么软件又如何和中间件进行通信交互,告知中间件去和磁盘或者内存进行交互(存储数据等)呢?
例如Java和Mysql如何通信?涉及到网络通信,就是涉及到数据传输,必然涉及到网络的7层模型中的数据传输层,数据传输一定会去遵守一定的协议进行传输数据。如Java和Mysql通信是遵守TCP/IP协议进行数据传输。
中间件的跨平台
假如不是Java和Mysql通信,而是Go、Python和Mysql通信呢?所以中间件一定要有跨平台的特点。
协议是在TCP/IP协议基础上构建的一种约定俗成的规范和机制,它的主要目的是让客户端之间可以进行沟通和通讯。并且这种协议下规范必须要有持久性、高可用、高可靠的特点。
像TCP/IP或者UDP协议虽然是很多都在使用的协议,但并不意味着它能满足所有的业务场景。如消息中间件就自己定义了一些协议进行数据的传输。
常用的一些消息队列数据传输协议:AMQP、MQTT、Kafka
一个系统,分为多个模块,在不同的机器上部署不同的功能,组合起来工作。
单体架构是一个请求发起jvm调度线程(tomcat线程池)分配线程处理请求直到释放。而分布式系统:一个请求是由多个系统共同协同完成,jvm和环境都是独立的。
存在问题
好处
如有一个分布式系统的架构,用户在App、前端、小程序进行一些操作时会将消息发送给中间件,其他相关系统需要去接收指定类型的消息,然后做出后续的业务操作。
消息中间件的应用场景:
其实,要明白,所有的中间件解决的最主要的问题就是通信问题
,大多都是通过中间件来实现异步通信。
ActiveMQ | RabbitMQ | Kafka | RocketMQ | |
---|---|---|---|---|
发布订阅 | 支持 | 支持 | 支持 | 支持 |
轮询发布 | 支持 | 支持 | 支持 | / |
公平分发 | / | 支持 | 支持 | / |
重发 | 支持 | 支持 | / | 支持 |
消息拉取 | / | 支持 | 支持 | 支持 |
高可用:是指产品在规定的条件和规定的时间内处于可执行规定功能状态的能力。一般情况下,当一台服务器已经无法满足业务需求的时候(请求量过大),考虑到系统的高可用性,必须要集群部署服务,到达高可用的目的。
高可靠:是指系统可以无故障的持续运行,比如一个系统突然崩溃报错,异常等等都不影响线上业务的正常运行,出错的几率极低。消息中间件如何保证高可靠?第一个就是消息传输时,通过协议保证系统间数据解析的正确性,第二是消息的持久化,通过持久化保证消息可靠性。
RabbitMQ是使用AMQP(默认)、MQTT(需要配置启用)协议的,这些协议是在tcp/ip协议基础上进行构建的。RabbitMQ是支持持久化的,会将数据存入磁盘中,使数据能够永久保存;而不是存储在内存中随着服务器断开而消息丢失。
需要服务器先安装好docker,然后使用docker快速安装部署RabbitMQ。没安装docker可以先把docker安装好
docker run -d -p 15672:15672 -p 5672:5672 \
-e RABBITMQ_DEFAULT_USER=admin \
-e RABBITMQ_DEFAULT_PASS=admin \
--hostname myRabbit \
--name rabbitmq \
rabbitmq
启用rabbitmq的管理插件
docker exec -it rabbitmq rabbitmq-plugins enable rabbitmq_management
记得把服务器的端口15672(网页管理端口)
和5672(AMQP端口)
开启一下,直接访问http://xxx.xxx.xx.xx:15672
如果RabbitMQ管理页面报500错误,记得进入docker 容器执行一下命令
# 进入 /etc/rabbitmq/conf.d/
cd /etc/rabbitmq/conf.d/
# 执行命令
echo management_agent.disable_metrics_collector = false > management_agent.disable_metrics_collector.conf
可以创建一些用户,并且赋予角色
简单模式就是一个生产者
发送消息到队列中,然后一个消费者
直接进行消费(一对一模式)
创建一个maven项目,导入RabbitMQ的依赖
<dependency>
<groupId>com.rabbitmqgroupId>
<artifactId>amqp-clientartifactId>
<version>5.4.3version>
dependency>
创建一个生产者,并且发送消息到队列中
// 创建连接工厂,初始化配置
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("xxx.xxx.xxx.xxx");
connectionFactory.setPort(5672);
connectionFactory.setUsername("admin");
connectionFactory.setPassword("admin");
connectionFactory.setVirtualHost("/");
// 连接
Connection connection = connectionFactory.newConnection("生产者");
// 获取通道 Channel
Channel channel = connection.createChannel();
// 通过创建交换机,声明队列,绑定关系,路由key,发送消息
String queue = "queue1";
/**
* @params1 队列名
* @params2 是否要持久化
* @params3 排他性,是否独占
* @params4 是否自动删除,最后一个消费者消费完消息后是否把队列自动删除
* @params5 携带的附加参数
*/
channel.queueDeclare(queue, false, false, false, null);
// 消息
String message = "hello message";
channel.basicPublish("", queue, null, message.getBytes());
System.out.println("发送成功");
// 关闭连接
channel.close();
connection.close();
可以在RabbitMQ的管理页面看到,创建了一个queue1
的队列
创建一个消费者进行消费,由于生产者创建队列时把自动删除给关了,我们消费后这个queue1的队列还存在。
// 创建连接工厂,初始化配置
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("xxx.xxx.xxx.xxx");
connectionFactory.setPort(5672);
connectionFactory.setUsername("admin");
connectionFactory.setPassword("admin");
connectionFactory.setVirtualHost("/");
// 连接
Connection connection = connectionFactory.newConnection("生产者");
// 获取通道 Channel
Channel channel = connection.createChannel();
// 通过创建交换机,声明队列,绑定关系,路由key,接收消息
String queue = "queue1";
channel.basicConsume(queue, true, (s, delivery) -> {
System.out.println("接收到消息:" + new String(delivery.getBody(), StandardCharsets.UTF_8));
}, s -> System.out.println("接收失败"));
// 关闭连接
channel.close();
connection.close();
如果创建队列时,设置为自动删除,那么管理页上会显示如下AD
,鼠标悬浮后显示auto-delete:true
channel.basicPublish("", queue, null, message.getBytes());
上面案例,生产者发送消息时并没有指定具体的交换机。虽然没有指定具体的交换机,但是会有一个默认的交换机。
图片来源学相伴-飞哥RabbitMQ教学
如果要在RabbitMQ管理页进行消息预览
这种模式就是常用的点对点(一对一)消息模式,生产者把消息放入到队列中,然后消费者消费消息,消费完后消息会被删除掉。
工作模式又分为两种:轮询模式、公平分发模式
交换机的几种消息模式指的是:交换机和队列的连接方式,生产者把生产出来的消息(设置routingKey、headers等)发送到交换机中,然后交换机会把消息分发到符合匹配关系的队列中
,消费者只需要去监听到队列即可。
注意:如果消费者监听了一个不存在的队列,那么程序会抛出异常。
Fanout–发布订阅模式
当交换机是Fanout模式时,当消息被发送到交换机时,所有的队列中都会被投放消息。也就是C1和C2都会收到相同的消息。也可以理解为广播模式。
Direct模式–直连模式,当生产者投递消息时没有声明交换机时,默认是发送到 direct模式
中的一个默认交换机中
这种模式是,交换机和队列绑定时,会创建一个routingKey,只有你的消息携带对应的routingKey时,消息才会被投递到对象的队列中。
topic模式和direct模式差异不大,对direct模式而言,topic模式是模糊匹配版的routingKey模式
此模式是在Headers中设置一些属性和值,只有发送的消息携带着这些属性和值的时候,此消息才会被投递到相应的队列中。