环境搭建
集群 单机 网上自己拉
遇到的坑:
-内存溢出 修改配置(测试机太小)
-多broker一条服务器启动 必须多个store路径 不同的端口 并且端口不要后面加一个数(本人就是加一个数 10911 第二个broker 10912 日志一直报找不到nameserver 其实是端口冲突了 )
-外网访问必须要写暴露外网IP
关闭namesrv服务:sh bin/mqshutdown namesrv
关闭broker服务 :sh bin/mqshutdown broker
# 查看nameServer日志
tail -500f ~/logs/rocketmqlogs/namesrv.log
# 查看broker日志
tail -500f ~/logs/rocketmqlogs/broker.log
使用
//导入MQ客户端依赖
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>4.4.0</version>
</dependency>
1.1 消息发送
消息发送者步骤
- 创建消费生产者producer,并制定生产者组名
- 制定nameserver地址
- 启动producer
- 创建消费对象,制定主题topic、Tag和消息体
- 发送消息
- 关闭生产者producer
1)发送同步消息
这种可靠性同步的发送方式使用的比较广泛,比如:重要的消息通知,短信通知。
// 1. 创建消费生产者producer,并制定生产者组名
DefaultMQProducer producer=new DefaultMQProducer("group1");
// 2. 制定nameserver地址
producer.setNamesrvAddr("120.27.146.116:9876;120.27.146.116:9877");
// 3. 启动producer
producer.start();
for (int i = 1; i <= 10; i++) {//模拟发送10次消息
// 4. 创建消费对象,制定主题topic、Tag和消息体
Message message=new Message("topic1","tag1",("Hello word"+i).getBytes(StandardCharsets.UTF_8));
// 5. 发送消息
SendResult send = producer.send(message);
System.out.println("%s%n"+ JSON.toJSONString(send));
}
// 6. 关闭生产者producer
producer.shutdown();
2)发送异步消息
异步消息通常用在对响应时间敏感的业务场景,即发送端不能容忍长时间地等待Broker的响应。
// 1. 创建消费生产者producer,并制定生产者组名
DefaultMQProducer producer=new DefaultMQProducer("group1");
// 2. 制定nameserver地址
producer.setNamesrvAddr("120.27.146.116:9876;120.27.146.116:9877");
// 3. 启动producer
producer.start();
for (int i = 1; i <= 10; i++) {//模拟发送10次消息
// 4. 创建消费对象,制定主题topic、Tag和消息体
Message message=new Message("topic1","tag2",("异步发送消息"+i).getBytes(StandardCharsets.UTF_8));
// 5. 异步发送消息 异步接收结果
producer.send(message, new SendCallback() {
@Override
public void onSuccess(SendResult sendResult) {
System.out.println("发送成功"+ JSON.toJSONString(sendResult));
}
@Override
public void onException(Throwable throwable) {
throwable.printStackTrace();
System.out.println("发送异常"+throwable.getMessage());
}
});
}
//让main线程睡眠6秒 不要提前关闭producer
Thread.sleep(6);
// 6. 关闭生产者producer
producer.shutdown();
3)发送单项消息
这种方式主要用在不特别关心发送结果的场景,例如日志发送
// 1. 创建消费生产者producer,并制定生产者组名
DefaultMQProducer producer=new DefaultMQProducer("group1");
// 2. 制定nameserver地址
producer.setNamesrvAddr("120.27.146.116:9876;120.27.146.116:9877");
// 3. 启动producer
producer.start();
for (int i = 1; i <= 10; i++) {//模拟发送10次消息
// 4. 创建消费对象,制定主题topic、Tag和消息体
Message message=new Message("topic1","tag3",("发送单项消息"+i).getBytes(StandardCharsets.UTF_8));
//发送单项消息
producer.send(message);
}
// 6. 关闭生产者producer
Thread.sleep(6);
producer.shutdown();
1.2 消费消息
消息消费者步骤
- 创建消费者consumer,制定消费者组名
- 指定nameserver地址
- 订阅主题Topic和Tag
- 设置回调函数,处理消息
- 启动消费者consumer
1)负载均衡模式(默认)
消费者采用负载均衡方式消费消息,多个消费者共同消费队列消息,每个消费者处理的消息不同
// 1. 创建消费者consumer,制定消费者组名
DefaultMQPushConsumer consumer=new DefaultMQPushConsumer("group1");
// 2. 指定nameserver地址
consumer.setNamesrvAddr("120.27.146.116:9876;120.27.146.116:9877");
// 3. 订阅主题Topic和Tag
consumer.subscribe("topic1","tag3"); //tag可以用*代替 消费所有tag
// 4. 设置回调函数,处理消息
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
list.forEach(a-> System.out.println(new String(a.getBody())));
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
// 5. 启动消费者consumer
consumer.start();
2)广播模式
消费者采用广播的方式消费消息,每个消费者消费的消息都是相同的
// 1. 创建消费者consumer,制定消费者组名
DefaultMQPushConsumer consumer=new DefaultMQPushConsumer("group1");
// 2. 指定nameserver地址
consumer.setNamesrvAddr("120.27.146.116:9876;120.27.146.116:9877");
// 3. 订阅主题Topic和Tag
consumer.subscribe("topic1","tag3"); //tag可以用*代替 消费所有tag
//设置消费模式 默认MessageModel.CLUSTERING 负载均衡模式
consumer.setMessageModel(MessageModel.BROADCASTING);//广播模式
// 4. 设置回调函数,处理消息
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
list.forEach(a-> System.out.println(new String(a.getBody())));
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
// 5. 启动消费者consumer
consumer.start();
1.3 顺序消息
消息有序指的是可以按照消息发送的顺序来消费(FIFO)。RocketMQ可以严格的保证消息有序,可以分为分区有序或全局有序。
顺序消费的原理解析:
在默认情况下消费发送会采取Round Robin 轮询方式把消息发送到不同的queue(分区队列);而消费消息时候从多个queue拉取消息,这种情况发送和消费是不能保证顺序。但是如果控制发送的顺序消息只能依次发送到同一个queue中,消费的时候只能一次从这个queue中拉取,则就保证了顺序。当发送和消费参与的queue只有一个,则是全局有序;如果多个queue参与,则为分区有序,即相对每个queue,消息都是有序的。