RocketMQ
-
简介
- 提供消息队列服务的中间件
- 消息生产、存储、消费
-
应用
- 限流削峰
- 异步解耦
- 数据收集
-
缺点
- 可用性降低
- 复杂性提高
- 一致性问题
-
MQ产品
- ActiveMQ
- RabbitMQ
- Kafka
- RocketMQ
-
协议
- JMS
- java消息服务
- STOMP
- 简单文本协议
- AMQP
- 统一消息服务应用层标准
- MQTT
- 即时通讯协议
- JMS
-
概念
- 消息
- message
- 必须属于某个topic
- 主题
- topic
- 包含多个消息
- 生产者可以生产多个主题
- 标签
- tag
- 队列
- queue
- 消息标识
- MessageId/key
- 消息
-
系统架构
- producer
- 消息生产者
- 生产者组
- producer group
- consumer
- 消息消费者
- 消费者组
- consumer group
- name server
- broker注册
- topic路由注册
- 路由注册
- 路由剔除
- 路由发现
- pull模型
- push模型
- long polling长轮询
- borker
- 消息中转
- 存储,转发
- producer
-
工作流程
- 启动NameServer,开始监听端接口,等待broker,producer,consumer连接
- 启动broker,与nameserver长连接
- 发送消息前,先创建topic,指定存储的broker
- producer与nameserver建立长连接,获取路由信息,选择一个queue,与队列所在的broker建立长连接并发送消息
- consumer与nameserver建立长连接,获取订阅topic的路由信息,获取对应的queue,与队列所在的broker建立长连接并消费消息
-
创建模式
- 集群
- broker
简单案例
- 依赖
<dependency>
<group>org.apacje.rocketmq</group>
<artifactId>rocketmq-client</artifactId>
<version>4.8.0</version>
</dependency>
public class Productor{
public static void main(String[] args){
// 谁来发
DefaultMQProducter producter = new DefaultMQProducter("group1");
// 发给谁
productor.setNamesrvAddr("xxx.xxx.xxx.xxx:xxx");
producter.start();
// 怎么发
// 发什么
String msg = "hello";
Message message = new Message("topic1","tag1",msg.getBytes());
SendResult sendResult = priducter.send(message);
// 发的结果
System.out.println(sendResult);
// 关闭连接
producer.shutdown();
}
}
public claass Consumer{
public static void main(String[] args){
// 谁来收
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("group1");
// 从哪里收
consumer.setNamesrvAddr("xxx.xxx.xxx.xxx:xxx");
// 监听哪个消息队列
consumer.ubscribe("topic1","*");
// 处理业务流程
consumer.registerMessageListener(new MessageListener(){
});
consumer.start();
}
}
功能
一对多
- 一个生产者多个消费者
// 谁来发
DefaultMQProducter producter = new DefaultMQProducter("group1");
// 发给谁
productor.setNamesrvAddr("xxx.xxx.xxx.xxx:xxx");
producter.start();
// 怎么发
// 发什么
for(int i=0;i<10;i++){
String msg = "hello "+i;
Message message = new Message("topic2","tag2",msg.getBytes());
SendResult sendResult = producter.send(message);
// 发的结果
System.out.println(sendResult);
}
// 关闭连接
producer.shutdown();
- 开启两个消费者
- 负载均衡模式
- 默认模式
- 同一组消费者一个消息只能被一个消费者消费
- 不同组消费者可以消费同一消息
- 广播模式
- 同一组每个消费者都可以获取全部消息
- 负载均衡模式
// 谁来收
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("group1");
// 从哪里收
consumer.setNamesrvAddr("xxx.xxx.xxx.xxx:xxx");
// 消费模式
consumer.setMessageModel(MessageModel.CLUSTERING);
// 监听哪个消息队列
consumer.ubscribe("topic2","*");
// 处理业务流程
consumer.registerMessageListener(new MessageListener(){
});
consumer.start();
同步消息&异步消息&单向消息
- 同步消息
- SendResult sendResult = producter.send(message);
- 立刻需要接收回执
- 异步消息
- producter.send(message,new SendCallback(){});
- 单向消息
- producter.sendOneway(message);
- 不需要回执
延时消息
- 延时消息
- message.setDelayTimeLevel(3);// 设置延时等级
- SendResult sendResult = producter.send(message);
批量消息
- 批量消息
- 需要相同topic
- 不能延时
- 总长不能超过4M
- 相同的waitStoreMsgOK
List<Message> msgList = new ArrayList<>();
Message message1 = new Message("topic2","tag2",msg.getBytes());
Message message2 = new Message("topic2","tag2",msg.getBytes());
Message message3 = new Message("topic2","tag2",msg.getBytes());
msgList.add(message1);
msgList.add(message2);
msgList.add(message3);
SendResult sendResult = producter.send(msgList);
tag过滤
- tag过滤
- consumer.subscribe(“topic1”,“tag1”)
- 监听tag1的消息
属性过滤
- 开启属性过滤
- enablePropertyFilter= true
- 消息属性
- message.putUserProperty(“age”,“18”);
- 属性过滤
- consumer.subscribe(“topic1”,MessageSelector.bySql(“age>16”))
springboot整合
- 依赖
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>2.0.3<version>
</dependency>
- 配置文件
rockermq:
name-server: xxx.xxx.xxx.xxx:xx
producer:
group: group1
- controller
@RestController
public class SendController{
@Autowired
RocketMQTemplate rocketMQTemplate;
@GetMapping("/send")
public String send(){
// 发送逻辑
//String msg = "xxx";
//rocketMQTemplate.convertAndSend("topic",msg);
User user = new User();
rocketMQTemplate.convertAndSend("topic",user);
// 同步消息
// SendResult result = rocketMQTemplate.syncSend("topic",user)
// 异步消息
// rocketMQTemplate.asyncSend("topic",user,new SendCallback(){
//
// },1000);
// 单向消息
// rocketMQTemplate.sendOneway("topic",user);
// 延时消息
// rocketMQTemplate。syncSend("topic",MessageBuilder.withPayload(msg).build(),2000,3);
// 批量消息
// rocketMQTemplate.syncSend("topic",mesList,1000,);
return "success";
}
}
public class User implements Serializable{
private String username;
private Integer age;
// set get
}
- 消费者
@Service
@RocketMQMessageListener(topic="topic1",consumerGroup="group1",selectorExpression="tag1||tag2")
// 属性过滤
// @RocketMQMessageListener(topic="topic1",consumerGroup="group1",selectorType=SelectorType.SQL92,selectorExpression="age>12")
// 广播模式
// messageMoedl = MessageModel.BROADCASTING
public class DemoConsumer implements RocketMQLinstener<User>{
PUBLIC VOID ONmESSAGE(User user){
System.out.println(user);
}
}
顺序消息
-
队列选择
-
生产者
// 订单消息
// 让同一订单的消息发送到同一队列
Message message = new Message("topic1","tag1",orderStep.toString().getBytes());
SendResult sendResult = producer.send(message,new MessageQueueSelector(){
// 队列选择
public MessageQueue select(List<MessageQueue> mqs,Message msg,Object arg){
// orderId
// 队列数
int size = mqs.size();
int orderId = (int)(orderStep.getOrderId());
int i = orderId%size;
return msq.get(i);
}
},null);
- 消费者
// 消费者起一个顺序监听器
consumer.registerMessageListener(new MessageListenerOrderly(){
public ConsumeOrderlyStatus consumeMessage(List<MessageExt> msgs,ConsumeOrderContext context){
for(Message msg:msgs){
System.out.println(msg);
byte[] body = msg.getBody();
System.out.println(new String(body));
}
return ConsumeOrderlyStatus.SUCCESS;
}
});
事务消息
TransactionMQProducer producer = new TransactionMQProducer("group1");
producer.setNamesrvAddr("xxx.xxx.xxx.xxx:xx");
producer.setTransactionListener(new TransactionLinstner(){
// 正常事务过程
public LocalTransactionState executeLocalTranscation(Message msg,Object msg){
// 处理消息
System.out.println("正常事务过程");
if(){
return LocalTransactionState.COMMIT_MESSAGE;// 正常
}else if(){
return LocalTransactionState.ROLLBACK_MESSAGE;// 回滚
}else{
return LocalTransactionState.UNKONOW;// 不确定状态,需要调用补偿
}
}
// 事务补偿过程
public LocalTransactionState checkLocalTransaction(Message msg){
System.out.println("事务补偿");
if(){
return LocalTransactionState.COMMIT_MESSAGE;// 正常
}else{
return LocalTransactionState.ROLLBACK_MESSAGE;// 回滚
}
}
});
producer.start();
// 发送消息
TranscationSendResult transcationSendResult = producer.sendMessageInTransaction(message,null);
// 不能关闭生产者