rocketmq搭建和测试
准备工作搭建rocketmq:
1.命令启动mqbroker:mqbroker.cmd -n localhost:9876 autoCreateTopicEnable=true(保证topic自动创建)
2.启动mqnamesrv.cmd
生产者-客户端初始化:
package com.simoo.mq; import org.apache.rocketmq.client.exception.MQClientException; import org.apache.rocketmq.client.producer.DefaultMQProducer; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; @Component public class MsgProducer { @Value("${rocketmq.producer.producerGroup}") private String producerGroup; @Value("${rocketmq.namesrvAddr}") private String namesrvAddr; private DefaultMQProducer mqProducer; //调用方注入MsgProducer后 通过这个方法获取配置好的DefaultMQProducer public DefaultMQProducer getMqProducer() { return mqProducer; } @PostConstruct public void initMQ() { mqProducer = new DefaultMQProducer(producerGroup); mqProducer.setNamesrvAddr(namesrvAddr); mqProducer.setVipChannelEnabled(false); try { mqProducer.start(); } catch (MQClientException e) { e.printStackTrace(); } } @PreDestroy public void destory() { mqProducer.shutdown(); } }
yml配置:
server: port: 8081 rocketmq: namesrvAddr: 127.0.0.1:9876 producer: producerGroup: test_Producer timeout: 4000 #rocketmq: # producer: # groupName: springBootGroup # namesrvAddr: localhost:9876 # timeout: 4000 # #失败重试次数 # retryTimesWhenSendFailed: 2 # # consumer: # groupName: consumer_01 # namesrvAddr: 127.0.0.1:9876 # topics: TestTopic~TestTag||abcTag;MyTopic~* # consumeThreadMin: 10 # consumeThreadMax: 5 # consumeMessageBatchMaxSize: 1 spring: elasticsearch: host: 11.121.35.197 port: 9200 cluster-name: myEs7.7 nodeName: node-1 pool: 5 application: name: hc_1 redis: host: 127.0.0.1 port: 6379 jedis: pool: max-active: 8 max-wait: -1ms max-idle: 500 min-idle: 0 lettuce: shutdown-timeout: 0 activiti: #1.flase:默认值。activiti在启动时,对比数据库表中保存的版本,如果没有表或者版本不匹配,将抛出异常 #2.true: activiti会对数据库中所有表进行更新操作。如果表不存在,则自动创建 #3.create_drop: 在activiti启动时创建表,在关闭时删除表(必须手动关闭引擎,才能删除表) #4.drop-create: 在activiti启动时删除原来的旧表,然后在创建新表(不需要手动关闭引擎) database-schema-update: true # 检测历史信息表是否存在,activiti7默认不生成历史信息表,开启历史表 db-history-used: true # 历史记录存储等级 history-level: full check-process-definitions: false datasource: username: root password: 123456 #?serverTimezone=UTC解决时区的报错 url: jdbc:mysql://localhost:3306/activity?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&&nullCatalogMeansCurrent=true driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource #Spring Boot 默认是不注入这些属性值的,需要自己绑定 #druid 数据源专有配置 initialSize: 5 minIdle: 5 maxActive: 20 maxWait: 60000 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQuery: SELECT 1 FROM DUAL testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入 #如果允许时报错 java.lang.ClassNotFoundException: org.apache.log4j.Priority #则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j filters: stat,wall,log4j maxPoolPreparedStatementPerConnectionSize: 20 useGlobalDataSourceStat: true connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500 mvc: pathmatch: matching-strategy=ANT_PATH_MATCHER mybatis: type-aliases-package: nuc.ss.pojo mapper-locations: classpath:mapper/*.xml logging: # pattern: # console: "%d - %msg%n" level: root: info com.simoo: info file: path: D://projectDoc
生产者-controller发送消息:
package com.simoo.controller; import cn.hutool.core.date.DateUtil; import com.simoo.mq.MsgProducer; import org.apache.rocketmq.client.producer.SendResult; import org.apache.rocketmq.common.message.Message; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.Date; @RestController @RequestMapping("/mq") public class MqController { @Autowired private MsgProducer msgProducer; @RequestMapping("/send") public void sendMsg() throws Exception { //消息体 String msg = "我是消息队列" + DateUtil.format(new Date(), "yyyyMMdd HHmmss"); //包装成消息 Message message = new Message("test_producer1", "test", msg.getBytes()); //调用配置好的DefaultMQProducer发送消息 SendResult result = msgProducer.getMqProducer().send(message); System.out.println(result.getMessageQueue()); System.out.println(result.getMsgId()); } }
消费端--config:
package com.simoo.config; import com.simoo.listener.MqListener; import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; import org.apache.rocketmq.common.consumer.ConsumeFromWhere; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; /** * @Module rocketMq 配置类 * @Date 2022/10/30 10:36 * @Author by simoo */ @Component public class ConsumerMqConfig { public static final Logger LOGGER = LoggerFactory.getLogger(ConsumerMqConfig.class); @Value("${spring.application.name}") public String groupName; // 项目名 根据项目分组 @Value("${rocketmq.namesrvAddr}") public String namesrvAddr; // 注册的地址 //生产消息超时时间 private Integer producerTimeout = 5000; @Bean public DefaultMQPushConsumer mqPushConsumer() { DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(groupName); consumer.setNamesrvAddr(namesrvAddr); try { consumer.subscribe("test_producer1", "*"); // 偏移量 从最后开始消费 consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET); // 消费端最小显线程数 consumer.setConsumeThreadMin(1); // 最大线程数 consumer.setConsumeThreadMax(100); // Listener,主要进行消息的逻辑处理,监听topic,如果有消息就会立即去消费 consumer.registerMessageListener(new MqListener()); consumer.start(); LOGGER.info("rocketMq 消费端启动完成!!!!"); } catch (Exception e) { LOGGER.error("rocketMq 消费端启动失败!!!!", e); } return consumer; } }
消费端--listener:
package com.simoo.listener; import com.alibaba.fastjson.JSON; import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; import org.apache.rocketmq.common.message.MessageExt; import java.util.List; /** * @author: create by simoo * @version: v1.0 * @description: com.simoo.config * @date:2022/12/21 */ //@Configuration public class MqListener implements MessageListenerConcurrently { @Override public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext consumeConcurrentlyContext) { // 获取第一条消息,进行处理 try { if (msgs != null && msgs.size() > 0) { MessageExt messageExt = msgs.get(0); String msgBody = new String(messageExt.getBody(), "utf-8"); System.out.println("消费端接收消息为:" + msgBody); System.out.println("消息重试次数:" + messageExt.getReconsumeTimes()); } } catch (Exception e) { System.out.println("消息消费失败,请尝试重试!!!"); e.printStackTrace(); // 尝试重新消费,直接第三次如果还不成功就放弃消费,进行消息消费失败补偿操作 if (msgs.get(0).getReconsumeTimes() == 3) { System.out.println("消息记录日志:" + msgs); return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; } else { // 重试状态码,重试机制可配置 System.out.println("消息消费失败,请尝试重试!!!"); return ConsumeConcurrentlyStatus.RECONSUME_LATER; } } System.out.println("消费端消息消费成功!!!"); return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; } }