四、RocketMQ发送普通消息、批量消息和延迟消息

Producer发送普通消息的方式

1.同步发送消息

同步消息代表发送端发送消息到broker之后,等待消息发送结果后,再次发送消息
四、RocketMQ发送普通消息、批量消息和延迟消息_第1张图片

实现步骤

  1. 创建生产端,声明在哪个生产组
  2. 注册NameServer地址
  3. 构建Message实体,指定topic、tag、body
  4. 启动生产端
  5. 发送消息
@Test
public void syncSend() throws MQBrokerException, RemotingException, InterruptedException, MQClientException {
    // 1.创建生产端,声明在哪个生产组
    DefaultMQProducer producer = new DefaultMQProducer("test_group");

    // 2.注册NameServer地址
    producer.setNamesrvAddr(NAME_SERVER_ADDR);

    // 3.构建Message实体,指定topic、tag、body
    Message message = new Message("test", "hello world".getBytes());

    // 4.启动生产端
    producer.start();

    // 5.发送消息
    SendResult sendResult = producer.send(message);
    System.out.println(sendResult.getSendStatus());
}

2.异步发送消息

异步消息代表发送端发送完消息后,会直接返回,但是可以注册一个回调函数,当broker将消息落盘后,回调这个回调函数
四、RocketMQ发送普通消息、批量消息和延迟消息_第2张图片

实现步骤

  1. 创建生产端,声明在哪个生产组
  2. 注册NameServer地址
  3. 构建Message实体,指定topic、tag、body
  4. 启动生产端
  5. 发送消息,并且实现SendCallback接口

注:这里必须等待异步返回,否则消费者无法消费成功

@Test
public void asyncSend() throws  RemotingException, InterruptedException, MQClientException {
    DefaultMQProducer producer = new DefaultMQProducer("test_group");
    producer.setNamesrvAddr(NAME_SERVER_ADDR);
    Message message = new Message("test", "tag-a","hello world".getBytes());
    producer.start();
    CountDownLatch countDownLatch = new CountDownLatch(1);
    // 发送消息,并且实现SendCallback接口
    producer.send(message, new SendCallback() {
        @Override
        public void onSuccess(SendResult sendResult) {
            countDownLatch.countDown();
            System.out.println("发送成功:" + sendResult.getSendStatus());
        }

        @Override
        public void onException(Throwable e) {
            countDownLatch.countDown();
            System.out.println("发送失败:" + e);
        }
    });
    countDownLatch.await();
}

3、发送单向消息

发送方只负责发送消息,不等待服务端返回响应且没有回调函数触发,即只发送请求不等待应答。此方式发送消息的过程耗时非常短

四、RocketMQ发送普通消息、批量消息和延迟消息_第3张图片

实现步骤

  1. 创建生产端,声明在哪个生产组
  2. 注册NameServer地址
  3. 构建Message实体,指定topic、tag、body
  4. 启动生产端
  5. 发送单向消息
@Test
public void sendOneWay() throws  RemotingException, InterruptedException, MQClientException {
    DefaultMQProducer producer = new DefaultMQProducer("test_group");
    producer.setNamesrvAddr(NAME_SERVER_ADDR);
    Message message = new Message("test","tag-a", "hello world".getBytes());
    producer.start();
    producer.sendOneway(message);
}

Producer发送批量消息

在对吞吐率有一定要求的情况下,Apache RocketMQ可以将一些消息聚成一批以后进行发送,可以增加吞吐率,并减少API和网络调用次数。

@Test
public void sendBatch() throws MQClientException, MQBrokerException, RemotingException, InterruptedException {
    DefaultMQProducer producer = new DefaultMQProducer("test-producer-group");
    producer.setNamesrvAddr(RocketMQConfig.NAME_SERVER_ADDR);

    // 构造批量消息
    List<Message> list = new ArrayList<>();
    list.add(new Message(RocketMQConfig.TEST_TOPIC, "hello world0".getBytes(Charset.defaultCharset())));
    list.add(new Message(RocketMQConfig.TEST_TOPIC, "hello world1".getBytes(Charset.defaultCharset())));
    list.add(new Message(RocketMQConfig.TEST_TOPIC, "hello world2".getBytes(Charset.defaultCharset())));
    producer.start();

    // 发送批量消息
    producer.send(list);
    producer.shutdown();
}

**注:**需要注意的是批量消息的大小不能超过 1MiB(否则需要自行分割),其次同一批 batch 中 topic 必须相同。

Producer发送延迟消息

Producer想要发送延迟消息,只要设置Message的DelayTimeLevel属性大于0即可。

RocketMQ无法随意设置延迟消息的延迟时间,只能根据延迟级别进行

延迟级别和延迟时间的对应关系

延迟级别 延迟时间 延迟级别 延迟时间
1 1s 10 6min
2 5s 11 7min
3 10s 12 8min
4 30s 13 9min
5 1min 14 10min
6 2min 15 20min
7 3min 16 30min
8 4min 17 1h
9 5min 18 2h
@Test
public void sendDelay() throws Exception {
    DefaultMQProducer producer = new DefaultMQProducer("test-producer-group");
    producer.setNamesrvAddr(RocketMQConfig.NAME_SERVER_ADDR);
    producer.start();

    Message message = new Message(RocketMQConfig.TEST_TOPIC, "hello world".getBytes(Charset.defaultCharset()));
    // 设置延迟级别
    message.setDelayTimeLevel(3);

    // 发送批量消息
    SendResult sendResult = producer.send(message);
    System.out.println(sendResult.getSendStatus());
    producer.shutdown();
}

延迟消息的原理

延迟消息并不会直接发送到指定的topic,而是发送到一个延迟消息对应的topic中

当延迟消息的时间到达后,在将消息发送到指定的topic中

延迟消息投递的流程

  1. producer端设置消息delayLevel延迟级别,消息属性DELAY中存储了对应了延时级别

  2. broker端收到消息后,判断延时消息延迟级别,如果大于0,则备份消息原始topic,queueId,并将消息topic改为延时消息队列特定topic(SCHEDULE_TOPIC),queueId改为延时级别的delayLevel-1

  3. mq服务端ScheduleMessageService中,为每一个延迟级别单独设置一个定时器,定时(每隔1秒)拉取对应延迟级别的消费队列

  4. 根据消费偏移量offset从commitLog中解析出对应消息

  5. 从消息tagsCode中解析出消息应当被投递的时间,与当前时间做比较,判断是否应该进行投递

  6. 若到达了投递时间,则构建一个新的消息,并从消息属性中恢复出原始的topic,queueId,并清除消息延迟属性,从新进行消息投递

你可能感兴趣的:(RocketMQ,rocketmq,中间件,java)