rocketmq

rocketmq-starter

  • 快速接入RocketMQ
  • 支持多数据源接入
  • 支持普通消息,顺序消息,事务消息,重试消息,延时消息
  • 支持集群模式,广播模式。

说明

(一)application.yml配置说明

参数名含义是否必填
namesrv-addr注册中心地址
group-id消费组消费者必须填写
access-key访问秘钥
secret-key访问秘钥
scope会做逻辑上的隔离,如果怕和别人topic冲突可以加上这个字段
message-modelCLUSTERING-集群消费模式,BROADCASTING-广播消费模式否(默认集群模式)
orderedtrue-有序消息,false-无序消息否(默认无序消息)
tstrue-事务消息,false-普通消息否(默认不开启分布式事务)
consumer-retry-count消费者失败或超时重试次数否(默认16次)

(二)消息体支持的类型

参数名含义
JSONJson
String字符串(Json也可以用Json字符串方式)
Binary二进制
Object对象

快速接入

前置准备

引入Maven依赖

<dependency>
    <groupId>com.yichehui.framework</groupId>
    <artifactId>ych-rocketmq-starter</artifactId>
    <version>1.0.0-SNAPSHOT</version>
</dependency>

应用场景:一个消费组,一个消息类型(普通消息/顺序消息/事务消息/广播消息)下,生产或消费一个或者多个Topic

(一)普通消息

(1)application.yml

ych:
  mq:
    rocket:
      group-id: CONSUMER-GROUP  #消费组
      namesrv-addr: 10.168.4.141:9876;10.168.4.143:9876  #注册中心地址
      consumer-retry-count: 1  #重试次数
      access-key: rocketmqak  #秘钥ak
      secret-key: rocketmqsk  #秘钥sk

(2)消息生产者


import com.yichehui.rocketmq.mq.producer.ProduceMessage;
import com.yichehui.rocketmq.mq.producer.Producer;
import com.yichehui.rocketmq.mq.producer.SendResultDetail;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class PushEnumController {
    @Autowired
    private Producer producer;

    @GetMapping("/send")
    public SendResultDetail send() {
        String jsonString  = "{\n" +
                "    \"msg\":\"hello\"\n" +
                "}";
        ProduceMessage message = ProduceMessage.fromString("wwwww", "", jsonString);
        return producer.send(message);
    }
}

此处ProduceMessage message = ProduceMessage.fromString(“wwwww”, “”, json);中的wwwww为Topic名,代表向wwwww这个Topic发送消息。 “” 为tag(rocketmq二级topic)此处为空,jsonString为发送的消息具体内容。

除了fromString之外还提供fromJSON,fromBinary,fromObject等不同类型的消息体格式

(3)消费者


import com.yichehui.rocketmq.mq.consumer.ConsumeMessage;
import com.yichehui.rocketmq.mq.consumer.MessageListener;
import org.springframework.stereotype.Component;

@Component
public class RocketmqMessageListener implements MessageListener {
    // 只有多数据源情况才需要值
    @Override
    public String getId() {
        return "";
    }
    // 监听的topic名
    @Override
    public String getTopic() {
        return "wwwww";
    }
    // 只有有tag情况下才需要值
    @Override
    public String getTag() {
        return "";
    }

    @Override
    public void process(ConsumeMessage message) {
        System.out.println("topic: => " + message.getTopic());
        System.out.println("message: => " + message.getValueAsJson());
        // 此处模拟异常,将会进行重试
        int i = 1 / 0;
    }
}

此处return “wwwww”;中的wwwww为Topic名,代表监听这个Topic
getValueAsJson代表以Json对象格式接收,除此之外也封装了其他类型、
int i = 1 / 0; 模拟抛出异常,由于consumer-retry-count: 1 所以会进行一次重试

(二)顺序消息

(1)application.yml

ych:
  mq:
    rocket:
      group-id: CONSUMER-GROUP #消费组
      namesrv-addr: 10.168.4.141:9876;10.168.4.143:9876 #注册中心
      consumer-retry-count: 10 #重试次数
      access-key: rocketmqak #秘钥ak
      secret-key: rocketmqsk #秘钥sk
      ordered: true #顺序消息需标注

