Обмен сообщениями PubSub с Spring Redis

Обмен сообщениями 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.

Related