rocketMQ
下载安装
官方网站
http://rocketmq.apache.org
GitHub
https://github.com/apache/rocketmq
Quick Start
Linux下使用Maven编译源码安装
Rocketmq4.6+需要jdk1.8环境编译和运行
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-226Ps8pF-1651752768151)(image-rocketMQ/image-20200218135102148.png)]
各版本要求
Version | Client | Broker | NameServer |
---|---|---|---|
4.0.0-incubating | >=1.7 | >=1.8 | >=1.8 |
4.1.0-incubating | >=1.6 | >=1.8 | >=1.8 |
4.2.0 | >=1.6 | >=1.8 | >=1.8 |
4.3.x | >=1.6 | >=1.8 | >=1.8 |
4.4.x | >=1.6 | >=1.8 | >=1.8 |
4.5.x | >=1.6 | >=1.8 | >=1.8 |
4.6.x | >=1.6 | >=1.8 | >=1.8 |
1.从GitHub上下载源码并上传到服务器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G7lajG1e-1651752768154)(image-rocketMQ/image-20200218134855528.png)]
2.在Linux上安装Maven
下载Maven
wget https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz
添加阿里云镜像
修改 maven/conf
目录下的 settings.xml
在 mirrors
节点下添加
<mirror>
<id>aliyun-maven</id>
<mirrorOf>*</mirrorOf>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
配置maven环境变量
修改 /etc/profile
export M2_HOME=/usr/local/maven
export PATH=$PATH:$M2_HOME/bin
配置java环境变量
export JAVA_HOME="/usr/java/jdk1.8.0_181-amd64"
export CLASS_PATH="$JAVA_HOME/lib"
export PATH=".$PATH:$JAVA_HOME/bin"
环境变量修完执行 source /etc/profile
立即生效
进入rocketmq主目录编译项目
mvn -Prelease-all -DskipTests clean install -U
3.启动nameserver
bin
目录下执行
./mqnamesrv
正常提示
4.启动Broker
./mqbroker -n localhost:9876
正常提示
5.测试消息发送
使用 tool.sh
脚本执行测试程序
在 bin
目录下执行
./tools.sh org.apache.rocketmq.example.quickstart.Producer
提示如下表示成功
6.接受消息
./tools.sh org.apache.rocketmq.example.quickstart.Consumer
控制台rocketmq-console编译安装
下载
https://github.com/apache/rocketmq-externals
中文指南
https://github.com/apache/rocketmq-externals/blob/master/rocketmq-console/doc/1_0_0/UserGuide_CN.md
上传到服务器并解压缩
编译
进入 rocketmq-console
目录
执行编译
mvn clean package -Dmaven.test.skip=true
启动
编译成功后在 rocketmq-console/target
目录下执行 rocketmq-console-ng-1.0.1.jar
启动时,直接动态添加 nameserver
地址或编辑 application.properties
添加属性
java -jar rocketmq-console-ng-1.0.1.jar --rocketmq.config.namesrvAddr=127.0.0.1:9876
启动成功后访问服务器8080端口即可
开启远程访问
1、开放9876端口和10911端口
2、修改conf/broker.conf,在最后加上
brokerIP1=xx.xx.xx.xx (自己的公网ip)
3、broker启动时需改成自己的公网ip
nohup sh mqbroker -n xx.xx.xx.xx:9876 -c ../conf/broker.conf
> /usr/local/rocketmq/logs/broker.log 2>&1 &
rocketMQ的作用
- 解耦
2. 限流
小demo
依赖
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>4.6.1</version>
</dependency>
同步消息发送
生产者
/**
* desc 消息发送方
* This class was created by马太吉 in 2022/5/5 12:39
*/
public class MQProducer {
public static void main(String[] args) throws Exception {
//创建一个生产者
DefaultMQProducer producer = new DefaultMQProducer("xxoo");
//设置nameser的地址
producer.setNamesrvAddr("192.168.174.128:9876");
//启动
producer.start();
//设置
producer.setSendMsgTimeout(150000);
// topic消息.将要发送到的地址
// body消息中的具体数据
// tag 是用来过滤消息,消息分组
// key 在消息发送之前还不知道message ID 这样就不好消费消息,可以设置一个key,用userid或者其他ID作为消息识别器来消费消息
Message message = new Message("top01", "第0条消息".getBytes());
Message message1 = new Message("top01", "第一条消息".getBytes());
Message message2 = new Message("top01", "第二条消息".getBytes());
Message message3 = new Message("top01", "第三条消息".getBytes());
ArrayList<Message> messages = new ArrayList<>();
messages.add(message1);
messages.add(message2);
messages.add(message3);
//同步消息发送
SendResult send = producer.send(message);
/*SendResult send1 = producer.send(message1);
SendResult send2 = producer.send(message2);
SendResult send3 = producer.send(message3);*/
producer.send(messages);
System.out.println(send);
}
}
消费者
/**
* desc
* This class was created by马太吉 in 2022/5/5 13:50
*/
public class MQConsumer {
public static void main(String[] args) throws Exception {
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("xxooConsumer");
//向谁获取消息
consumer.setNamesrvAddr("192.168.174.128:9876");
//每个consumer关注一个topic
// topic关注的消息的地址
// 过滤器* 表示不过滤
consumer.subscribe("top01", "*");
// 监听器
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
for (MessageExt msg : msgs) {
System.out.println(new String(msg.getBody()));
}
// 默认情况下这条消息只会被一个consumer消费到点对点
//message状态修改
// ack
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
consumer.start();
}
}
消费流程
其中这里的ack与producer无关
异步消息
/**
* desc 消息发送方,异步发送
* This class was created by马太吉 in 2022/5/5 12:39
*/
public class MQProducer1 {
public static void main(String[] args) throws Exception {
//创建一个生产者
DefaultMQProducer producer = new DefaultMQProducer("xxoo");
//设置nameser的地址
producer.setNamesrvAddr("192.168.174.128:9876");
//启动
producer.start();
//设置
producer.setSendMsgTimeout(150000);
// topic消息.将要发送到的地址
// body消息中的具体数据
Message message = new Message("top01", "第0条消息".getBytes());
//异步可靠消息
//不会阻塞,等待broker确认
// 采用事件监听方式接受broker确认
producer.send(message, new SendCallback() {
@Override
public void onSuccess(SendResult sendResult) {
//发送成功处理消息
System.out.println("消息发送成功");
System.out.println(sendResult);
}
@Override
public void onException(Throwable e) {
//如果发生异常case异常,尝试重投
// 哎者调整业务逻辑
System.out.println("消息发送失败" + e);
}
});
//单向传递消息
//只发送消息,不等待服务器响应,只发送请求不等待应答。此方式发送消息的过程耗时非常短,一般在微秒级别。
producer.sendOneway(message);
}
}
消息中的tag
消费者
public class MQConsumer {
public static void main(String[] args) throws Exception {
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("xxooConsumer");
//向谁获取消息
consumer.setNamesrvAddr("192.168.174.128:9876");
//每个consumer关注一个topic
// topic关注的消息的地址
// 过滤器* 表示不过滤
// tag selector在一个group中的消费者,都不能随便变,要保持统一
consumer.subscribe("top01", "TAG_A");
// 监听器
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
for (MessageExt msg : msgs) {
System.out.println(new String(msg.getBody()));
}
// 默认情况下这条消息只会被一个consumer消费到点对点
//message状态修改
// ack
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
consumer.start();
}
}
tagA生产者
public class MQProducer {
public static void main(String[] args) throws Exception {
//创建一个生产者
DefaultMQProducer producer = new DefaultMQProducer("xxoo");
//设置nameser的地址
producer.setNamesrvAddr("192.168.174.128:9876");
//启动
producer.start();
//设置
producer.setSendMsgTimeout(150000);
// topic消息.将要发送到的地址
// body消息中的具体数据
Message message = new Message("top01", "TAG_A", "第0条消息".getBytes());
//同步消息发送
SendResult send = producer.send(message);
System.out.println("TAG_A");
}
}
tagB生产者
public class MQProducer1 {
public static void main(String[] args) throws Exception {
//创建一个生产者
DefaultMQProducer producer = new DefaultMQProducer("xxoo");
//设置nameser的地址
producer.setNamesrvAddr("192.168.174.128:9876");
//启动
producer.start();
//设置
producer.setSendMsgTimeout(150000);
// topic消息.将要发送到的地址
// body消息中的具体数据
Message message = new Message("top01", "TAG_B", "第0条消息".getBytes());
//单向传递消息
producer.send(message);
System.out.println("TAG_B");
}
}
同一消费集群下消费不同tag标记的消息
生产者为消息中的tag一样
消费者如下
设置消费TAG_A
public class MQConsumer {
public static void main(String[] args) throws Exception {
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("xxooConsumer");
//向谁获取消息
consumer.setNamesrvAddr("192.168.174.128:9876");
//每个consumer关注一个topic
// topic关注的消息的地址
// 过滤器* 表示不过滤
// tag selector在一个group中的消费者,都不能随便变,要保持统一
consumer.subscribe("top01", "TAG_A");
// 监听器
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
for (MessageExt msg : msgs) {
System.out.println(new String(msg.getBody()));
}
// 默认情况下这条消息只会被一个consumer消费到点对点
//message状态修改
// ack
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
consumer.start();
}
}
设置消费TAG_B
public class MQConsumer1 {
public static void main(String[] args) throws Exception {
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("xxooConsumer");
//向谁获取消息
consumer.setNamesrvAddr("192.168.174.128:9876");
//每个consumer关注一个topic
// topic关注的消息的地址
// 过滤器* 表示不过滤
// tag selector在一个group中的消费者,都不能随便变,要保持统一
consumer.subscribe("top01", "TAG_B");
// 监听器
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
for (MessageExt msg : msgs) {
System.out.println(new String(msg.getBody()));
}
// 默认情况下这条消息只会被一个consumer消费到点对点
//message状态修改
// ack
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
consumer.start();
}
}
显示结果并没有一个消费者消费消息,生产者发送的消息已消费,但被过滤掉了。