(2)消息生产者

原理:同一个RocketMQ Queue消息有序;根据此处传的 shardingKey,SDK会对RocketMQ Queue数取余,不同shardingKey发送到指定RocketMQ Queue,
以下示例模拟8个用户"生成订单", “下单”, "支付"三个步骤,对于每个用户三个步骤有序

import com.yichehui.rocketmq.mq.producer.ProduceMessage;
import com.yichehui.rocketmq.mq.producer.Producer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class Demo {
@Autowired
private Producer producer;

    public void send() {
        List<String> orderStep = Arrays.asList("生成订单", "下单", "支付");
      
        for (int userId = 0; userId < 8; userId++) {
            for (int j = 0; j <= 2; j++) {
                ProduceMessage message = ProduceMessage.fromString("wwwww", "", "用户" + userId + orderStep.get(j));
                message.setShardingKey(userId);
                SendResultDetail sendResultDetail = producer.send(message);
                System.out.println(sendResultDetail);
            }
        }
    }
}

(2)消息消费者


import com.yichehui.rocketmq.mq.consumer.ConsumeMessage;
import com.yichehui.rocketmq.mq.consumer.MessageListener;
import org.springframework.stereotype.Component;

@Component
public class RocketmqMessageListener implements MessageListener {

    @Override
    public String getId() {
        return "";
    }

    @Override
    public String getTopic() {
        return "wwwww";
    }

    @Override
    public String getTag() {
        return "";
    }

    @Override
    public void process(ConsumeMessage message) {
        System.out.println(message.getValueAsString());
    }
}

(三)事务消息

RocketMQ 3.0.8 以及之前的版本支持分布式事务消息;
RocketMQ 3.0.8 之后删除分布式事务功能(付费商用:阿里云ONS服务);
RocketMQ 4.0.0 开始 apache孵化,但是也不支持分布式事务消息;
RocketMQ 4.3.0 开始支持分布式事务消息。
建议使用RocketMQ 4.7.1版本
回查时间间隔可以在RocketMQ Broker配置
事务消息QPS会降低

使用时需要指本地事务与事务回查逻辑
对于某个事务会有UNKNOW ,COMMIT,ROLLBACK 状态
本地事务UNKNOW或者无响应会触发回查逻辑,直到COMMIT(提交)或ROLLBACK (回滚)

(1)application.yml

ych:
  mq:
    rocket:
      group-id: CONSUMER-GROUP  #消费组
      namesrv-addr: 10.168.4.141:9876;10.168.4.143:9876  #连接地址
      access-key: rocketmqak #秘钥ak
      secret-key: rocketmqsk #秘钥sk
      ts: true #如果是事务消息需要添加

(2)消息生产者

import com.yichehui.rocketmq.mq.producer.ProduceMessage;
import com.yichehui.rocketmq.mq.producer.Producer;
import com.yichehui.rocketmq.mq.producer.SendResultDetail;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class PushEnumController {
    @Autowired
    private Producer producer;

    @GetMapping("/send/{id}")
    public SendResultDetail queryEnumList(@PathVariable Long id) {
        ProduceMessage message = ProduceMessage.fromString("wwwww", "", "" + id);
        return producer.send(message);
    }
}

(3)消费者


import com.yichehui.rocketmq.mq.consumer.ConsumeMessage;
import com.yichehui.rocketmq.mq.consumer.MessageListener;
import org.springframework.stereotype.Component;

@Component
public class RocketmqMessageListener implements MessageListener {

    @Override
    public String getId() {
        return "";
    }

    @Override
    public String getTopic() {
        return "wwwww";
    }

    @Override
    public String getTag() {
        return "";
    }

    @Override
    public void process(ConsumeMessage message) {
        System.out.println("topic: => " + message.getTopic());
        System.out.println("message: => " + message.getValueAsString());
    }
}

(4)本地事务与回查事务


import com.yichehui.rocketmq.mq.producer.YchTransactionListener;
import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageExt;
import org.springframework.stereotype.Component;

import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Date;

