RabbitMQ学习笔记

1消息队列基础

1.1同步异步

同步调用

  • 时效性强

  • 拓展性差

  • 性能下降

  • 级联失败

异步调用

  • 业务解耦,拓展性强

  • 无需等待,性能好

  • 故障隔离

  • 缓存信息,流量削峰填谷

  • 时效性差

  • 不确定执行是否成功

1.2MQ技术选型

2安装

2.1安装步骤

linux环境,用docker安装

  1. 下载rabbitmq镜像

    docker 复制代码
    docker pull rabbitmq:3.7.15
  2. 创建容器

    docker 复制代码
    docker run -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=123456 -v mq-plugins:/plugins --name rabbitmq --hostname myrabbitmq -p 15672:15672 -p 5672:5672 -d rabbitmq:3.7.15
  3. 查看容器

    docker 复制代码
    docker ps
  4. 配置管理页面插件

    docker 复制代码
    docker exec -it rabbitmq /bin/bash
    rabbitmq-plugins enable rabbitmq_management
  5. 访问管理页面ip:15672,账号密码为创建容器的RABBITMQ_DEFAULT信息

2.2架构和概念

  • publisher:消息发送者

  • consumer:消息消费者

  • queue:队列,负责存储消息

  • exchange:交换机,负责路由转发消息

  • virtual-host:虚拟主机,负责数据隔离

3Java客户端

3.1AMQP

高级消息队列协议

Spring AMQP:基于AMQP协议定义的一套API规范

3.2简单发送接收消息

rabbitmq管理页面创建队列testQueue

微服务项目,引入依赖

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

配置rabbitmq信息

yml 复制代码
spring:
  rabbitmq:
    host: ip
    port: 5672
    virtual-host: /
    username: username
    password: password

发送,用单元测试

java 复制代码
@SpringBootTest(classes = UserApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class SpringAmqpTest {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    void test() {
        String queue = "testQueue";
        String message = "hello";
        rabbitTemplate.convertAndSend(queue, message);
    }
}

接收

java 复制代码
@Component
public class MqListener {

    @RabbitListener(queues = "testQueue")
    public void listen(String message) {
        System.out.println("msg=" + message);
    }
}

3.3work模型

rabbitmq管理页面创建队列workQueue

多个消费者绑定到一个队列,加快消息处理速度

同一条消息只会被一个消费者处理

设置prefetch控制消费者预取消息数量

消费者配置

yml 复制代码
spring:
  rabbitmq:
    listener:
      simple:
        prefetch: 1 # 每次只能获取一条消息,处理完成才能获取下一条

发送

java 复制代码
    @Test
    void testWorkQueue() {
        String queue = "workQueue";
        for (int i = 1; i <= 50; i++) {
            String message = "hello" + i;
            rabbitTemplate.convertAndSend(queue, message);
        }
    }

接收

java 复制代码
    @RabbitListener(queues = "workQueue")
    public void listenWorkQueue1(String message) throws InterruptedException {
        System.out.println("listen1,msg=" + message);
        Thread.sleep(20);
    }

    @RabbitListener(queues = "workQueue")
    public void listenWorkQueue2(String message) throws InterruptedException {
        System.out.println("listen2,msg=" + message);
        Thread.sleep(200);
    }

listen1处理速度更快,因此处理消息数量更多

3.4交换机

3.4.1Fanout

广播模式,分发每个队列

rabbitmq管理页面创建队列q1,q2,绑定amq.fanout交换机

发送

java 复制代码
    @Test
    void testFanout() {
        String exchange = "amq.fanout";
        String message = "hello fanout";
        rabbitTemplate.convertAndSend(exchange, "", message);
    }

接收

java 复制代码
    @RabbitListener(queues = "q1")
    public void listenFanout1(String message) {
        System.out.println("listenfanout1,msg=" + message);
    }

    @RabbitListener(queues = "q2")
    public void listenFanout2(String message) {
        System.out.println("listenfanout2,msg=" + message);
    }

3.4.2Direct

定向路由,每个队列绑定交换机时设置一个routingKey,发送消息指定routingKey发送到指定队列

rabbitmq管理页面创建队列directQueue1,directQueue2,分别绑定amq.direct交换机,设置routingKey为direct1,direct2

发送

java 复制代码
    @Test
    void testDirect() {
        String exchange = "amq.direct";
        String message = "hello direct";
        String routingKey = "direct1";
        rabbitTemplate.convertAndSend(exchange, routingKey, message);
    }

接收

java 复制代码
    @RabbitListener(queues = "directQueue1")
    public void listenDirect1(String message) {
        System.out.println("listenDirect1,msg=" + message);
    }

    @RabbitListener(queues = "directQueue2")
    public void listenDirect2(String message) {
        System.out.println("listenDirect2,msg=" + message);
    }

3.4.3Topic

与Direct类似,routingKey可以是多个单词的列表,以.分割,routingKey可以指定通配符

  • #:0个或多个单词

  • *:一个单词

rabbitmq管理页面创建队列topicQueue1,topicQueue2,分别绑定amq.topic交换机,设置routingKey为topic1.#,topic2.#

发送

java 复制代码
    @Test
    void testTopic() {
        String exchange = "amq.topic";
        String message = "hello topic";
        String routingKey = "topic1.aaa";
        rabbitTemplate.convertAndSend(exchange, routingKey, message);
    }

接收

java 复制代码
    @RabbitListener(queues = "topicQueue1")
    public void listenTopic1(String message) {
        System.out.println("listenTopic1,msg=" + message);
    }

    @RabbitListener(queues = "topicQueue2")
    public void listenTopic2(String message) {
        System.out.println("listenTopic2,msg=" + message);
    }

3.5声明队列和交换机

3.5.1Bean配置

java 复制代码
@Configuration
public class FanoutConfig {
    @Bean
    public FanoutExchange fanoutExchange() {
        // 二选一
//        return ExchangeBuilder.fanoutExchange("myFanout");
        return new FanoutExchange("myFanout");
    }

    @Bean
    public Queue queue() {
        // 二选一
//        return QueueBuilder.durable("myQueue");
        return new Queue("myQueue");
    }

    @Bean
    public Binding binding(Queue queue, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(queue).to(fanoutExchange);
    }


}

3.5.2注解配置

java 复制代码
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "myQueue", durable = "true"),
            exchange = @Exchange(name = "myDirect", type = ExchangeTypes.DIRECT),
            key = {"red"}
    ))
    public void listenDirect(String message) {
        System.out.println("listenDirect,msg=" + message);
    }

