Обмен сообщениями PubSub с использованием Red Data Redis
1. обзор
Во второй статье из серии, посвященной Spring Data Redis, мы рассмотрим очереди сообщений pub / sub.
В Redis издатели не запрограммированы отправлять свои сообщения конкретным подписчикам. Скорее, опубликованные сообщения делятся на каналы, не зная, какие (если таковые имеются) подписчики могут быть.
Точно так же подписчики выражают интерес к одной или нескольким темам и получают только те сообщения, которые представляют интерес, не зная, какие (если таковые имеются) издатели существуют.
Такое разделение издателей и подписчиков может обеспечить большую масштабируемость и более динамичную топологию сети.
2. Конфигурация Redis
Приступим к добавлению конфигурации, необходимой для очередей сообщений.
Сначала мы определим bean-компонентMessageListenerAdapter, который содержит настраиваемую реализацию интерфейсаMessageListener под названиемRedisMessageSubscriber. Этот бин действует как подписчик в модели обмена сообщениями pub-sub:
@Bean
MessageListenerAdapter messageListener() {
return new MessageListenerAdapter(new RedisMessageSubscriber());
}
RedisMessageListenerContainer - это класс, предоставляемый Spring Data Redis, который обеспечивает асинхронное поведение для слушателей сообщений Redis. Это вызывается внутренне и, согласноSpring Data Redis documentation - «обрабатывает низкоуровневые детали прослушивания, преобразования и отправки сообщений».
@Bean
RedisMessageListenerContainer redisContainer() {
RedisMessageListenerContainer container
= new RedisMessageListenerContainer();
container.setConnectionFactory(jedisConnectionFactory());
container.addMessageListener(messageListener(), topic());
return container;
}
Мы также создадим компонент, используя специально созданный интерфейсMessagePublisher и реализациюRedisMessagePublisher. Таким образом, у нас может быть общий API публикации сообщений, а реализация Redis принимает в качестве аргументов конструктораredisTemplate иtopic:
@Bean
MessagePublisher redisPublisher() {
return new RedisMessagePublisher(redisTemplate(), topic());
}
Наконец, мы настроим тему, по которой издатель будет отправлять сообщения, а подписчик будет их получать:
@Bean
ChannelTopic topic() {
return new ChannelTopic("messageQueue");
}
3. Публикация сообщений
3.1. Определение интерфейсаMessagePublisher
Spring Data Redis не предоставляет интерфейсMessagePublisher, который будет использоваться для распространения сообщений. Мы можем определить собственный интерфейс, который будет использоватьredisTemplate в реализации:
public interface MessagePublisher {
void publish(String message);
}
3.2. RedisMessagePublisher Реализация
Наш следующий шаг - предоставить реализацию интерфейсаMessagePublisher, добавив детали публикации сообщений и используя функции вredisTemplate.
Шаблон содержит очень богатый набор функций для широкого круга операций, из которыхconvertAndSend может отправлять сообщение в очередь через тему:
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);
}
}
Как видите, реализация издателя проста. Он использует методconvertAndSend() элементаredisTemplate для форматирования и публикации данного сообщения в настроенной теме.
Тема реализует семантику публикации и подписки: когда сообщение публикуется, оно распространяется на всех подписчиков, которые зарегистрированы для прослушивания этой темы.
4. Подписка на сообщения
RedisMessageSubscriber реализует интерфейсMessageListener, предоставляемый 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());
}
}
Обратите внимание, что есть второй параметрpattern, который мы не использовали в этом примере. В документации Spring Data Redis указано, что этот параметр представляет «шаблон, соответствующий каналу (если указан)», но это может бытьnull.
5. Отправка и получение сообщений
Теперь соберем все воедино. Давайте создадим сообщение, а затем опубликуем его с помощьюRedisMessagePublisher:
String message = "Message " + UUID.randomUUID();
redisMessagePublisher.publish(message);
Когда мы вызываемpublish(message), контент отправляется в Redis, где он направляется в тему очереди сообщений, определенную в нашем издателе. Затем он распространяется среди подписчиков этой темы.
Возможно, вы уже заметили, чтоRedisMessageSubscriber является слушателем, который регистрируется в очереди для получения сообщений.
По прибытии сообщения срабатывает определенный метод подписчикаonMessage().
В нашем примере мы можем проверить, получили ли мы опубликованные сообщения, проверивmessageList в нашемRedisMessageSubscriber:
RedisMessageSubscriber.messageList.get(0).contains(message)
6. Заключение
В этой статье мы рассмотрели реализацию очереди сообщений pub / sub с использованием Spring Data Redis.
Реализацию приведенного выше примера можно найти вa GitHub project.