本次使用的是rocketmq4.3.0版本,
新建maven项目导入依赖
<dependencies>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>4.3.0</version>
</dependency>
</dependencies>
// 消息发送的状态
public enum SendStatus {
SEND_OK, // 发送成功
FLUSH_DISK_TIMEOUT, // 刷盘超时。当Broker设置的刷盘策略为同步刷盘时才可能出
现这种异常状态。异步刷盘不会出现
FLUSH_SLAVE_TIMEOUT, // Slave同步超时。当Broker集群设置的Master-Slave的复
制方式为同步复制时才可能出现这种异常状态。异步复制不会出现
SLAVE_NOT_AVAILABLE,
// 没有可用的Slave。当Broker集群设置为Master-Slave的
复制方式为同步复制时才可能出现这种异常状态。异步复制不会出现
}
发送同步消息
同步发送消息是指,Producer发出⼀条消息后,会在收到MQ返回的ACK之后才发下⼀条消息。该方式的消息可靠性最高,但消息发送效率太低。
代码示例
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.exception.RemotingException;
public class SyncProducer {
public static void main(String[] args) throws MQClientException, MQBrokerException, RemotingException, InterruptedException {
// 创建一个producer,参数为Producer Group名称
DefaultMQProducer producer = new DefaultMQProducer("pg");
// 指定nameServer地址
producer.setNamesrvAddr("127.0.0.1:9876");
// 设置当发送失败时重试发送的次数,默认为2次
producer.setRetryTimesWhenSendFailed(3);
// 设置发送超时时限为5s,默认3s
producer.setSendMsgTimeout(5000);
// 开启生产者
producer.start();
for (int i = 0; i < 10; i++) {
byte[] body = ("Hi," + i).getBytes();
Message message = new Message("someTopic", "someTag", body);
// 为消息指定key
message.setKeys("key-" + i);
SendResult sendResult = producer.send(message);
System.out.println(sendResult);
}
//关闭
producer.shutdown();
}
}
异步发送消息
异步发送消息是指,Producer发出消息后无需等待MQ返回ACK,直接发送下⼀条消息。该方式的消息可靠性可以得到保障,消息发送效率也可以。
import java.util.concurrent.TimeUnit;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.exception.RemotingException;
public class ASyncProducer {
public static void main(String[] args) throws MQClientException, MQBrokerException, RemotingException, InterruptedException {
// 创建一个producer,参数为Producer Group名称
DefaultMQProducer producer = new DefaultMQProducer("myTopicA_pg");
// 指定nameServer地址
producer.setNamesrvAddr("127.0.0.1:9876");
// 设置当发送失败时不进行重试。默认为2
producer.setRetryTimesWhenSendAsyncFailed(0);
// 指定新创建的Topic的Queue数量为2,默认为4
producer.setDefaultTopicQueueNums(2);
// 开启生产者
producer.start();
for (int i = 0; i < 10; i++) {
byte[] body = ("Hi," + i).getBytes();
Message message = new Message("myTopicA", "myTag", body);
// 为消息指定key
message.setKeys("key-" + i);
//异步发送
producer.send(message, new SendCallback() {
public void onSuccess(SendResult sendResult) {
System.out.println("发送成功:"+sendResult);
}
public void onException(Throwable e) {
e.printStackTrace();
}
});
}
//休眠一会,让异步发送完成。
TimeUnit.SECONDS.sleep(10);
//关闭
producer.shutdown();
}
}
单向发送消息
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.exception.RemotingException;
public class OnewayProducer {
public static void main(String[] args) throws MQClientException, RemotingException, InterruptedException {
DefaultMQProducer producer = new DefaultMQProducer("myTopicB_pg");
producer.setNamesrvAddr("127.0.0.1:9876");
producer.start();
for (int i = 0; i < 10; i++) {
byte[] body = ("Hi," + i).getBytes();
Message message = new Message("myTopicB", "myTag", body);
producer.sendOneway(message);
}
producer.shutdown();
}
}
发送顺序消息
全局有序需要设置Queue为1.,不为1,只能保证每个队列的有序
以下只能保证发送的顺序,消费的时候还应该使用顺序消费。不能多线程并发消费。
import java.util.List;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.MessageQueueSelector;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.remoting.exception.RemotingException;
public class OrderProducer {
public static void main(String[] args) throws MQClientException, MQBrokerException, RemotingException, InterruptedException {
DefaultMQProducer producer = new DefaultMQProducer("myTopicOrderA_pg");
producer.setNamesrvAddr("127.0.0.1:9876");
//全局有序需要设置为1
producer.setDefaultTopicQueueNums(1);
producer.start();
for (int i = 0; i < 10; i++) {
Integer orderId = i;
byte[] body = ("Hi," + i).getBytes();
Message message = new Message("myTopicOrderA", "myTag", body);
// 为消息指定key
message.setKeys(i+"");
//send()第三个参数值会传递给选择器的select()的第三个参数
SendResult sendResult = producer.send(message, new MessageQueueSelector() {
public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
//用key作为参数选择队列,当前是int类型,
// 如果string类型可使用hash算法。
String keys = msg.getKeys();
int key = Integer.parseInt(keys);
int index = key % mqs.size();
//使用arg作为参数选择队列的算法。
// Integer id = (Integer) arg;
// int index = id % mqs.size();
return mqs.get(index);
}
}, orderId);
System.out.println(sendResult);
}
producer.shutdown();
}
}
发送延时消息
当消息写入到Broker后,在指定的时长后才可被消费处理的消息,称为延时消息。
采用RocketMQ的延时消息可以实现 定时任务 的功能,而无需使用定时器。
典型的应用场景是,电商交易中超时未支付关闭订单的场景,12306平台订票超时未支付取消订票的场景。
默认级别:从1开始
private String messageDelayLevel = "1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h";
可以在broker.conf 自定义级别
或者消费的时候再次发送延时队列,达到再次延时的目的。
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
public class DelayProducer {
public static void main(String[] args) throws Exception {
DefaultMQProducer producer = new DefaultMQProducer("myTopicD_pg");
producer.setNamesrvAddr("127.0.0.1:9876");
producer.start();
for (int i = 0; i < 10; i++) {
byte[] body = ("Hi," + i).getBytes();
Message message = new Message("myTopicD", "myTag", body);
// 指定消息延迟等级为6级,即延迟2min
message.setDelayTimeLevel(6);
SendResult sendResult = producer.send(message);
// 输出消息被发送的时间
System.out.print(new SimpleDateFormat("mm:ss").format(new Date()));
System.out.println(", " + sendResult);
}
System.out.println("-----------------");
producer.shutdown();
}
}