Spring Cloud Streamのメッセージ処理設計

メッセージングフレームワーク

概要

https://spring.io/projects/spring-cloud-stream#overview

https://docs.spring.io/spring-cloud-stream/docs/current/reference/html/

メッセージングの課題

複数のメッセージキューイングシステムを使用する場合、各システムのAPI差異により開発が複雑化します。Spring Cloud Streamはこれらの差異を抽象化し、統一的なプログラミングモデルを提供します。

機能概要

Spring Cloud Streamは、イベント駆動型マイクロサービスを構築するためのフレームワークです。アプリケーションは入力/出力チャネルを通じてバインダーと通信し、設定によりメッセージングシステムと接続します。現在サポートされているメッセージングシステムはRabbitMQとKafkaです。

デザインコンセプト

一般的なメッセージング構造

プロデューサーとコンシューマーはMessageオブジェクトを通じて通信します。メッセージはMessageChannelを介して送信され、サブスクライバーが受信します。

なぜSpring Cloud Streamを使うのか

RabbitMQとKafkaのアーキテクチャ差異(例: エクスチェンジ vs トピック/パーティション)により、メッセージングシステムの切り替えが困難です。Spring Cloud Streamはこの課題を解消するための抽象化レイヤーを提供します。

実装方法

バインダーを介してアプリケーションとメッセージングシステムを分離します。統一されたチャネルインターフェースを通じて、メッセージの送受信を実現します。

メッセージ処理フロー

バインダー: メッセージングシステムとの接続を管理し、差異を隠蔽します。

チャネル: ソースとシンクの役割を分担します。

プログラミングAPIと注釈

メッセージプロデューサー

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>


spring:
  application:
    name: msg-producer

  cloud:
    stream:
      binders:  
        mqConfig:  
          type: rabbit  
          environment:  
            spring:
              rabbit:
                host: localhost
                port: 5672
                username: guest
                password: guest

      bindings: 
        output: 
          destination: msgExchange  
          content-type: application/json  
          binder: mqConfig


@EnableBinding(Source.class)
public class Producer {

    @Autowired
    private MessageChannel output;

    public String sendMessage(){
        output.send(MessageBuilder.withPayload("test").build());
        return UUID.randomUUID().toString();
    }

}


@RestController
public class MsgController {

    @Autowired
    private Producer producer;

    @GetMapping(value = "/send")
    public String send(){
        return producer.sendMessage();
    }

}


@SpringBootApplication
public class MsgProducerApp {

    public static void main(String[] args) {
        SpringApplication.run(MsgProducerApp.class, args);
    }

}

http://localhost:8080/send

メッセージコンシューマー

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>


spring:
  application:
    name: msg-consumer

  cloud:
    stream:
      binders:  
        mqConfig:  
          type: rabbit  
          environment:  
            spring:
              rabbit:
                host: localhost
                port: 5672
                username: guest
                password: guest

      bindings: 
        input: 
          destination: msgExchange  
          content-type: application/json  
          binder: mqConfig


@Component
@EnableBinding(Sink.class)
public class Consumer {

    @StreamListener(Sink.INPUT)
    public void processMessage(String message){
        System.out.println("受信データ: " + message);
    }

}


@SpringBootApplication
public class MsgConsumerApp {

    public static void main(String[] args) {
        SpringApplication.run(MsgConsumerApp.class, args);
    }

}

グループ化と永続化

クラスタ環境での課題

同じ機能のマイクロサービスが複数稼働する場合、メッセージの重複処理が発生します。

グループ設定による解決

Spring Cloud Streamのグループ機能により、同一グループ内のコンシューマーは競合関係となり、メッセージは1つのサービスにのみ届きます。

spring:
  cloud:
    stream:
      bindings:
        input:
          group: msgGroup
永続化の仕組み

グループを明示的に設定することで、アプリケーション再起動時も未処理メッセージを再取得できます。グループ未設定の場合、障害発生時にメッセージが失われる可能性があります。

タグ: SpringCloudStream MessagingFramework RabbitMQ Kafka Microservices

9月14日 05:50 投稿