首先,我们先介绍一下消息队列。
队列是一个数据结构,可以存储,符合先进先出原理。(消息队列)Message Queue 作为一个单独的中间件产品存在的,独立部署的。
消息队列是一种进程间通信或同一进程的不同线程间的通信方式,软件的贮列用来处理一系列的输入,通常是来自用户。
消息的发送者和接收者不需要同时与消息队列交互。消息会保存到队列中,直到接收者取回它。
三个组件信息描述:
(1)Producer:消息生产者,负责产生和发送消息到Broker
(2)Broker:消息处理中心。负责消息存储、确认、重试等,一般其中会包含多个queue。
(3)Consumer:消息消费者,负责从Broker 中获取消息,并进行相应的处理。
为什么要用消息对列???
(特点)
解耦、异步、削峰
(1)解耦:降低耦合度。消息队列减少了服务之间的耦合性,不同的服务可以通过消息队列进行通信,而不用关系彼此的实现细节,只要定义好消息的格式就可以。
(2)异步:提升服务的性能,允许接收者在消息发送很长时间后再取回消息。
(3)削峰:将某一短时间的超高流量分摊到更长的一段时间内去消化,避免了流量洪峰击垮系统。
RabbitMQ 作为常见的消息队里中间件之一, 该中间件是基于主从做 高可用的,有三种模式,单机模式,普通集群模式,镜像集群模式,每台机器上存储着全量数据。
RabbitMQ:基于AMQP协议,erlang语言开发,稳定性好。
实现高级消费队列协议(AMQP)的开源消息代理软件(面向消息的中间件)。RabbitMQ服务器是用Erlang 语言编写的,而集群和故障转移是构建在开放电信平台架构上的。所有主要的编程语言均有与代理接口通讯的客户端库。
RabbitMQ 支持下列编程语言:
python Java Ruby PHP C# JavaScript Go Elixir Objective-C Swift
主要特性:集群服务
消息持久化:从内存持久化消息到硬盘,再从硬盘加载到内存。
RabbitMQ 安装的过程:
Erlang 与 RabbitMQ 安装路径都不应含有空格符。
安装RabbitMQ 需要安装Erlang。
AMQP 是 Advanced Message Queuing Protocol 简称,它是一个面向消息中间件的开发标准应用层协议。AMQP定义了特性:
(1)消息方向
(2)消息队列
(3)消息路由(包括:点到点和发布-订阅模式)
(4)可靠性
(5)安全性
RabbitMQ 是以AMQP协议实现的一种中间件产品,支持多操作系统,多种编程语言,几乎可以覆盖所有主流的企业级技术平台。
实现RabbitMQ 的小案例:
Java 实现生产者:
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.MessageProperties;
/**
* @author : Jone
* @date : 2022/3/29 15:46
* @description : 生产者 producer
*/
public class ProducerRabbit {
// 设置队列的名称 DirectQueue
private static String queueName = "DirectQueue";
public static void main(String[] args) throws Exception{
// 配置RabbitMQ 信息
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setUsername("guest");
factory.setPassword("guest");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(queueName, true, false, false, null);
// 循环发送数据信息
for (int i = 0; i < 100; i++){
//发送的消息
String message = "简单数据(scalars,标量数据)可以不使用引号括起来,包括字符串数据。用单引号或者双引号括起来的被当作字符串数据,在单引号或双引号中使用C风格的转义字符";
// 往队列中发出一条消息 String exchange, String routingKey
// channel.basicPublish("", routingKeyName, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());
channel.basicPublish("", queueName, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());
System.out.println(" [x] Sent '" + message + "'");
Thread.sleep(1000);
}
//关闭频道和连接
channel.close();
connection.close();
}
}
SpringBoot 架构实现消费者:
package com.toec.bussiness.util;
import com.toec.util.ModifyRegular;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* @author : Jone
* @date : 2022/3/29 14:32
* @description :
*/
@Component
@RabbitListener(queues = "testDirectQueue") // 监听的队列名称testDirectQueue
//@RabbitListener(queues = "DirectQueue") // 监听的队列名称DirectQueue
public class DirectReceiver {
@RabbitHandler
public void receiver(String message){
System.out.println("DirectReceiver消费者收到消息:" + message.toString());
// channel.nack(message)来让不通过的消息再次进入消息队列
// 测试
String ruleInfo = "简单数据((scalars,标量数据))可以不使用引号括起来,包括(字符串数据)。用单引号或者双引号括起来的被当作字符串数据";
ModifyRegular modifyRegular = new ModifyRegular();
// message 进行处理 返回数据(队列返回数据) ack 机制
modifyRegular.modifyRegularMethod(message, ruleInfo);
}
}