rocketmq starter学习笔记

290 阅读4分钟

前言

  • spring cloud提供的stream模块,本人不太推崇。 首先,虽然其目的是屏蔽底层不同mq实现细节,但引入了新的抽象,增大了开发者的理解门槛和难度,以及问题排查难度。

其次,当未来需要替换消息中间件时,也无法达到低成本(少改或不改代码)切换的目的。对于线上运行系统,替换消息中间件难度和工作量都极大,如消息迁移、发布期间两套mq并行和兼容、producer和consumer两端的兼容、大量微服务应用配合改造等等,远远不止是业务开发端的改造。何况业务开发端也有工作量,即便不修改代码,也要修改依赖、修改配置项、测试验证发布上线等。

因此,基于实用角度考虑,对于中小型团队,个人还是建议直接使用rocketmq-spring-boot-starter。

  • 对于初学者来说,github.com/apache/rock… 下的rocketmq-spring-boot-samples,是最好的代码示例。这也是笔者的选择。

生产者

主要是通过RocketMQTemplate提供api给开发者调用。 绝大部分业务场景下,默认使用一个name server,对应一个RocketMQTemplate实例即可。但是官方还是支持多name server的,参见org.apache.rocketmq.samples.springboot.ExtRocketMQTemplate。 RocketMQTemplate提供的功能汇总如下:

syncSend/syncSendOrderly系列重载函数

同步发送mq,即发送成功才返回。

参数功能描述
消息参数支持传org.springframework.messaging.Message或其他任何类型的payload
timeout等待超时的时间(单位:毫秒)
Collection messages批量发送消息
delayLevel支持发送延时消息
hashKey支持顺序消息,保证相同hashKey的消息发送到同一个队列中。参看www.iocoder.cn/RocketMQ/me…
/支持事务性消息。具体下方备注

备注:早期的LocalTransactionExecuter虽然使用起来最简单,但可靠性不足,已Deprecated,将于5.0.0版本删除。官方提供了TransactionListener接口供开发者自行实现事务性消息,可靠性交由开发者保证。官方示例org.apache.rocketmq.samples.springboot.ProducerApplication.TransactionListenerImpl仅供参考,不可直接用于分布式生产环境,改造中的几个参考点:

  1. transaction id的生成,可以使用id生成器中间件或数据库自增;
  2. transaction id和transaction status映射关系的保存,可以选择各种持久化方案,如db、redis等;
  3. 参数Object arg可以是DML代码片段(如Runnable),在executeLocalTransaction中执行。成功,则保存上述映射关系,返回COMMIT;失败,则直接返回ROLLBACK;
  4. 对于可靠性要求高的场景,回查方法checkLocalTransaction一定要规范实现。

sendOneWay系列重载函数

如函数注释所言,调用性能很高(不等待ack到达即return),但只能用于可靠性要求不高的场景,如日志搜集。

/**
 * Similar to <a href="https://en.wikipedia.org/wiki/User_Datagram_Protocol">UDP</a>, this method won't wait for
 * acknowledgement from broker before return. Obviously, it has maximums throughput yet potentials of message loss.
 * <p>
 * One-way transmission is used for cases requiring moderate reliability, such as log collection.
 *
 * @param destination formats: `topicName:tags`
 * @param message {@link org.springframework.messaging.Message}
 */
public void sendOneWay(String destination, Message<?> message) {
}

asyncSend/asyncSendOrderly系列重载函数

支持异步发送,监听回调SendCallback。

sendAndReceive系列重载函数

同步发送并等待接收consumer的返回消息。如DefaultMQProducer的函数注释所言,

/**
 * Send request message in synchronous mode. This method returns only when the consumer consume the request message and reply a message. </p>
 *
 * <strong>Warn:</strong> this method has internal retry-mechanism, that is, internal implementation will retry
 * {@link #retryTimesWhenSendFailed} times before claiming failure. As a result, multiple messages may potentially
 * delivered to broker(s). It's up to the application developers to resolve potential duplication issue.
 * 
 @return reply message
 */
@Override
public Message request(final Message msg, final long timeout) throws RequestTimeoutException, MQClientException,
    RemotingException, MQBrokerException, InterruptedException {

}

返回类型支持泛型:

ProductWithPayload<String> replyGenericObject = rocketMQTemplate.sendAndReceive(
        genericRequestTopic,
        "request generic", 
        new TypeReference<ProductWithPayload<String>>() {}.getType(),
        30000,
        2
);

异步发送,监听回调RocketMQLocalRequestCallback。

/**
 * Send request message in asynchronous mode. </p> This method returns immediately. On receiving reply message,
 * <code>rocketMQLocalRequestCallback</code> will be executed. </p>
 *
 * @param destination formats: `topicName:tags`
 * @param message {@link org.springframework.messaging.Message} the message to be sent.
 * @param rocketMQLocalRequestCallback callback that will invoked when reply message received.
 * @param hashKey needed when sending message orderly
 * @param timeout send timeout in millis
 * @param delayLevel message delay level(0 means no delay)
 * @return
 */
public void sendAndReceive(String destination, Message<?> message,
    RocketMQLocalRequestCallback rocketMQLocalRequestCallback, String hashKey, long timeout, int delayLevel) {

消费者

consumer接口有2个:RocketMQListener和RocketMQReplyListener,接口函数onMessage的参数类型可以是MessageExt/Message/payload的类型。 注解ocketMQMessageListener,支持按tag过滤或sql过滤,支持指定name server,ConsumeMode,MessageModel等。 MessageExtConsumer L42只消费启动以来的新增消息。