RocketMQ源码解析:消息发送流程

RocketMQ源码解析:消息发送流程_第1张图片

RocketMQ发送消息的三种方式

在RocketMQ中发送消息的方式有如下三种,同步发送,异步发送和单向发送。其中前2中发送方式是可靠的,因为会有发送是否成功的应答,而单向发送只管发不管发送是否成功

同步发送消息,用来发送比较重要的消息通知

public class SyncProducer {
     
	public static void main(String[] args) throws Exception {
     
    	// 实例化消息生产者Producer
        DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name");
    	// 设置NameServer的地址
    	producer.setNamesrvAddr("localhost:9876");
    	// 启动Producer实例
        producer.start();
    	for (int i = 0; i < 100; i++) {
     
    	    // 创建消息,并指定Topic,Tag和消息体
    	    Message msg = new Message("TopicTest" /* Topic */,
        	"TagA" /* Tag */,
        	("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */
        	);
        	// 发送消息到一个Broker
            SendResult sendResult = producer.send(msg);
            // 通过sendResult返回消息是否成功送达
            System.out.printf("%s%n", sendResult);
    	}
    	// 如果不再发送消息,关闭Producer实例。
    	producer.shutdown();
    }
}

异步发送消息,用来对响应时间敏感的业务场景,即发送端不能长时间等待Broker的响应

public class AsyncProducer {
     
    public static void main(
        String[] args) throws MQClientException, InterruptedException, UnsupportedEncodingException {
     

        DefaultMQProducer producer = new DefaultMQProducer("Jodie_Daily_test");
        producer.start();
        producer.setRetryTimesWhenSendAsyncFailed(0);

        int messageCount = 100;
        final CountDownLatch countDownLatch = new CountDownLatch(messageCount);
        for (int i = 0; i < messageCount; i++) {
     
            try {
     
                final int index = i;
                Message msg = new Message("Jodie_topic_1023",
                    "TagA",
                    "OrderID188",
                    "Hello world".getBytes(RemotingHelper.DEFAULT_CHARSET));
                // SendCallback异步接收发送的结果
                producer.send(msg, new SendCallback() {
     
                    @Override
                    public void onSuccess(SendResult sendResult) {
     
                        countDownLatch.countDown();
                        System.out.printf("%-10d OK %s %n", index, sendResult.getMsgId());
                    }

                    @Override
                    public void onException(Throwable e) {
     
                        countDownLatch.countDown();
                        System.out.printf("%-10d Exception %s %n", index, e);
                        e.printStackTrace();
                    }
                });
            } catch (Exception e) {
     
                e.printStackTrace();
            }
        }
        countDownLatch.await(5, TimeUnit.SECONDS);
        producer.shutdown();
    }
}

单向发送消息,用来不关心发送结果的场景,比如日志发送

public class OnewayProducer {
     
	public static void main(String[] args) throws Exception{
     
    	// 实例化消息生产者Producer
        DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name");
    	// 设置NameServer的地址
        producer.setNamesrvAddr("localhost:9876");
    	// 启动Producer实例
        producer.start();
    	for (int i = 0; i < 100; i++) {
     
        	// 创建消息,并指定Topic,Tag和消息体
        	Message msg = new Message("TopicTest" /* Topic */,
                "TagA" /* Tag */,
                ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */
        	);
        	// 发送单向消息,没有任何返回结果
        	producer.sendOneway(msg);

    	}
    	// 如果不再发送消息,关闭Producer实例。
    	producer.shutdown();
    }
}

RocketMQ五种消息类型

RocketMQ源码解析:消息发送流程_第2张图片

批量消息

List<Message> messageList = new ArrayList<>();
messageList.add(new Message(TOPIC_NAME, TAG_NAME, "id001", "hello world1".getBytes()));
messageList.add(new Message(TOPIC_NAME, TAG_NAME, "id002", "hello world2".getBytes()));
messageList.add(new Message(TOPIC_NAME, TAG_NAME, "id003", "hello world3".getBytes()));
producer.send(messageList);

批量消息即一次性发送多个消息,底层实现是把Collection转为MessageBatch对象发送出去

顺序消息

SendResult sendResult = producer.send(message, new MessageQueueSelector() {
     
    /**
     * @param mqs topic对应的message queue
     * @param msg send方法传入的message
     * @param arg send方法传入的orderId
     */
    @Override
    public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
     
        // 根据业务对象选择对应的队列
        Integer orderId = (Integer) arg;
        int index = orderId % mqs.size();
        return mqs.get(index);
    }
}, orderId);

事务消息

延迟消息

Message message = new Message(TOPIC_NAME, TAG_NAME, ("hello rocketmq " + i).getBytes(RemotingHelper.DEFAULT_CHARSET));
// 设置消息延迟级别为2,延时5s左右
message.setDelayTimeLevel(2);
SendResult sendResult = producer.send(message);

我们可以通过设置消息的延迟级别来让消息变为一个延迟消息,总共有18个延迟级别,对应的延迟时间如下

// MessageStoreConfig.java
private String messageDelayLevel = "1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h";

源码解析

Producer启动流程

Producer发送消息流程

参考博客

你可能感兴趣的:(RocketMQ,java,开发语言,后端)