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 消息队列

相关推荐
Allen Bright19 小时前
RabbitMQ中的普通Confirm模式:深入解析与最佳实践
分布式·rabbitmq
S-X-S19 小时前
集成RabbitMQ+MQ常用操作
rabbitmq
dzend19 小时前
Kafka、RocketMQ、RabbitMQ 对比
kafka·rabbitmq·rocketmq
小林想被监督学习1 天前
RabbitMQ 的7种工作模式
分布式·rabbitmq
wy02_2 天前
Linux下载RabbitMQ,并解决Github拒绝访问443的问题
linux·rabbitmq·github
浩哲Zhe3 天前
RabbitMQ
java·分布式·rabbitmq
Allen Bright3 天前
RabbitMQ中的Topic模式
分布式·rabbitmq
Allen Bright3 天前
Spring Boot 整合 RabbitMQ:手动 ACK 与 QoS 配置详解
spring boot·rabbitmq·java-rabbitmq
一路狂飙的猪3 天前
RabbitMQ的工作模型
分布式·rabbitmq
来一杯龙舌兰3 天前
【RabbitMQ】RabbitMQ保证消息不丢失的N种策略的思想总结
分布式·rabbitmq·ruby·持久化·ack·消息确认