【MQ工作队列模式】

1 、模式介绍
Work Queues :与入门程序的简单模式相比,多了一个或一些消费端,
多个消费端共同消费同一个队列中的消息。
应用场景:对于任务过重或任务较多情况使用工作队列可以提高任务处
理的速度。
小结 :
1 、在一个队列中如果有多个消费者,那么消费者之间对于同一个消息的关
系是 竞争 的关系
2 Work Queues 对于任务过重或任务较多情况使用工作队列可以提高任
务处理的速度。例如:短信服务部署多个,
只需要有一个节点成功发送即可。

 

2 、代码实现
Work Queues 与入门程序的简单模式的代码几乎是一样的。可以完全复
制,并多复制一个消费者进行多
个消费者同时对消费消息的测试。
1 、生产者
生产者代码 Producer_WorkQueues:
package com.dxw.producer;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* 生产者:发送消息
*/
public class Producer_WorkQueues {
public static void main(String[] args) throws
IOException, TimeoutException {
//1、创建连接工厂
ConnectionFactory factory = new
ConnectionFactory();
//2、设置参数
factory.setHost("localhost");//ip 默认localhost
factory.setPort(5672);//端口 默认5672
factory.setVirtualHost("/dxw");//虚拟机 默认/
factory.setUsername("dxw");//用户名 默认guest
factory.setPassword("1234");//密码 默认guest
//3、创建连接
Connection connection = factory.newConnection();
//4、创建Channel
Channel channel = connection.createChannel();
//5、创建队列
/*
* 参数解释:
* queueDeclare(String queue,
* boolean durable,
* boolean exclusive,
* boolean autoDelete,
* Map<String, Object> arguments)
* 1. queue:队列名称
* 如果没有一个名字叫hello_world的队列,则会创建该队
列,如果有则不会创建
* 2. durable:是否持久化,当mq重启之后,队列中消息还在
* 3. exclusive:
* 是否独占。只能有一个消费者监听这队列
* 当Connection关闭时,是否删除队列
* 4. autoDelete:是否自动删除。当没有Consumer时,自动
删除掉
* 5. arguments:参数。
*/
channel.queueDeclare("work_queues",true,false,false,null)
;
//6、发送消息
/*
* 参数解释:
* basicPublish(String exchange,
* String routingKey,
* BasicProperties props,
* byte[] body)
* 1. exchange:交换机名称。简单模式下交换机会使用默认的
""
* 2. routingKey:路由名称
* 3. props:配置信息
* 4. body:发送消息数据
启动生产者观察控制台
2、消费者
第一个消费者代码Consumer_WorkQueues1:
*/
for(int i=1;i<=10;i++){
String body = i+"hello rabbitmq~~~";
channel.basicPublish("","work_queues",null,body.getBytes(
));
}
//7、释放资源
//channel.close();
//connection.close();
}
}
启动生产者观察控制台

 

