簡體   English   中英

Redis訂閱者無法與Redis發行者一起使用

[英]redis subscriber can't work with redis publisher

我現在正在使用Java設計Redis發布/訂閱系統,但遇到了問題。 我將向您顯示詳細信息:

發布者在這里:

public class RedisMessagePublisher implements MessagePublisher {

public RedisMessagePublisher(StringRedisTemplate redisTemplate,ChannelTopic topic)
{
    this.redisTemplate = redisTemplate;
    this.topic = topic;
}

private StringRedisTemplate redisTemplate;

private ChannelTopic topic;

@Override
public void publish(String message) {
    redisTemplate.convertAndSend(topic.getTopic(), message);
    }
}

發布者是正確的並且可以正常工作。

然后我們轉到訂戶類:

public class RedisMessageSubscriber implements MessageListener {

//action inspect here
private Action2<Message, byte[]> action;

public void setAction(Action2<Message, byte[]> action) {
    logger.info("action set");
    this.action = action;
}

private static Logger logger = LogManager.getLogger(RedisMessageSubscriber.class);

@Override
public void onMessage(Message message, byte[] bytes) {

    logger.info("===> redis subscribe message in <===");

    if (action != null)
        action.call(message, bytes);
    else
        logger.info("===> action is null <===");
    }
}

在訂閱者類中,我使用RxJava注入了Action,以便可以更輕松地使用它。

但是問題出在這里,當我發布發布者的消息之后,我可以將消息轉移到onMessage方法中,日志打印不是我期望的:

===> redis subscribe message in <===
===> action is null <===

我期望的是,當我發布新消息時,訂閱者收到了該消息並運行了我創建的操作。

我用來觸發以下發布者和訂閱者的服務:

@RestController("redispubsubcontroller")
@RequestMapping(value = "/redis")
public class redispubsubcontroller {

@Autowired
private RedisMessagePublisher redisMessagePublisher;

@Autowired
private RedisMessageSubscriber redisMessageSubscriber;

private static Logger logger = LogManager.getLogger(redispubsubcontroller.class);

@RequestMapping(value = "/publisher", method = {RequestMethod.GET})
public ApiResponse getConfig(String message,HttpServletRequest request,
                                            HttpServletResponse response) {

    redisMessageSubscriber.setAction(new Action2<Message, byte[]>() {
        @Override
        public void call(Message message, byte[] bytes) {
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                String result = objectMapper.readValue(message.getBody(), String.class);
                logger.info("receive:"+result);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    });

    redisMessagePublisher.publish(message);

    return new ApiResponse("success","message sent");
    }
}

從上面的代碼中,您可以c我訂閱了該主題並為訂閱者設置了一個新操作:

 redisMessageSubscriber.setAction(new Action2<Message, byte[]>() {
    @Override
    public void call(Message message, byte[] bytes) {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            String result = objectMapper.readValue(message.getBody(), String.class);
            logger.info("receive:"+result);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
});

但是我不知道為什么,在觸發發布者之后,訂閱者可以獲得消息但仍然保留NULL Action,而我創建的Action沒有傳遞給它。

有人可以幫忙嗎? 這個機制有問題嗎?

====編輯=====

RedisMessageConfig的代碼如下:

@Configuration
public class RedisMessageConfig {

@Bean
ChannelTopic topic() {
    return new ChannelTopic("useraddresspubsub:queue");
}

@Bean
MessageListenerAdapter messageListener() {
    return new MessageListenerAdapter(new RedisMessageSubscriber());
}

@Autowired
private RedisConnectionFactory JedisConnectionFactory;

@Bean
RedisMessageListenerContainer redisContainer() {
    final RedisMessageListenerContainer container = new RedisMessageListenerContainer();
    container.setConnectionFactory(JedisConnectionFactory);
    container.addMessageListener(messageListener(), topic());
    return container;
    }
}

====解決====

最終,我按照mp的想法解決了這個問題,因為從redismessageconfig到redismessagesubscriber的流程從myismismagesubscriber更改為myredismessageconfig,所以在redismessageconfig中,我需要先向其注入操作,然后redismessageconfig將創建新的redismessagesubscriber並保留新創建的操作。 下面的代碼:

@Component
public class MyRedisMessageConfig extends RedisMessageConfig {

private static Logger logger =LogManager.getLogger(MyRedisMessageConfig.class);

public MyRedisMessageConfig() {
    super.action = new Action2<Message, byte[]>() {
        @Override
        public void call(Message message, byte[] bytes) {
            String result = new String(message.getBody());
                logger.info("received:" + result);
            }
        };
    }
}

屏幕截圖如下: 在此處輸入圖片說明

這不是MessageListener工作方式。 此外,您創建共享的可變狀態。 兩個並發調用會同時更改RedisMessageSubscriber的狀態。

我假設您在一個線程中設置action在另一個線程上發生消息接收時遇到了可見性問題。

如果每個MessageListener要求不同的行為,則創建多個實現該行為的偵聽器。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM