RabbitMQ基本命令
ubuntu、基于Debian的【deb】的系统
sudo service rabbitmq-server start
sudo service rabbitmq-server stop
sudo service rabbitmq-server restart
sudo service rabbitmq-server status
CentOS、基于rpm的系统
systemctl start rabbitmq-server
systemctl stop rabbitmq-server
systemctl restart rabbitmq-server
systemctl status rabbitmq-server
插件管理
sudo rabbitmq-plugins enable rabbitmq_management #启用某个插件
sudo rabbitmq-plugins list #显示所有插件名
应用
流量削峰、降低耦合
整合Spring
连接
public class FactoryRabbit {
public ConnectionFactory getFactory(){
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setPort(5672);
connectionFactory.setHost("222.201.144.247");
connectionFactory.setUsername("lian");
connectionFactory.setPassword("lian");
connectionFactory.setVirtualHost("/virtual");
return connectionFactory;
}
}
发布消息
public class RabbitMQTest {
public static void main(String[] args) throws IOException, TimeoutException {
FactoryRabbit factoryRabbit = new FactoryRabbit();
ConnectionFactory factory = factoryRabbit.getFactory();
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare("hello",false,false,false,null);
channel.basicPublish("","hello",MessageProperties.PERSISTENT_TEXT_PLAIN,"hello:lian".getBytes());
channel.close();
connection.close();
}
}
消费消息
public class Customer {
public static void main(String[] args) throws IOException, TimeoutException {
FactoryRabbit factoryRabbit = new FactoryRabbit();
ConnectionFactory factory = factoryRabbit.getFactory();
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
Channel.basicQos(1);//每一次只能消费一个消息
channel.queueDeclare("hello",false,false,false,null);
//关闭自动确认机制
channel.basicConsume("hello",false,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("msg: "+ new String(body));
channel.basicAck(envelope.getDeliveryTag(),false);
}
});
}
}
消息确认机制:
工作队列中的每条消息只要有一个worker处理即可
当开启自动确认机制时,消费者接受到消息则会自动返回确认,而不管剩下的业务逻辑是否顺利执行。在自动确认机制开启的情况下,在工作队列中每个消费者往往是循环的接收到队列中的消息。所以需要关闭消息自动确认
channel.basicConsume("hello",false,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("msg: "+ new String(body));
channel.basicAck(envelope.getDeliveryTag(),false);
}
});
优点:保证能者多劳,消息不会丢失
发布和订阅模式:广播
需要用到交换机:队列中的每条消息都发送给所有worker:
其中发送者只需要把消息给交换机即可
public class FanOut {
public static void main(String[] args) throws IOException, TimeoutException {
FactoryRabbit factoryRabbit = new FactoryRabbit();
ConnectionFactory factory = factoryRabbit.getFactory();
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare("exchange","fanout");
channel.basicPublish("exchange","",null,"fan out".getBytes());
channel.close();
connection.close();
}
}
而接收者需要定义临时队列并通过队列接受消息
public class FanCustomer {
public static void main(String[] args) throws IOException, TimeoutException {
FactoryRabbit factoryRabbit = new FactoryRabbit();
ConnectionFactory factory = factoryRabbit.getFactory();
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
//在channel对象里添加一个交换机
channel.exchangeDeclare("exchange","fanout");
//在channel对象里添加一个临时队列:queueDeclare(),并返回队列名
String queue = channel.queueDeclare().getQueue();
//绑定指定的交换机和队列,一个channel对象里有多个交换机和队列
channel.queueBind(queue,"exchange","");
//在channel中指定的队列中消费对象,设置自动确认,否则应当手动确认
channel.basicConsume(queue,true,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(new String(body));
}
});
}
}
路由模式:
交换机通过消息中不同的key值转发到不同的消息队列中:指定交换机类型type=direct
发布消息部分:
public class Route {
public static void main(String[] args) throws IOException, TimeoutException {
FactoryRabbit factoryRabbit = new FactoryRabbit();
ConnectionFactory factory = factoryRabbit.getFactory();
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare("direct_exchange","direct");
String key = "info";
channel.basicPublish("direct_exchange",key,null,"msg:key is info".getBytes());
channel.close();
connection.close();
}
}
接收消息部分
public class RouteCustomer {
public static void main(String[] args) throws IOException, TimeoutException {
FactoryRabbit factoryRabbit = new FactoryRabbit();
ConnectionFactory factory = factoryRabbit.getFactory();
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare("direct_exchange","direct");
String queue = channel.queueDeclare().getQueue();
String key = "info";
//当使用动态路由时,用统配符代替下面的key即可,*匹配一个,而#匹配多个
channel.queueBind(queue,"direct_exchange",key);
channel.basicConsume(queue,true,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(new String(body));
}
});
}
}
整合SpringBoot
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
application.properties,用RabbitTemplate直接注入然后操作即可
spring.rabbitmq.host=222.201.144.247
spring.rabbitmq.port=5672
spring.rabbitmq.username=lian
spring.rabbitmq.password=lian
#虚拟主机名
spring.rabbitmq.virtual-host=/virtual
注解开发
@Component
@RabbitListener(queuesToDeclare = @Queue(value = "boot",durable = "false"))
public class HalloCustomer {
@RabbitHandler
public void receive(String message) {
System.out.println("message:"+ message);
}
}
class MqApplicationTests {
@Autowired
public RabbitTemplate rabbitTemplate;
@Test
void test() {
rabbitTemplate.convertAndSend("boot","hello spring");
}
}
基于SpringBoot的多种模式
工作队列:循环分配
@Component
public class Work {
@RabbitListener(queuesToDeclare = @Queue("work"))
public void receive1(String msg){
System.out.println("message1:"+msg);
}
@RabbitListener(queuesToDeclare = @Queue("work"))//监听的队列名称是work
public void receive2(String msg){
System.out.println("message2:"+msg);
}
}
发布订阅:广播
@Test
void fanOut(){
rabbitTemplate.convertAndSend("logs","","fanout:msg");
}
@Component
public class FanOut {
@RabbitListener(bindings = {@QueueBinding(
value = @Queue,
exchange = @Exchange(value = "logs",type = "fanout")
)})
public void receive(String msg){
System.out.println("receive1:"+ msg);
}
@RabbitListener(bindings = {@QueueBinding(
value = @Queue,
exchange = @Exchange(value = "logs",type = "fanout")
)})
public void receive2(String msg){
System.out.println("receive2:"+ msg);
}
}
路由模式:
@Test
void route(){
rabbitTemplate.convertAndSend("directs","info","route:msg");
}
@Component
public class Route {
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue,
exchange = @Exchange(value = "directs",type = "direct"),
key = {"info","error"}
)
})
public void receive(String msg){
System.out.println("receive1"+msg);
}
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue,
exchange = @Exchange(value = "directs",type = "direct"),
key = {"debug"}
)
})
public void receive2(String msg){
System.out.println("receive2 "+msg);
}
}
动态路由
@Test
void topic(){
rabbitTemplate.convertAndSend("topics","info.hello","topic:msg");
}
@Component
public class Topic {
@RabbitListener(bindings = {@QueueBinding(
value = @Queue,
exchange = @Exchange(type="topic",name = "topics"),
key = {"info.#"}
)
})
public void receive(String msg){
System.out.println("receive: "+msg);
}
}
RabbitMQ镜像集群
主备集群只是同步交换机信息,对除了消息队列外的信息做一个备份而已。其他节点能够通过主节点看到队列,但实际上并没有消息队列的实际信息
ubuntu搭建好的rabbitmq默认是没有配置文件的,需要我们来手动添加;Rabbitmq的一些运行脚本存放在 /usr/sbin 下面;通过rabbitmqctl cluster_status命令,可以查看和个节点的状态。
创建步骤1:
vim /etc/rabbitmq/rabbitmq.config
[{rabbit, [{loopback_users, []}]}].
拷贝/var/lib/rabbitmq/ .erlang.cookie,因为是隐藏的直接ls看不到
步骤2:
要将一个节点加入到现有的集群中,你需要停止这个应用并将节点设置为原始状态,然后就为加入集群准备好了。使用rabbitmqctl stop_app仅仅关闭应用
./rabbitmqctl stop_app
./rabbitmqctl join_cluster rabbit@host
./rabbitmqctl start_app
./rabbitmqctl cluster_status
步骤3:
设置镜像集趣
#set_policy [-p vhostpath] {name} {pattern} {definition} [priority]
./rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}
Setting policy "ha-all" for pattern "^" to "{\"ha-mode\":\"all\"}" with priority "0"
./rabbitmqctl list_policies#显示当前正在使用的策略
消息队列的作用
解耦合:在某个场景下需要向不同的系统发送消息,为了避免为每一个系统维护一个接口,并方面后续的扩展,使用消息队列达到解耦合的目的
异步操作:某个系统接收到用户请求,不仅需要调用本地服务,还要调用其他服务,有时可以不用等待后续服务的调用结果,将调用申请缓冲到消息队列中,直接向用户返回结果,避免了长时间的等待。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)