1,事务消息代码实现
之前我们已经在讨论订单业务消息丢失问题中引出了事务消息,本内容我们就实际用代码来实现一下事务消息吧。
首先我们用原生代码来实现一下事务消息,下面是事务消息生产者TransactionProducer类的代码,具体代码解释已经用注释标明。
package com.huc.rocketmq.transaction;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.TransactionListener;
import org.apache.rocketmq.client.producer.TransactionMQProducer;
import org.apache.rocketmq.client.producer.TransactionSendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.common.RemotingHelper;
import java.io.UnsupportedEncodingException;
import java.util.concurrent.*;
/**
* @author liumeng
*/
public class TransactionProducer {
public static void main(String[] args)
throws MQClientException, UnsupportedEncodingException {
// 这里是一个自定义的接收RocketMQ回调的监听接口
TransactionListener transactionListener = new TransactionListenerImpl();
// 创建支持事务消息的Producer,并指定生产者组
TransactionMQProducer producer =
new TransactionMQProducer("testTransactionGroup");
// 指定一个线程池,用于处理RocketMQ回调请求的
ExecutorService executorService = new ThreadPoolExecutor(
2,
5,
100,
TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(2000),
new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setName("testThread");
return thread;
}
}
);
// 给事务消息生产者设置线程池
producer.setExecutorService(executorService);
// 给事务消息生产者设置回调接口
producer.setTransactionListener(transactionListener);
// 启动生产者
producer.start();
// 构造一条订单支付成功的消息
Message message = new Message(
"PayOrderSuccessTopic",
"testTag",
"testKey",
"订单支付消息".getBytes(RemotingHelper.DEFAULT_CHARSET)
);
// 将消息作为half消息发送出去
try {
TransactionSendResult result = producer.sendMessageInTransaction(message, null);
} catch (Exception e) {
// half消息发送失败
// 订单系统执行回滚逻辑,比如退款、关闭订单
}
}
}
针对于half消息发送失败的情况,是有可能一直接收不到消息发送失败的异常的,所以我们可以在发送half消息的时候,同时保存一份half消息到内存中,或者写入磁盘里,后台开启线程去检查half消息,如果超过10分钟都没有接到响应,就自动执行回滚逻辑。
那么如果half消息成功了,如何执行本地事务逻辑呢?这就要说到代码中自定义的回调监听接口TransactionListenerImpl类了,代码如下:
package com.huc.rocketmq.transaction;
import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.client.producer.TransactionListener;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageExt;
public class TransactionListenerImpl implements TransactionListener {
/**
* 如果half消息发送成功了,就会回调这个方法,执行本地事务
* @param message
* @param o