3.6消息转换器

创建队列objectQueue

发送java对象或者map

引入依赖

xml 复制代码
        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-xml</artifactId>
        </dependency>

发送方、接收方添加消息转换器

java 复制代码
    @Bean
    public MessageConverter messageConverter() {
        return new Jackson2JsonMessageConverter();
    }

发送

java 复制代码
    @Test
    void testSendObject() {
        String queue = "objectQueue";
        Map<String, Object> map = new HashMap<>();
        map.put("id", "1");
        map.put("name", "hhh");
        rabbitTemplate.convertAndSend(queue, map);
    }

接收

java 复制代码
    @RabbitListener(queues = "objectQueue")
    public void listenObject(Map<String, Object> map) {
        System.out.println("listenObject,msg=" + map);
    }

其它消息队列知识看JavaGuide 消息队列

相关推荐
为什么不问问神奇的海螺呢丶21 小时前
n9e categraf rabbitmq监控配置
分布式·rabbitmq·ruby
m0_687399841 天前
telnet localhost 15672 RabbitMQ “Connection refused“ 错误表示目标主机拒绝了连接请求。
分布式·rabbitmq
Ronin3051 天前
日志打印和实用 Helper 工具
数据库·sqlite·rabbitmq·文件操作·uuid生成
坊钰3 天前
【Rabbit MQ】Rabbit MQ 的结构详解,传输机制!!!
java·rabbitmq
请叫我头头哥4 天前
SpringBoot进阶教程(八十九)rabbitmq长链接及域名TTL,多机房切换配置重连能力
rabbitmq·springboot
三水不滴4 天前
对比一下RabbitMQ和RocketMQ
经验分享·笔记·分布式·rabbitmq·rocketmq
JP-Destiny4 天前
后端-RabbitMQ
后端·消息队列·rabbitmq·java-rabbitmq
AC赳赳老秦5 天前
DeepSeek 辅助科研项目申报:可行性报告与经费预算框架的智能化撰写指南
数据库·人工智能·科技·mongodb·ui·rabbitmq·deepseek
Knight_AL5 天前
线程池满了怎么办?用 RabbitMQ 做任务补偿不丢失
分布式·rabbitmq·ruby
坊钰5 天前
【Rabbit MQ】Rabbit MQ 介绍
java·rabbitmq