@Component
public class YchTransactionListenerImpl implements YchTransactionListener {

    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Override
    public LocalTransactionState executeLocalTransaction(Message message, Object o) {
        String sss = new String(message.getBody(), Charset.defaultCharset());
        if ("1".equals(sss)) {
            // new Date()为获取当前系统时间
            String dateTime = df.format(new Date());
            System.out.println("执行本地事务,模拟断电等异常" + dateTime);
            return LocalTransactionState.UNKNOW;
        } else if ("2".equals(sss)) {
            // new Date()为获取当前系统时间
            String dateTime = df.format(new Date());
            System.out.println("执行本地事务,模拟本地事务失败" + dateTime);
            return LocalTransactionState.ROLLBACK_MESSAGE;
        } else if ("3".equals(sss)) {
            String dateTime = df.format(new Date());
            System.out.println("执行本地事务,模拟本地事务成功" + dateTime);
            return LocalTransactionState.COMMIT_MESSAGE;
        }
        return LocalTransactionState.UNKNOW;
    }

    @Override
    public LocalTransactionState checkLocalTransaction(MessageExt messageExt) {
        String dateTime = df.format(new Date());
        System.out.println("模拟第回查成功" + dateTime);
        return LocalTransactionState.COMMIT_MESSAGE;
    }
}

(四)延时消息

开源版本的RocketMQ中,对延迟消息并不支持任意时间的延迟设定(商业版本中支持),而是只支持18个固定的延迟级别
1到18分别对应messageDelayLevel=1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h。

import com.yichehui.rocketmq.mq.producer.ProduceMessage;
import com.yichehui.rocketmq.mq.producer.Producer;
import com.yichehui.rocketmq.mq.producer.SendResultDetail;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class PushEnumController {
    @Autowired
    private Producer producer;

    @GetMapping("/send/{id}")
    public SendResultDetail queryEnumList(@PathVariable Long id) {
        ProduceMessage message = ProduceMessage.fromString("wwwww", "", "" + id);
        message.setDelayTimeLevelTime(1);
        return producer.send(message);
    }
}

(五)广播模式

广播模式先启动消费端后,任何实例都会被消费到
消费者只会监听启动之后收到的消息

(1)application.yml

ych:
  mq:
    rocket:
      group-id: CONSUMER-GROUP #消费组
      namesrv-addr: 10.168.4.141:9876;10.168.4.143:9876 #注册中心
      access-key: rocketmqak #秘钥ak
      secret-key: rocketmqsk #秘钥sk
      message-model: BROADCASTING  #广播模式

(2)消息生产者

import com.yichehui.rocketmq.mq.producer.ProduceMessage;
import com.yichehui.rocketmq.mq.producer.Producer;
import com.yichehui.rocketmq.mq.producer.SendResultDetail;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class PushEnumController {
    @Autowired
    private Producer producer;

    @GetMapping("/send/{id}")
    public SendResultDetail queryEnumList(@PathVariable Long id) {
        ProduceMessage message = ProduceMessage.fromString("wwwww", "", "" + id);
        return producer.send(message);
    }
}

(3)消息消费者

import com.yichehui.rocketmq.mq.consumer.ConsumeMessage;
import com.yichehui.rocketmq.mq.consumer.MessageListener;
import org.springframework.stereotype.Component;

@Component
public class RocketmqMessageListener implements MessageListener {

    @Override
    public String getId() {
        return "";
    }

    @Override
    public String getTopic() {
        return "wwwww";
    }

    @Override
    public String getTag() {
        return "";
    }

    @Override
    public void process(ConsumeMessage message) {
        System.out.println(message.getValueAsString());
    }
}

应用场景:一个或多个数据源,一个或多个消费组,一个或多个消息类型(普通消息/顺序消息/事务消息/广播消息)下,生产或消费一个或者多个Topic

(六)多数据源

id为数据源,此处模拟两个数据源,rocket-source-1为数据源1,发送事务消息。rocket-source-2为数据源2,发送顺序消息。

(1)application.yml