2 、消费者
第一个消费者代码 Consumer_WorkQueues1:
package com.dxw.consumer;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* 消费者:接收消息
*/
public class Consumer_WorkQueues1 {
public static void main(String[] args) throws
IOException, TimeoutException {
//1、创建连接工厂
ConnectionFactory factory = new
ConnectionFactory();
//2. 设置参数
factory.setHost("localhost");//ip 默认值 localhost
factory.setPort(5672); //端口 默认值 5672
factory.setVirtualHost("/dxw");//虚拟机 默认/
factory.setUsername("dxw");//用户名 默认guest
factory.setPassword("1234");//密码 默认guest
//3. 创建连接 Connection
Connection connection = factory.newConnection();
//4. 创建Channel
Channel channel = connection.createChannel();
//5、创建队列
/*
* 参数解释:
* queueDeclare(String queue,
* boolean durable,
* boolean exclusive,
* boolean autoDelete,
* Map<String, Object> arguments)
* 1. queue:队列名称
* 如果没有一个名字叫hello_world的队列,则会创建该
队列,如果有则不会创建
* 2. durable:是否持久化,当mq重启之后,队列中消息还在
* 3. exclusive:
* 是否独占。只能有一个消费者监听这队列
* 当Connection关闭时,是否删除队列
* 4. autoDelete:是否自动删除。当没有Consumer时,自
动删除掉
* 5. arguments:参数。
*/
channel.queueDeclare("work_queues",true,false,false,null)
;
//6、接收消息
Consumer consumer = new DefaultConsumer(channel){
/*
回调方法,当收到消息后,会自动执行该方法
1. consumerTag:标识
2. envelope:获取一些信息,交换机,路由key...
3. properties:配置信息
4. body:数据
*/
@Override
public void handleDelivery(String consumerTag,
Envelope envelope, AMQP.BasicProperties properties, byte[]
body) throws IOException {
/*System.out.println("consumerTag:"+consumerTag);
System.out.println("Exchange:"+envelope.getExchange());
System.out.println("RoutingKey:"+envelope.getRoutingKey(
));
System.out.println("properties:"+properties);*/
System.out.println("body:"+new
String(body));
}
};
/*
* 参数解释:
* basicConsume(String queue, boolean autoAck,
Consumer callback)
* 1. queue:队列名称
* 2. autoAck:是否自动确认
* 3. callback:回调对象
*/
channel.basicConsume("work_queues",true,consumer);
//关闭资源?不要
}
}
第二个消费者代码 Consumer_WorkQueues2:
package com.dxw.consumer;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* 消费者:接收消息
*/
public class Consumer_WorkQueues2 {
public static void main(String[] args) throws
IOException, TimeoutException {
//1、创建连接工厂
ConnectionFactory factory = new
ConnectionFactory();
//2. 设置参数
factory.setHost("localhost");//ip 默认值 localhost
factory.setPort(5672); //端口 默认值 5672
factory.setVirtualHost("/dxw");//虚拟机 默认/
factory.setUsername("dxw");//用户名 默认guest
factory.setPassword("1234");//密码 默认guest
//3. 创建连接 Connection
Connection connection = factory.newConnection();
//4. 创建Channel
Channel channel = connection.createChannel();
//5、创建队列
/*
* 参数解释:
* queueDeclare(String queue,
* boolean durable,
* boolean exclusive,
* boolean autoDelete,
* Map<String, Object> arguments)
* 1. queue:队列名称
* 如果没有一个名字叫hello_world的队列,则会创建该
队列,如果有则不会创建
* 2. durable:是否持久化,当mq重启之后,队列中消息还在
* 3. exclusive:
* 是否独占。只能有一个消费者监听这队列
* 当Connection关闭时,是否删除队列
* 4. autoDelete:是否自动删除。当没有Consumer时,自
动删除掉
* 5. arguments:参数。
*/
channel.queueDeclare("work_queues",true,false,false,null)
;
//6、接收消息
Consumer consumer = new DefaultConsumer(channel){
/*
回调方法,当收到消息后,会自动执行该方法
1. consumerTag:标识
2. envelope:获取一些信息,交换机,路由key...
3. properties:配置信息
4. body:数据
*/
@Override
public void handleDelivery(String consumerTag,
Envelope envelope, AMQP.BasicProperties properties, byte[]
body) throws IOException {
/*System.out.println("consumerTag:"+consumerTag);
System.out.println("Exchange:"+envelope.getExchange());
System.out.println("RoutingKey:"+envelope.getRoutingKey(
));
System.out.println("properties:"+properties);*/
System.out.println("body:"+new
String(body));
}
};
/*
* 参数解释:
* basicConsume(String queue, boolean autoAck,
Consumer callback)
* 1. queue:队列名称
* 2. autoAck:是否自动确认
* 3. callback:回调对象
注意:先启动两个消费者,然后再启动生产者,然后观察两个生产者控制台输出
3、Pub/Sub订阅模式
1、模式介绍
在订阅模型中,多了一个 Exchange 角色,而且过程略有变化:
⚫ P:生产者,也就是要发送消息的程序,但是不再发送到队列中,而是
发给X(交换机)
⚫ C:消费者,消息的接收者,会一直等待消息到来
⚫ Queue:消息队列,接收消息、缓存消息
⚫ Exchange:交换机(X)。一方面,接收生产者发送的消息。另一方
面,知道如何处理消息,例如递交给某个特别队 列、递交给所有队列、
*/
channel.basicConsume("work_queues",true,consumer);
//关闭资源?不要
}
}
注意 : 先启动两个消费者 , 然后再启动生产者 , 然后观察两个生产者控制台输出

 

手动推送MQ消息队列是指应用程序主动将数据发送到消息队列服务的过程,这一过程通常用于在分布式系统中处理异步通信、解耦组件间的依赖、负载均衡以及事务一致性等问题。 ### 实现步骤: 1. **选择消息队列服务**:首先需要选择一个适合您需求的消息队列服务,如RabbitMQ、Kafka、Apache Pulsar 或RocketMQ 等,每个服务都有其特定的特点和使用场景。 2. **安装并配置服务器**:按照所选消息队列服务的文档指导完成安装和基本配置工作。这包括设置监听端口、创建所需用户权限、调整性能参数等。 3. **编写生产者代码**:在应用程序中编写生产者代码,该代码负责将消息发布到指定的队列或主题。一般包含以下几个关键部分: - **初始化连接**:建立与消息队列服务器的连接。 - **创建信道**:在连接上创建一个信道,用于后续的读取或写入操作。 - **声明交换机**:对于基于主题模式的消息队列,需要先声明一个交换机,并绑定到相应的队列。 - **发布消息**:通过生产者API将消息内容放入队列中。可以设定消息的持久化、优先级、TTL(存活时间)、序列号等属性。 - **关闭资源**:完成消息发布后,记得关闭信道和连接,释放资源。 4. **验证消息送达**:通过监控工具或测试脚本检查消息是否成功到达预期的队列,并确认接收方能够接收到消息。 ### 示例代码片段(使用RabbitMQ Java API): ```java import com.rabbitmq.client.Connection; import com.rabbitmq.client.Channel; public class ManualPushMessage { private static final String QUEUE_NAME = "my_queue"; public static void main(String[] args) throws Exception { // 获取连接 Connection connection = RabbitMQUtils.getConnection(); Channel channel = connection.createChannel(); try { // 声明队列 channel.queueDeclare(QUEUE_NAME, false, false, false, null); // 发布消息 String message = "Hello, Message Queue!"; channel.basicPublish("", QUEUE_NAME, null, message.getBytes()); System.out.println(" [x] Sent '" + message + "'"); } finally { // 关闭通道和连接 channel.close(); connection.close(); } } } ``` ### 相关问题: 1. **如何选择合适的消息队列服务**? 2. **消息队列的服务端部署与集群配置**? 3. **消费消息的最佳实践是什么**?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

God Zhang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值