使用RabbitMq推模式,消费者调用Dubbo服务踩坑记录
问题描述:
需求开发中需要使用到队列,且对实时性要求比较高,因此选择推模式,也就是mq主动向消费者投递消息,为此需要使用SimpleMessageListenerContainer,作为bean初始化注入ioc容器中,用来监听队列,配置了消费方法consumeTags(),消费者会调用该方法消费
@Configuration
public class RabbitReceiverConfig {
@Bean
public SimpleMessageListenerContainer qyWechat(ConnectionFactory connectionFactory, QyWeChatService qyWeChatService) {
// 配置在webapp.properties中,false表示不消费 true表示消费
boolean marketingMailConsume = Configurations.getBoolean("qy.wechat.consume", Configurations.isEnvPro());
if (!marketingMailConsume) {
return null;
}
MessageListenerAdapter messageListenerAdapter = new MessageListenerAdapter(qyWeChatService);
Map<String, String> args = Maps.newHashMap();
args.put(MQConfig.QUEUE_QY_WECHAT_SYNC, "consumeTags");
messageListenerAdapter.setQueueOrTagToMethodName(args);
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setQueueNames(MQConfig.QUEUE_QY_WECHAT_SYNC);
container.setPrefetchCount(0);
container.setMessageListener(messageListenerAdapter);
return container;
}
}
@DubboReference(version = Versions.DUBBO_SERVICE, timeout = 15000)
private LogService logService;
public void consumeTags(byte[] message) {
String messageStr = new String(message, StandardCharsets.UTF_8);
logService.xxx();
}
我的消费方法中,需要远程调用LogService服务的方法,这时候坑就出现了:
因为我前面实现推模式用的@Bean去初始化对象,而@DubboReference的初始化在这之后,这样就导致了我消费的时候,logService服务对象直接是null。
解决方法:
尝试了延迟引用(@DubboReference里面加check = false),懒加载(@Lazy),优先级(@Order),@DependOn都解决不了这个问题,最后想到了重新初始化
方法一:用QyWeChatService类实现InitializingBean接口的afterPropertiesSet()方法,重新初始化一次
@Override
public void afterPropertiesSet() throws Exception {
Object qyWechat = BeanProvider.getBean("qyWechat");
if (qyWechat == null)
return;
SimpleMessageListenerContainer container = (SimpleMessageListenerContainer) qyWechat;
Object messageListener = container.getMessageListener();
MessageListenerAdapter adapter = (MessageListenerAdapter) messageListener;
adapter.setDelegate(this);
}
后续新方案待补充。。。