网上抄的。博主做了个小工具sandbox
法二:
producer.setNamesrvAddr("192.168.xx.xx:9876;192.168.yy.16y:9876");
try {
// 设置实例名称
producer.setInstanceName("producer_broadcast");
---------------实践到公司项目时踩坑:
1.公司maven在云效,虽然我deploy配置都正确,不过给我整了个没权限。找架构上传。本地insatll时因为IDEA仓库配在另一个盘,眼花没看清,以为install咋没起效
2.启动报错,其他地方也有叫producer重名了,还好那个地方没啥用,把它名改了,没动用的很多的mq,呼呼。
3.启动报错,sandbox一个类用到的包没有。昨天在家玩咋没这事啊。 先不管了,不知冲突还是咋,直接在公司项目手动重复导一次
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>${cglib.version}</version>
</dependency>
启动正常了。
NettyDecoder: decode exception TooLongFrameException: Adjusted---- 原来是 netty使用FrameDecoder 解码 并没有把 一个协议包的内容读完 ,就调用了后面的业务逻辑代码,造成业务逻辑在解析 包的内容时长度不够---黏包?
【解决】:这个mq有没测过啊?[后知:这不是mq服务器地址,是mq控制台地址。。。]有毒,换个mq就好了!还好贵司mq服务器多。
4.@Test 启动报错了
Caused by: java.lang.VerifyError: class net.sf.cglib.core.DebuggingClassWriter overrides final method org.objectweb.asm.ClassWriter.visit(IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;
解决:从pom中分析可知道:asm出现了两个不同的版本,所以把asm 5.2这个版本移除即可
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<!-- 切换log4j2日志读取 -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
<exclusion>
<artifactId>asm</artifactId>
<groupId>org.ow2.asm</groupId>
</exclusion>
</exclusions>
</dependency>
---------------------------------------------------------------------------------------
多个服务器的Consumer倒没有这个问题。
(-----待验证。因为rocketmq虽一个进程jvm但不会注册为同一个Consumer吧?(2022年2月25日错,要得),所以,不存在 " 需要设置不同的instanceName[ producer.setInstanceName(instanceName);"] 的问题,更用不到sandbox
)还是设置了吧: consumer.setInstanceName(env+"-ib-kq");
待测一、配置时注册不同的自定义监听器(待测:或者用注解的方式实现),然后启动就好了吧
implements MessageListenerConcurrently
@Autowired
private MQConsumeMsgListenerConcurrently mqMessageListenerProcessor;
consumer.registerMessageListener(mqMessageListenerProcessor);
return consumer;
--------------------------
@PostConstruct
public void defaultMQPushConsumer() {
try {
consumer.start();
} catch (MQClientException e) {
LOGGER.error("===consumer start 异常,groupName:{},namesrvAddr:{}",
consumer.getConsumerGroup(),consumer.getNamesrvAddr(), e);
}
}catch (Exception e) {
//todo
}
--------------------------
@Component
public class MQConsumeMsgListenerConcurrently implements MessageListenerConcurrently {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
待测二、也可如此yml配置 namesrvAddr ;
namesrvAddr: 172.18.10.211:9866;172.16.16.985:9866 # 多个时,以;隔开
补充:
如果消费一个服务器的多个topic也简单:
// 订阅多个主题
// consumer.subscribe(topicName, "*");
// consumer.subscribe(topicName+";"+"test-ks-hik-server-face", "*");
consumer.subscribe(topicOa, "*");
consumer.subscribe(topicFromIbms, "*");
========启动顺序(存疑?:按道理@Bean>方法上@Autowired/@PostConstruct那种注册方式也是最后的【比如,定时任务也是此注解运行后查的数据库,和mq逻辑一样呀,定时任务两年了咋从没出现过数据库未好查不到数据呢?说明mq启动收到60条但消费成功5条的问题定位不一定在此】,毕竟都是注入到Spring)(防止消费时,数据库还没连?消费异常)
换用注解方式消费
@Component
@RocketMQMessageListener(topic = "${rocketmq.topics.topic.name}",consumerGroup = "${rocketmq.consumer.groupName}",maxReconsumeTimes = 6)
public class MQConsumeMsgListenerConcurrently implements RocketMQListener<MessageExt> {
@Override
public void onMessage(MessageExt messageExt) {
//这时候延迟消费就不是return false,而是抛异常了?
@Override
public void onMessage(MessageExt messageExt) {
MqSwitchEntity mqSwitchEntity = mqSwitchService.getMqSwitchByTopicAndTag(topicName,"sendRecordMsg");
if(MqConstant.SWITCH_ON.equalsIgnoreCase(mqSwitchEntity.getSwitchStatus())){
String logStr = StrUtil.format("触发mq消费开关 topic:{} ,tag :{},稍后消费;", topicName, "sendRecordMsg");
logger.info(logStr);
// mqIdempotent.serializeToRedis();
throw new RuntimeException(logStr);
}
[SpringBoot 启动时的运行方法](SpringBoot 启动时的运行方法_如来神掌十八式的博客-CSDN博客_springboot启动时执行)????
implements CommandLineRunner(实现CommandLineRunner接⼝的类会在Spring IOC容器加载完毕后执⾏,适合预加载类及其它资源;也可以使⽤ApplicationRunner,使⽤ ⽅法及效果是⼀样的)