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.