关于RabbitMQ的工作模式

首先了解RabbitMQ的一些名词

  • Broker: 简单来说就是消息队列服务器实体
  • Exchange: 消息交换机,它指定消息按什么规则,路由到哪个队列
  • Queue: 消息队列载体,每个消息都会被投入到一个或多个队列
  • Binding: 绑定,它的作用就是把exchange和queue按照路由规则绑定起来
  • Routing Key: 路由关键字,exchange根据这个关键字进行消息投递
  • VHost: vhost 可以理解为虚拟 broker ,即 mini-RabbitMQ server。其内部均含有独立的 queue、exchange 和 binding 等,但最最重要的是,其拥有独立的权限系统,可以做到 vhost 范围的用户控制。当然,从 RabbitMQ 的全局角度,vhost 可以作为不同权限隔离的手段(一个典型的例子就是不同的应用可以跑在不同的 vhost 中)。
  • Producer: 消息生产者,就是投递消息的程序
  • Consumer: 消息消费者,就是接受消息的程序
  • Channel: 消息通道,在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务

RabbitMQ的工作模式
1, simple模式, 消息生产者直接将消息加入到队列中, 消息消费者监听消息队列, 如果队列有消息, 就消费掉, 消息被拿走后会自动删除, 但有可能消息并没有被消费者正确处理, 但消息却已经消失了, 造成消失丢失, 解决: 在消息正确处理后手动确认, 注意要即时, 否则会造成内存溢出

@Component
@RabbitListener(queuesToDeclare = @Queue("hello")) //接收hello队列的消息
public class HelloCustomer {
    @RabbitHandler
    public void receivel(String message) {
        System.out.println("message = "+message);
    }
}

2, work工作模式: 消息产生者将消息放入队列, 消费者可以有多个, 消费者1,消费者2同时监听同一个队列, 消息被生成后, C1 C2共同争抢当前的消息队列内容,谁先拿到谁负责消费消息, 默认情况是平均分配的, 问题: 高并发下会产生一个消息被多个消费者同时消费, 需要设置一个锁, 保证一条消息只能被一个消费者消费

@Component
public class WorkCustomer {
    /**
     * 多个消费者同时消费一个队列的信息
     * @param message
     */
    @RabbitListener(queuesToDeclare = @Queue("work"))
    public void receivel1(String message) {
        System.out.println("message1 = "+ message);
    }

    @RabbitListener(queuesToDeclare = @Queue("work"))
    public void receivel2(String message) {
        System.out.println("message2 = "+ message);
    }
}

3, fanout广播模式: 每个消费者监听自己的队列, 且每个队列绑定交换机, 生产者将消息发送给交换机, 由交换机将消息发送给绑定的队列

@Component
public class FanoutCustomer {
    //无路由key, 定义交换机类型为广播类型, 所有绑定交换机的消费者都可消费队列中信息
    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue,
                    exchange = @Exchange(value = "logs", type = "fanout")
            )
    })
    public void receivel1(String message) {
        System.out.println("message1 = " + message);
    }

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue,
                    exchange = @Exchange(value = "logs", type = "fanout")
            )
    })
    public void receivel2(String message) {
        System.out.println("message2 = " + message);
    }
}

4, routing路由模式: 此时队列与交换机的绑定需要指定一个Routing key, 而且交换机也不是将消息发送给所有绑定的队列, 而且发送给Routing key与交换机的Routing key匹配的队列

@Component
public class RouteCustomer {
    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue, //创建一个临时队列
                    exchange = @Exchange(value = "direct", type = "direct"),    //定义交换机的值和类型
                    key = {"info", "error"} //路由key, 只能接收固定路由key的信息
            )
    })
    public void receivel1(String message) {
        System.out.println("message1 = " + message);
    }

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue,
                    exchange = @Exchange(value = "direct", type = "direct"),
                    key = {"error"}
            )
    })
    public void receive2(String message) {
        System.out.println("message1 = " + message);
    }
}

5, topic 主题模式(路由模式的一种): 在路由模式的基础上添加了Routing key的通配符功能

@Component
public class TopicCustomer {
    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue,
                    exchange = @Exchange(value = "topic", type = "topic"),
                    key = "user.*"
            )
    })
    public void receivel(String message) {
        System.out.println("message = " + message);
    }
}

对应工作模式的发送消息的测试

@SpringBootTest(classes = yxy.cart.DemoApplication.class)
public class TestMQ {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    public void simple() {
        rabbitTemplate.convertAndSend("hello", "hello world");
    }

    @Test
    public void work() {
        for (int i = 0; i < 10; i++) {
            rabbitTemplate.convertAndSend("work", "work的消息");
        }
    }

    @Test
    public void fanout() {
        rabbitTemplate.convertAndSend("logs","", "fanout");
    }

    @Test
    public void route() {
        rabbitTemplate.convertAndSend("direct","info", "direct");
    }

    @Test
    public void topic() {
        rabbitTemplate.convertAndSend("topic","user.save", "topic");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值