MQ 的概念
MQ 全称 Message Queue(消息队列),是在消息的传输过程中保存消息的容器。用于分布式系统之间进行通信。
MQ 的优势
解耦
系统的耦合性越高,容错性就越低,可维护性就越低。使用 MQ 使得应用间解耦,提升容错性和可维护性。
具体而言
在一个复杂的系统中,不同的模块或服务之间可能需要相互依赖,如果是直接使用函数调用或者 API 调用的方式会造成模块之间的耦合。当一个模块发生改变时,调用方和被调用方的代码要同时修改。而使用消息队列作为中间件,不同的模块就可以将消息发送到消息队列中, 也不需要知道具体的接收方是谁。接收方可以独立的消费消息,实现了模块之间的解耦。
异步
一次请求可能会涉及多个系统的多次服务调用,服务与服务之间响应时间不断叠加,如果使用同步的方式处理,会阻塞主线程或者进程,导致系统性能下降。而使用 MQ 可以将这些操作封装成消息,放入消息队列中,异步地处理这些操作,不影响主流程的执行,提高了系统的性能和响应速度。
削峰填谷
削峰填谷是一种在高并发场景下平衡系统压力的技术,通常用于平衡系统在高峰期和低谷期的资源利用率提高系统的吞吐量和响应速度在削峰填谷的过程中,通常使用消息队列作为缓冲区,将请求放入消息队列中,然后在系统负载低的时候进行处理这种方式可以将系统的峰值压力分散到较长的时间段内减少瞬时压力对系统的影响,从而提高系统的稳定性和可靠性。
MQ 的劣势
使用 MQ 中间件将面临以下两个问题:
- 系统可用性降低系统引入的外部依赖越多,系统稳定性越差。一旦 MQ 宕机,就会对业务造成影响。如何保证 MQ 的高可用成为了新的挑战。
- 系统复杂度提高。MQ 的加入大大增加了系统的复杂度,以前系统间是同步的远程调用,现在是通过 MQ 进行异步调用。如何保证消息不被丢失等情况?
RabbitMQ官网:www.rabbitmq.com/
安装RabbitMQ
首先安装了Homebrew,并且确保是最新:
sql
brew update
使用一下命令安装 RabbitMQ 服务器:
brew rabbitmq
安装路径:
Intel Mac,应该在:/usr/local/opt/rabbitmq/sbin
Apple Mac ,应该在:/opt/homebrew/Cellar/rabbitmq
也可以使用 brew info rabbitmq 命令来查找:
vbnet
# liulvhua @ MacBookPro in / [19:04:39]
$ brew info rabbitmq
==> rabbitmq: stable 3.12.9 (bottled)
Messaging broker
https://www.rabbitmq.com
/opt/homebrew/Cellar/rabbitmq/3.12.9 (1,442 files, 34.4MB) *
Poured from bottle using the formulae.brew.sh API on 2023-11-19 at 19:03:51
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/r/rabbitmq.rb
License: MPL-2.0
==> Dependencies
Required: erlang ✔
==> Caveats
Management Plugin enabled by default at http://localhost:15672
To start rabbitmq now and restart at login:
brew services start rabbitmq
Or, if you don't want/need a background service you can just run:
CONF_ENV_FILE="/opt/homebrew/etc/rabbitmq/rabbitmq-env.conf" /opt/homebrew/opt/rabbitmq/sbin/rabbitmq-server
==> Analytics
install: 6,952 (30 days), 21,352 (90 days), 57,247 (365 days)
install-on-request: 6,949 (30 days), 21,350 (90 days), 57,235 (365 days)
build-error: 0 (30 days)
# liulvhua @ MacBookPro in / [19:35:59]
RabbitMQ 服务器脚本和CLI工具
Intel Mac 位于:/usr/local/Cellar/rabbitmq/{version}/sbin
Apple Mac 位于:/opt/homebrew/Cellar/rabbitmq/{version}/
登录管理端(需先启动):默认账户是(guest/guest)
启动 RabbitMQ Server
前台启动:
ini
CONF_ENV_FILE="/opt/homebrew/etc/rabbitmq/rabbitmq-env.conf" /opt/homebrew/opt/rabbitmq/sbin/rabbitmq-server
后台启动:
sql
brew services start rabbitmq
停止服务:
arduino
brew services stop rabbitmq
或者直接使用 CLI 工具:
arduino
/opt/homebrew/sbin/rabbitmqctl shutdown
配置环境变量:
ruby
# for macOS Intel
export PATH=$PATH:/usr/local/sbin
# for Apple Silicon
export PATH=$PATH:/opt/homebrew/sbin
社区插件下载安装
www.rabbitmq.com/community-p...
安装rabbitmq_delayed_message_exchange
找到对应的版本 下载:
放到rabbitmq安装路径下的plugins目录下:
使用以下命令启用插件:
bash
../sbin/rabbitmq-plugins enable rabbitmq_delayed_message_exchange
enable后面加插件名,复制前缀即可。若rabbitmq未启动,则不会生效,需要在命令后面再加上 --offline。
在 Spring 项目中使用 RabbitMQ
大体分为以下步骤:
- 添加RabbitMQ依赖:在
pom.xml
文件中添加以下Maven依赖项,以引入RabbitMQ的相关库:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
- 配置RabbitMQ连接:在
application.properties
(或application.yml
)文件中添加RabbitMQ的连接配置,包括URL、端口、用户名和密码等信息。例如:
ini
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=username
spring.rabbitmq.password=password
- 创建消息发送者和接收者:在Spring项目中,可以通过注解来定义消息发送者和接收者。
- 消息发送者:使用
RabbitTemplate
类来发送消息。创建一个类,并使用@Component
注解标记为组件,然后使用@Autowired
注解将RabbitTemplate
实例注入到该类中。你可以调用convertAndSend()
方法来发送消息,指定交换机名称、路由键和消息内容。例如:
typescript
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class MessageSender {
private RabbitTemplate rabbitTemplate;
@Autowired
public MessageSender(RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
}
public void sendMessage(String exchange, String routingKey, Object message) {
rabbitTemplate.convertAndSend(exchange, routingKey, message);
}
}
- 消息接收者:使用
@RabbitListener
注解来标记一个方法,该方法将用于处理接收到的消息。创建一个类,并使用@Component
注解标记为组件,然后定义一个带有@RabbitListener
注解的方法,指定监听的队列名称。例如:
kotlin
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
public class MessageReceiver {
@RabbitListener(queues = "myQueue")
public void receiveMessage(String message) {
System.out.println("Received message: " + message);
}
}
- 配置交换机和队列:可以使用
RabbitAdmin
类来在Spring项目中自动声明交换机和队列。在你的配置类中,使用@Bean
注解创建一个RabbitAdmin
实例,并为交换机和队列设置属性。例如:
typescript
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RabbitMQConfig {
@Bean
public Queue myQueue() {
return new Queue("myQueue");
}
@Bean
public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
return new RabbitAdmin(connectionFactory);
}
}
这些是在Spring项目中使用RabbitMQ的基本步骤。实际还应根据实际需求进行进一步的配置和扩展,例如使用交换机和绑定、设置消息确认等功能。
RabbitMQ 的工作模式
RabbitMQ 一共有六种(工作模式消息分发方式)。
官网对应介绍:www.rabbitmq.com/getstarted....
- 简单模式(HelloWorld)一个生产者、一个消费者,不需要设置交换机(使用默认的交换机)。
- 工作队列模式(Work Queue)一个生产者、多个消费者(竞争关系),不需要设置交换机(使用默认的交换机)。
- 发布订阅模式(Publish/Subscribe) 需要设置类型为 fanout 的交换机,并且交换机和队列进行绑定,当发送消息到交换机后,交换机会将消息发送到绑定的队列。
- 路由模式(Routing) 需要设置类型为 fanout 的交换机,并且交换机和队列进行绑定,当发送消息到交换机后,交换机会将消息发送到绑定的队列。
- 主题模式(Topics) 需要设置类型为 fanout 的交换机,并且交换机和队列进行绑定,当发送消息到交换机后,交换机会将消息发送到绑定的队列。
- RPC模式(不太算MQ)