学习笔记-RocketMQ

3 篇文章 0 订阅
2 篇文章 0 订阅

RocketMQ

  • 简介

    • 提供消息队列服务的中间件
    • 消息生产、存储、消费
  • 应用

    • 限流削峰
    • 异步解耦
    • 数据收集
  • 缺点

    • 可用性降低
    • 复杂性提高
    • 一致性问题
  • MQ产品

    • ActiveMQ
    • RabbitMQ
    • Kafka
    • RocketMQ
  • 协议

    • JMS
      • java消息服务
    • STOMP
      • 简单文本协议
    • AMQP
      • 统一消息服务应用层标准
    • MQTT
      • 即时通讯协议
  • 概念

    • 消息
      • message
      • 必须属于某个topic
    • 主题
      • topic
      • 包含多个消息
      • 生产者可以生产多个主题
    • 标签
      • tag
    • 队列
      • queue
    • 消息标识
      • MessageId/key
  • 系统架构

    • producer
      • 消息生产者
      • 生产者组
        • producer group
    • consumer
      • 消息消费者
      • 消费者组
        • consumer group
    • name server
      • broker注册
      • topic路由注册
      • 路由注册
      • 路由剔除
      • 路由发现
        • pull模型
        • push模型
        • long polling长轮询
    • borker
      • 消息中转
      • 存储,转发
  • 工作流程

    • 启动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);
// 不能关闭生产者
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值