1. 概要

Spring Data Redisを探索するシリーズのこの2番目の記事では、pub/subメッセージキューについて説明します。

Redisでは、パブリッシャーは特定のサブスクライバーにメッセージを送信するようにプログラムされていません。 むしろ、公開されたメッセージは、(もしあれば)サブスクライバーが何であるかを知らなくても、チャネルに特徴付けられます。

同様に、サブスクライバーは1つ以上のトピックに関心を示し、関心のあるメッセージのみを受信します。パブリッシャーが存在するかどうかはわかりません。

パブリッシャーとサブスクライバーのこの分離により、スケーラビリティと動的なネットワークトポロジが向上します。

2. Redis構成

メッセージキューに必要な構成の追加を始めましょう。

最初に、RedisMessageSubscriberと呼ばれるMessageListenerインターフェイスのカスタム実装を含むMessageListenerAdapterbeanを定義します。 このBeanは、pub-subメッセージングモデルのサブスクライバーとして機能します。

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

RedisMessageListenerContainer は、Spring Data Redisによって提供されるクラスであり、Redisメッセージリスナーに非同期動作を提供します。 これは内部的に呼び出され、 Spring Data Redisドキュメントによると、「リスニング、変換、メッセージディスパッチの低レベルの詳細を処理します」。

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

また、カスタムビルドのMessagePublisherインターフェースとRedisMessagePublisher実装を使用してBeanを作成します。 このようにして、汎用のメッセージ公開APIを使用し、Redis実装にredisTemplatetopicをコンストラクター引数として使用させることができます。

@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<String, Object> redisTemplate;
    @Autowired
    private ChannelTopic topic;

    public RedisMessagePublisher() {
    }

    public RedisMessagePublisher(
      RedisTemplate<String, Object> redisTemplate, ChannelTopic topic) {
      this.redisTemplate = redisTemplate;
      this.topic = topic;
    }

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

ご覧のとおり、パブリッシャーの実装は簡単です。 redisTemplateconvertAndSend()メソッドを使用して、指定されたメッセージをフォーマットし、構成されたトピックに公開します。

トピックは、パブリッシュおよびサブスクライブのセマンティクスを実装します。メッセージがパブリッシュされると、そのトピックをリッスンするように登録されているすべてのサブスクライバーに送信されます。

4. メッセージの購読

RedisMessageSubscriber は、SpringDataRedisが提供するMessageListenerインターフェースを実装します。

@Service
public class RedisMessageSubscriber implements MessageListener {

    public static List<String> messageList = new ArrayList<String>();

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

pattern という2番目のパラメーターがあることに注意してください。これは、この例では使用していません。 Spring Data Redisのドキュメントには、このパラメーターは「チャネルに一致するパターン(指定されている場合)」を表すと記載されていますが、nullの場合もあります。

5. メッセージの送受信

今、私たちはそれをすべてまとめます。 メッセージを作成し、RedisMessagePublisherを使用して公開しましょう。

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

publish(message)を呼び出すと、コンテンツはRedisに送信され、パブリッシャーで定義されたメッセージキュートピックにルーティングされます。 次に、そのトピックのサブスクライバーに配布されます。

RedisMessageSubscriber がリスナーであり、メッセージを取得するためにキューに登録されていることにお気づきかもしれません。

メッセージの到着時に、定義されたサブスクライバーの onMessage()メソッドがトリガーされました。

この例では、RedisMessageSubscribermessageListをチェックすることで、公開されたメッセージを受信したことを確認できます。

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

6. 結論

この記事では、SpringDataRedisを使用したPub/Subメッセージキューの実装について説明しました。

上記の例の実装は、GitHubプロジェクトにあります。