RabbitMQ-初级

RabbitMQ

同步通讯的优缺点

优点:

·时效性较强,可以立即得到结果

缺点:

·耦合度高

·性能和吞吐能力下降

·有额外的资源消耗

·有级联失败问题

异步通讯

优点:

·不需要等待服务的结果

·性能提升,吞吐量提升

·服务间耦合度减少

·没有级联失败

·流量削峰(高并发场景下常用)

缺点:

·依赖于Broker的可靠性、安全性、吞吐能力架构复杂了

·业务没有明显的流程线,不好追踪管理

常见的 MQ (消息队列:事件队列)

消息队列的收发流程 (后面的框架封装了这些流程)
1,发消息:与消息中间件MQ服务器建立连接、创建通道(channel)、通过通道声明队列(queue)、利用通道向队列发送消息
2,收消息:建立连接、创建通道、声明队列、定义消费行为 handleDelivery(),利用管道将消费者与队列绑定

消费者:指的是消息接收方

SpringAMQP-(Advanced Message Queuing Protocol)

该框架提供:
1:自动声明队列,交换机,及绑定关系
2:基于注解的监听器模式,异步接收消息
3:封装了 RabbitTemplate 工具,用于发送消息

配置方式:

spring:
  rabbitmq:
    host: 127.0.0.1 # MQ服务器主机IP
    port: 5672 # 端口
    virtual-host: / # 虚拟主机
    username: guest # 用户名
    password: guest # 密码

当消息很多的时候,为了提高消息处理的速度,

可以通过控制消费者的预取的消息数量(prefecth),

让处理速度快的消费者可以处理更多的消息,而不会导致消息堆积

加入配置

spring:
  rabbitmq:
    listener:
      simple:
        prefetch: 1 # 每次只能获取一条消息,处理完成才能获取下一个消息
简单队列 Basic Queue

最普通的消息收发队列,可用性不太高,不够灵活,不推荐

示例(关键代码)
// 发送方 
@Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    public void testSimpleQueue() {
        // 队列名称
        String queueName = "simple.queue";
        // 消息
        String message = "hello, spring amqp!";
        // 发送消息
        rabbitTemplate.convertAndSend(queueName, message);
    }
    
-------------------------------------------------

// 接收方
@Component
public class SpringRabbitListener {

    @RabbitListener(queues = "simple.queue")
    public void listenSimpleQueueMessage(String msg) throws InterruptedException {
        System.out.println("spring 消费者接收到消息:【" + msg + "】");
    }
}
任务模型 Work Queue
多个消费者绑定到一个队列,同一条消息只会被一个消费者处理
示例

// 发送方
/**
     * workQueue
     * 向队列中不停发送消息,模拟消息堆积。
     */
@Test
public void testWorkQueue() throws InterruptedException {
    // 队列名称
    String queueName = "simple.queue";
    // 消息
    String message = "hello, message_";
    for (int i = 0; i < 50; i++) {
        // 发送消息
        rabbitTemplate.convertAndSend(queueName, message + i);
        Thread.sleep(20);
    }
}

-----------------------------------------

// 接收方

@RabbitListener(queues = "simple.queue")
public void listenWorkQueue1(String msg) throws InterruptedException {
        System.out.println("消费者1接收到消息:【" + msg + "】" + LocalTime.now());
        Thread.sleep(20);
        }

@RabbitListener(queues = "simple.queue")
public void listenWorkQueue2(String msg) throws InterruptedException {
        System.err.println("消费者2........接收到消息:【" + msg + "】" + LocalTime.now());
        Thread.sleep(200);
        }
发布-订阅

加入了交换机 Exchange

- Publisher:生产者,也就是要发送消息的程序,但是不再发送到队列中,而是发给X(交换机)
- Exchange:交换机,一方面,接收生产者发送的消息。另一方面,知道如何处理消息,例如递交给某个特别队列、递交给所有队列、或是将消息丢弃。到底如何操作,取决于Exchange的类型。Exchange有以下3种类型:
  - Fanout:广播,将消息交给所有绑定到交换机的队列
  - Direct:定向,把消息交给符合指定routing key 的队列
  - Topic:通配符,把消息交给符合routing pattern(路由模式) 的队列
- Consumer:消费者,与以前一样,订阅队列,没有变化
- Queue:消息队列也与以前一样,接收消息、缓存消息。
Fanout 扇出(类似广播)

特点:该模式下的消息收取都会由交换机管理,并通过广播的形式,传递给该交换机绑定的所有队列,即所有的消费者都能收到同样的消息

缺点:配置 bean 太过于繁琐。不推荐使用

Direct 路由模式

特点:该模式下的消息经交换机,只路由给指定的key对应的队列,其他的队列不可接收

示例(关键代码)
基于@Bean的方式声明队列和交换机比较麻烦,Spring还提供了基于注解方式来声明。

在consumer的SpringRabbitListener中添加两个消费者,同时基于注解来声明队列和交换机:

// 接收方
@RabbitListener(bindings = @QueueBinding(
    value = @Queue(name = "direct.queue1"),
    exchange = @Exchange(name = "itcast.direct", type = ExchangeTypes.DIRECT),
    key = {"red", "blue"}
))
public void listenDirectQueue1(String msg){
    System.out.println("消费者接收到direct.queue1的消息:【" + msg + "】");
}

@RabbitListener(bindings = @QueueBinding(
    value = @Queue(name = "direct.queue2"),
    exchange = @Exchange(name = "itcast.direct", type = ExchangeTypes.DIRECT),
    key = {"red", "yellow"}
))
public void listenDirectQueue2(String msg){
    System.out.println("消费者接收到direct.queue2的消息:【" + msg + "】");
}

--------------------------------------

// 发送方

@Test
public void testSendDirectExchange() {
        // 交换机名称
        String exchangeName = "itcast.direct";
        // 消息
        String message = "红色警报!日本乱排核废水,导致海洋生物变异,惊现哥斯拉!";
        // 发送消息
        rabbitTemplate.convertAndSend(exchangeName, "red", message);
        }
Topic

特点:该模式与 direct 相似,但是加入了通配符#、*、且路由routekey的名称都是一个或多个单词通过.连接组成

通配符规则:

#:匹配一个或多个词
*:匹配不多不少恰好1个词

举例:
item.#:能够匹配 item.spu.insert 或者 item.spu
item.*:只能匹配 item.spu
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值