# 配置 Broker 的IP地址
echo "brokerIP1=192.168.215.140" > broker.conf
# 启动 Broker 和 Proxy
docker run -d \
--name rmqbroker \
--network rocketmq \
-p 10912:10912 -p 10911:10911 -p 10909:10909 \
-p 8080:8080 -p 8081:8081 \
-e "NAMESRV_ADDR=rmqnamesrv:9876" \
-v /root/rocketmq/broker.conf:/home/rocketmq/rocketmq-5.3.1/conf/broker.conf \
apache/rocketmq:5.3.1 sh mqbroker --enable-proxy \
-c /home/rocketmq/rocketmq-5.3.1/conf/broker.conf
# 验证 Broker 是否启动成功
docker exec -it rmqbroker bash -c "tail -n 10 /home/rocketmq/logs/rocketmqlogs/proxy.log"
可视化控制台
docker run -d --name rocketmq-dashboard --network rocketmq -e "JAVA_OPTS=-Drocketmq.namesrv.addr=rmqnamesrv:9876" -p 8101:8080 -t apacherocketmq/rocketmq-dashboard:latest
客户端依赖
<dependency>
<groupId>org.apache.rocketmqgroupId>
<artifactId>rocketmq-clientartifactId>
<version>${rocketmq.version}version>
dependency>
生产者和主题的关系为多对多关系,即同一个生产者可以向多个主题发送消息,对于平台类场景如果需要发送消息到多个主题,并不需要创建多个生产者;同一个主题也可以接收多个生产者的消息,以此可以实现生产者性能的水平扩展和容灾。
RocketMQ提供了三种消息发送模式:同步发送,异步发送,单向发送。
同步发送是指消息发送方发出一条消息后,会在收到服务端同步响应之后才发下一条消息的通讯方式。
应用场景
对消息可靠性较高的场景,可以保证发送成功后才继续业务逻辑处理。
代码示例
/**
* 同步发送
*/
public class SyncProducer {
public static void main(String[] args) throws Exception {
//Instantiate with a producer group name.
DefaultMQProducer producer = new DefaultMQProducer("producerGroup1");
// Specify name server addresses.
producer.setNamesrvAddr(MqConstant.DEFAULT_NAMESRVADDR);
//Launch the instance.
producer.start();
for (int i = 0; i < 100; i++) {
//Create a message instance, specifying topic, tag and message body.
Message msg = new Message(MqConstant.SIMPLE_TOPIC ,
"TagA" ,
("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET)
);
//Call send message to deliver message to one of brokers.
//收到broker确认后该方法才会返回SendResult
SendResult sendResult = producer.send(msg);
System.out.printf("%s%n", sendResult);
}
//Shut down once the producer instance is not longer inuse.
producer.shutdown();
}
}
异步发送是指发送方发出一条消息后,不等服务端返回响应,接着发送下一条消息的通讯方式。云消息队列 RocketMQ 版的异步发送,需要您实现异步发送回调接口(SendCallback)。消息发送方在发送了一条消息后,不需要等待服务端响应即可发送第二条消息。发送方通过回调接口接收服务端响应,并处理响应结果。
应用场景
异步发送一般用于链路耗时较长,对响应时间较为敏感的业务场景。对实时性要求较高。但希望获得发送结果的通知
代码示例
/**
* 异步发送
*/
public class AsyncProducer {
public static void main(String[] args) throws Exception {
//Instantiate with a producer group name.
DefaultMQProducer producer = new DefaultMQProducer("producerGroup1");
// Specify name server addresses.
producer.setNamesrvAddr(MqConstant.DEFAULT_NAMESRVADDR);
//Launch the instance.
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(MqConstant.SIMPLE_TOPIC,
"TagA",
("Hello RocketMQ"+i).getBytes(RemotingHelper.DEFAULT_CHARSET));
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 {
//Instantiate with a producer group name.
DefaultMQProducer producer = new
DefaultMQProducer("producerGroup1");
// Specify name server addresses.
producer.setNamesrvAddr(MqConstant.DEFAULT_NAMESRVADDR);
//Launch the instance.
producer.start();
for (int i = 0; i < 100; i++) {
//Create a message instance, specifying topic, tag and message body.
Message msg = new Message(MqConstant.SIMPLE_TOPIC,
"TagA",
("Hello RocketMQ " +i).getBytes(RemotingHelper.DEFAULT_CHARSET)
);
//Call send message to deliver message to one of brokers.
//没有返回值也就是不需要broker确认
producer.sendOneway(msg);
}
//Wait for sending to complete
Thread.sleep(5000);
producer.shutdown();
}
}
过滤的含义指的是将符合条件的消息投递给消费者,而不是将匹配到的消息过滤掉。
topic是对消息的高层分类,tag是在topic基础上对消息更细粒度的分类
交易生产者 分别向订单服务、物流服务和支付服务发送消息
/**
* 交易服务生产者
*/
public class TradeProducer {
public static void main(String[] args) throws Exception {
DefaultMQProducer producer = new DefaultMQProducer("trade-producer-group");
producer.setNamesrvAddr(MqConstant.DEFAULT_NAMESRVADDR);
producer.start();
String[] tags = new String[]{MqConstant.PAY_TAG, MqConstant.LOGISTICS_TAG, MqConstant.ORDER_TAG};
for (int i = 0; i < 15; i++) {
Message msg = new Message(MqConstant.TRADE_TOPIC,
tags[i % tags.length],
tags[i % tags.length].getBytes(RemotingHelper.DEFAULT_CHARSET));
SendResult sendResult = producer.send(msg);
System.out.printf("%s%n", sendResult);
}
producer.shutdown();
}
}
物流服务消费者 只消费物流tag的消息
/**
* 物流服务消费者
*/
public class LogisticsConsumer {
public static void main(String[] args) throws MQClientException {
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("LogisticsConsumer");
consumer.setNamesrvAddr(MqConstant.DEFAULT_NAMESRVADDR);
consumer.subscribe(MqConstant.TRADE_TOPIC , MqConstant.LOGISTICS_TAG);
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
ConsumeConcurrentlyContext context) {
System.out.printf("%s Receive New Messages: %s %n",
Thread.currentThread().getName(),
msgs);
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
consumer.start();
}
}
支付服务消费者 只消费订单tag消息
/**
* 支付服务消费者
*/
public class PaymentConsumer {
public static void main(String[] args) throws MQClientException {
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("PaymentConsumer");
consumer.setNamesrvAddr(MqConstant.DEFAULT_NAMESRVADDR);
consumer.subscribe(MqConstant.TRADE_TOPIC , MqConstant.PAY_TAG);
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
ConsumeConcurrentlyContext context) {
System.out.printf("%s Receive New Messages: %s %n",
Thread.currentThread().getName(),
msgs);
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
consumer.start();
}
}
交易成功率分析服务 订阅支付和订单消息
/**
* 交易成功率分析服务
*/
public class TransactionSuccessRateAnalysisConsumer {
public static void main(String[] args) throws MQClientException {
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("TransactionSuccessRateAnalysisConsumer");
consumer.setNamesrvAddr(MqConstant.DEFAULT_NAMESRVADDR);
consumer.subscribe(MqConstant.TRADE_TOPIC , MqConstant.PAY_TAG+" || "+MqConstant.ORDER_TAG);
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
ConsumeConcurrentlyContext context) {
System.out.printf("%s Receive New Messages: %s %n",
Thread.currentThread().getName(),
msgs);
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
consumer.start();
}
}
实时计算服务 订阅trade-topic所有消息
/**
* 实时计算服务 订阅trade-topic所有消息
*/
public class RealtimeComputingConsumer {
public static void main(String[] args) throws MQClientException {
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("RealtimeComputingConsumer");
consumer.setNamesrvAddr(MqConstant.DEFAULT_NAMESRVADDR);
consumer.subscribe(MqConstant.TRADE_TOPIC , "*" );
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
ConsumeConcurrentlyContext context) {
System.out.printf("%s Receive New Messages: %s %n",
Thread.currentThread().getName(),
msgs);
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
consumer.start();
}
}
@Slf4j
public class ClusterModel1 {
public static void main(String[] args) throws MQClientException {
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("cluster_consume_group");
consumer.setNamesrvAddr(MqConstant.DEFAULT_NAMESRVADDR);
consumer.subscribe(MqConstant.CONSUME_TEST_TOPIC, "TagA");
// 消费模式 默认是集群模式(负载均衡模式)
consumer.setMessageModel(MessageModel.BROADCASTING);
// 注册回调函数,处理消息
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
try {
for (MessageExt msg : msgs) {
String topic = msg.getTopic();
String tags = msg.getTags();
String msgBody = new String(msg.getBody());
log.info("消息消费成功:{}", "topic:" + topic + " tags:" + tags + " 消息内容:" + msgBody);
}
} catch (Exception e) {
log.info("消息消费失败:{}", e.getMessage());
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
// 最后才启动消费者
consumer.start();
log.info("消费者启动成功... clientId:"+consumer.buildMQClientId());
}
}