Mensagens do PubSub com Spring Data Redis

Mensagens do PubSub com Spring Data Redis

1. Visão geral

Neste segundo artigo da série que explora o Spring Data Redis, daremos uma olhada nas filas de mensagens pub / sub.

No Redis, os editores não estão programados para enviar suas mensagens a assinantes específicos. Em vez disso, as mensagens publicadas são caracterizadas em canais, sem o conhecimento do que (se houver) assinantes.

Da mesma forma, os assinantes manifestam interesse em um ou mais tópicos e recebem apenas mensagens de seu interesse, sem o conhecimento do (se houver) publicador.

Essa dissociação de editores e assinantes pode permitir maior escalabilidade e uma topologia de rede mais dinâmica.

2. Configuração Redis

Vamos começar adicionando a configuração necessária para as filas de mensagens.

Primeiro, definiremos um beanMessageListenerAdapter que contém uma implementação personalizada da interfaceMessageListener chamadaRedisMessageSubscriber. Este bean atua como um assinante no modelo de mensagens pub-sub:

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

RedisMessageListenerContainer é uma classe fornecida pelo Spring Data Redis que fornece comportamento assíncrono para ouvintes de mensagem do Redis. Isso é chamado internamente e, de acordo com oSpring Data Redis documentation - “lida com os detalhes de baixo nível de escuta, conversão e envio de mensagens”.

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

Também criaremos um bean usando uma interfaceMessagePublisher customizada e uma implementaçãoRedisMessagePublisher. Dessa forma, podemos ter uma API de publicação de mensagens genérica e fazer com que a implementação do Redis tomeredisTemplateetopic como argumentos do construtor:

@Bean
MessagePublisher redisPublisher() {
    return new RedisMessagePublisher(redisTemplate(), topic());
}

Por fim, configuraremos um tópico para o qual o editor enviará mensagens e o assinante as receberá:

@Bean
ChannelTopic topic() {
    return new ChannelTopic("messageQueue");
}

3. Publicação de mensagens

3.1. Definindo a InterfaceMessagePublisher

O Spring Data Redis não fornece uma interfaceMessagePublisher para ser usada para distribuição de mensagens. Podemos definir uma interface personalizada que usaráredisTemplate na implementação:

public interface MessagePublisher {
    void publish(String message);
}

3.2. Implementação deRedisMessagePublisher

Nossa próxima etapa é fornecer uma implementação da interfaceMessagePublisher, adicionando detalhes de publicação de mensagens e usando as funções emredisTemplate.

O modelo contém um conjunto muito rico de funções para uma ampla gama de operações - das quaisconvertAndSend é capaz de enviar uma mensagem para uma fila por meio de um tópico:

public class RedisMessagePublisher implements MessagePublisher {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private ChannelTopic topic;

    public RedisMessagePublisher() {
    }

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

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

Como você pode ver, a implementação do editor é direta. Ele usa o métodoconvertAndSend() doredisTemplate para formatar e publicar a mensagem fornecida no tópico configurado.

Um tópico implementa a semântica de publicação e assinatura: quando uma mensagem é publicada, ela vai para todos os assinantes registrados para ouvir sobre esse tópico.

4. Inscrever-se em mensagens

RedisMessageSubscriber implementa a interfaceMessageListener fornecida pelo Spring Data Redis:

@Service
public class RedisMessageSubscriber implements MessageListener {

    public static List messageList = new ArrayList();

    public void onMessage(Message message, byte[] pattern) {
        messageList.add(message.toString());
        System.out.println("Message received: " + message.toString());
    }
}

Observe que há um segundo parâmetro chamadopattern, que não usamos neste exemplo. A documentação do Spring Data Redis afirma que este parâmetro representa o “padrão correspondente ao canal (se especificado)”, mas que pode sernull.

5. Envio e recebimento de mensagens

Agora vamos colocar tudo junto. Vamos criar uma mensagem e publicá-la usando oRedisMessagePublisher:

String message = "Message " + UUID.randomUUID();
redisMessagePublisher.publish(message);

Quando chamamospublish(message), o conteúdo é enviado ao Redis, onde é encaminhado para o tópico da fila de mensagens definido em nosso editor. Em seguida, é distribuído aos assinantes desse tópico.

Você já deve ter notado queRedisMessageSubscriber é um ouvinte, que se registra na fila para recuperação de mensagens.

Na chegada da mensagem, o métodoonMessage() definido do assinante foi acionado.

Em nosso exemplo, podemos verificar se recebemos mensagens que foram publicadas verificandomessageList em nossoRedisMessageSubscriber:

RedisMessageSubscriber.messageList.get(0).contains(message)

6. Conclusão

Neste artigo, examinamos uma implementação de fila de publicação / sub mensagem usando Spring Data Redis.

A implementação do exemplo acima pode ser encontrada ema GitHub project.