ych:
  mq:
    rocket:
      producers:
        producer-list: #生产者
          - id: rocket-source-1  #数据源1
            access-key: rocketmqak #秘钥ak
            secret-key: rocketmqsk #秘钥sk
            scope: dev #逻辑隔离
            group-id: CONSUMER-1 #消费者组
            ts: true #事务消息
            namesrv-addr: 10.168.4.141:9876;10.168.4.143:9876 #注册中心
          - id: rocket-source-2  #数据源2
            access-key: rocketmqak #秘钥ak
            secret-key: rocketmqsk  #秘钥sk
            scope: dev #逻辑隔离
            group-id: CONSUMER-2 #消费者组
            ordered: true #顺序消息
            namesrv-addr: 10.168.4.141:9876;10.168.4.143:9876 #注册中心
      consumers: #消费者
        consumer-list:
          - id: rocket-source-1  #数据源1
            access-key: rocketmqak #秘钥ak
            secret-key: rocketmqsk #秘钥sk
            scope: dev #逻辑隔离
            group-id: CONSUMER-1 #消费者组
            ts: true #事务消息
            namesrv-addr: 10.168.4.141:9876;10.168.4.143:9876 #注册中心
          - id: rocket-source-2   #数据源2
            access-key: rocketmqak #秘钥ak
            secret-key: rocketmqsk  #秘钥sk
            scope: dev #逻辑隔离
            group-id: CONSUMER-2 #消费者组
            ordered: true #顺序消息
            namesrv-addr: 10.168.4.141:9876;10.168.4.143:9876 #注册中心

(2)生产者

Producer producer = producerAssist.getProducerById(“rocket-source-1”) 代表此处使用rocket-source-1的数据源,将会发送事务消息

import com.yichehui.rocketmq.mq.producer.ProduceMessage;
import com.yichehui.rocketmq.mq.producer.Producer;
import com.yichehui.rocketmq.mq.producer.ProducerAssist;
import com.yichehui.rocketmq.mq.producer.SendResultDetail;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class PushEnumController {
    @Autowired
    private ProducerAssist producerAssist;

    @GetMapping("/send1")
    public SendResultDetail send1() {
        Producer producer = producerAssist.getProducerById("rocket-source-1");
        ProduceMessage message = ProduceMessage.fromString("rocket-source-1-topic", "", "hello-rocket-source-1");
        return producer.send(message);
    }

    @GetMapping("/send2")
    public SendResultDetail send2() {
        Producer producer = producerAssist.getProducerById("rocket-source-2");
        ProduceMessage message = ProduceMessage.fromString("rocket-source-2-topic", "", "hello-rocket-source-2");
        message.setShardingKey(1);
        return producer.send(message);
    }
}

(3) 第一个数据源消费

如果想消费rocket-source-1的数据源getId里 return "rocket-source-1"即可
@Override
public String getId() {
return “rocket-source-1”;
}

import com.yichehui.rocketmq.mq.consumer.ConsumeMessage;
import com.yichehui.rocketmq.mq.consumer.MessageListener;
import org.springframework.stereotype.Component;

/**
 * 第一个数据源消费
 */
@Component
public class RocketmqMessageListener implements MessageListener {

    @Override
    public String getId() {
        return "rocket-source-1";
    }

    @Override
    public String getTopic() {
        return "rocket-source-1-topic";
    }

    @Override
    public String getTag() {
        return "";
    }

    @Override
    public void process(ConsumeMessage message) {
        System.out.println("topic: => " + message.getTopic());
        System.out.println("message: => " + message.getValueAsString());
    }
}

(4) 第二个数据源消费

import com.yichehui.rocketmq.mq.consumer.ConsumeMessage;
import com.yichehui.rocketmq.mq.consumer.MessageListener;
import org.springframework.stereotype.Component;

/**
 * 第二个数据源消费
 */
@Component
public class RocketmqMessageListener2 implements MessageListener {

    @Override
    public String getId() {
        return "rocket-source-2";
    }

    @Override
    public String getTopic() {
        return "rocket-source-2-topic";
    }

    @Override
    public String getTag() {
        return "";
    }

    @Override
    public void process(ConsumeMessage message) {
        System.out.println("topic: => " + message.getTopic());
        System.out.println("message: => " + message.getValueAsString());
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值