RabbitMQ实战之消息队列Queue

本文详细介绍了RabbitMQ中常见的消息队列类型,包括Hello World、Work Queues、Publish/Subscribe、Routing、Topics和RPC。通过示例代码展示了如何实现消息的生产与消费,探讨了消息确认、公平分发、路由模式和通配符模式等关键概念,旨在帮助读者深入理解RabbitMQ的工作原理。
摘要由CSDN通过智能技术生成

 
 我的上一篇RabbitMQ初识文章:RabbitMQ实战之初识篇
 RabbitMQ官方讲解教程(推荐学习):RabbitMQ Tutorials
 RabbitMQ-Tutorials官方GitHub代码仓库(多种语言均有):rabbitmq-tutorials
 

=》RabbitMQ常用的几种Queue(消息队列)教程

          我的实验是基于 [ JDK1.8 + Maven + IDEA ],所以基于Maven的基础上以下队列项目的workspace需要引入如下的 pom.xml 中的依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.xxx</groupId>
    <artifactId>RabbitMQ</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <!-- configuration配置跟JDK版本相关联 -->
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <!-- rabbitmq客户端依赖 -->
        <dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <version>5.7.1</version>
        </dependency>
        
        <!-- rabbitmq客户端依赖(上面的)依赖于slf4j依赖 -->
        <!-- 但在生产环境中(线上)应该引入更加成熟的日志依赖库,如Logback日志库 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.26</version>
        </dependency>
    </dependencies>
</project>

 

一、 Hello World

     Hello World
  P:Producer - 生产者:生产msg并发布到队列(queue)中
  C:Consumer - 消费者:保持运行 && 监听队列 中的msg,拉取msg并消费它

  • 生产者发送msg到mq的代码:
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

public class Send {
   

    private static final String QUEUE_NAME = "hello";

    public static void main(String[] args) throws Exception {
   
        // mq的连接工厂
        ConnectionFactory factory = new ConnectionFactory(); 
        // mq的服务器地址,这里是本机IP 127.0.0.1
        // 也可以设置其他信息:端口port、用户名、密码passwd等
        factory.setHost("localhost"); 
        // 从factory中获取连接 + 在连接中创建管道 channel
        // channel: 完成工作的大多数API所在的位置
        try (Connection connection = factory.newConnection();
             Channel channel = connection.createChannel()) {
   
            // 在管道中声明连接的队列 queue
            // Declaring a queue is idempotent[声明队列是幂等的,仅当队列不存在时才创建]
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
            String message = "HELLO MQ-queue, i am hengx's Producer";
            // 发布(Publish) msg 到 queue
            channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
            System.out.println("[x] Send '" + message + "'");
        }
    }
}
  • 消费者从mq中拉取并消费msg的代码:
public class Recv {
   

    private final static String QUEUE_NAME = "hello";

    public static void main(String[] argv) throws Exception {
   
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();

        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
		// TODO
        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
   
            String message = new String(delivery.getBody(), "UTF-8");
            System.out.println(" [x] Received '" + message + "'");
        };
        // 从队列(queue)监听、拉取并消费(Consume) msg
        channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> {
    });
    }
}

运行生产者后管理界面查看:
mq
点击队列的名字即可查看详细的信息:
mq

 1) 为什么不使用try语句自动关闭管道Channel跟连接Connection呢?(即调用chanel.close();connection.close();)
      如果这样,我们的程序将继续运行,然而关闭了所有内容 (管道 + 连接) 并退出!这将很尴尬,因为我们希望在消费者 异步侦听消息到达 时,该过程保持有效

 2) queueDeclare() 参数解析:

     我的下一篇博文:channel.queueDeclare()参数解析
 

二、 Work queues

     work-queue
一个生产者,多个消费者 ;
一个msg只能被一个消费者消费
msg在消费者之间是共享的 ;

1. 目的:
        To avoid doing a resource-intensive(资源密集型) task immediately and having to wait for it to complete. Instead we schedule the task to be done later. [ 就是避免立即处理资源密集型的任务而是在后期处理它 ,异步处理达到削峰的目的],比如在一个HTTP短连接中要处理一个长时间的任务是不可能的,特别是在Web应用中.

  • 生产者代码:
public class Send_WorkQueue {
   

    private static final String QUEUE_NAME = "work-queue";

    public static void main(String[] args) throws Exception {
   
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        try (Connection connection = factory.newConnection();
             Channel channel = connection.createChannel()) {
   
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
            args = new String[]{
   "Java",".",".","."};
            String message = String.join(" ",args);
            // 发送20条消息到 mq
            for (int i=0;i<20;i++){
   
                channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
            }
            System.out.println("[x] Send '" + message + "'");
        }
    }
}
  • 消费者-1 代码:
public class Recv1_WorkQueue {
   
    private final static String QUEUE_NAME = "work-queue";
    private static int count = 0;

    public static void main(String[] argv) throws Exception {
   
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();

        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");

        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
   
            String message = new String(delivery.getBody(), "UTF-8");
            System.out.println(" [x1] Received '" + message + "'");
            try {
   
            	// 模拟耗时工作
                doWork(message);
            } catch (InterruptedException e) {
   
                e.printStackTrace();
            } finally {
   
                System.out.println("[x1] Done,count : " + (++count));
            }
        };
        // false关闭自动确认ack
        boolean autoAck = true; // acknowledgment is covered below
        // 监听队列,false表示手动返回完成状态,true表示自动
        channel.basicConsume(QUEUE_NAME, autoAck, deliverCallback, consumerTag -> {
    });
    }

    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值