SpringCloud プロジェクトの構築方法を説明します (16) 統合ストリーム メッセージ ドライバー

マイクロサービスとは何ですか? シリーズが一目でわかる!

1. SpringCloudプロジェクトのビルド方法を教えます (1) 写真とテキストで詳しく説明、アホのような操作

2. SpringCloud プロジェクトの構築方法を教える (2) プロデューサーとコンシューマー

3. SpringCloudプロジェクトの構築方法を教えます (3) Eurekaサービス登録センターの統合

4. SpringCloudプロジェクトの構築方法を教えます (4) Eurekaクラスタのバージョン構築

5. SpringCloudプロジェクトのビルド方法を教えます (5) プロデューサークラスターバージョンをビルドします

6. SpringCloudプロジェクトの構築方法を教えます (6) Eurekaはサービスディスカバリを実現します

7. SpringCloudプロジェクトの構築方法を教える (7) Consulサービス登録センターを統合する

8. SpringCloudプロジェクトの構築方法を教えます (8) 統合リボンロードバランサ

9. SpringCloud プロジェクトの構築方法を説明します (9) OpenFeign サービス インターフェイス呼び出しの統合

10. SpringCloud プロジェクトの構築方法を教えます (10) Hystrix サービスのダウングレードの統合

11. SpringCloud プロジェクトの構築を教える (11) Hystrix のサービス ヒューズの統合

12. SpringCloud プロジェクトの構築方法を教える (12) Hystrix のグラフィカル ダッシュボードのリアルタイム モニタリングを統合する

13. SpringCloud プロジェクトの構築方法を教える (13) 新世代のゲートウェイを統合する

14. SpringCloudプロジェクトの構築方法を教えます (14) Integrated Config Distributed Configuration Center

15. SpringCloudプロジェクトの構築方法を教えます (15) Integrated Busメッセージバス

16. SpringCloud プロジェクトの構築方法を説明します (16) 統合された Stream メッセージ ドライバー

17. SpringCloud プロジェクトの構築方法を説明します (17) Sleuth 分散リンク追跡の統合

これからも更新していきますので、いいねやフォロー大歓迎です!

1. メッセージドリブンの概要

1. メッセージドリブンとは何ですか?

ActiveMQ、RabbitMQ、RocketMQ、Kafkaなど、企業でよく使われている実用的なメッセージミドルウェアは数多くあり、これらすべてのメッセージミドルウェアを習得するには多大な時間とコストがかかることは間違いありません。特定のメッセージ ミドルウェアの詳細に注意を払う必要がなくなり、適応バインディング方式を使用してさまざまなメッセージ ミドルウェアを自動的に切り替えるだけで済むテクノロジーです。メッセージ駆動型は、基盤となるメッセージ ミドルウェアの違いを保護し、スイッチング コストを削減し、メッセージのプログラミング モデルを統一できるテクノロジです。

Spring Cloud Stream は、コンポーネントのメッセージ駆動型マイクロサービスのフレームワークです。アプリケーションは、入力と出力、構成を介したバインディングを通じて SpringCloud Stream のバインダー (バインダー) オブジェクトと対話し、SpringCloud Stream のバインダー オブジェクトはメッセージ ミドルウェアと対話する役割を担うため、Spring Cloud と対話する方法を理解するだけで済みます。ストリームを使用すると、メッセージ駆動型のアプローチを簡単に使用できます。ただし、現時点では、SpringCloud Stream は RabbitMQ と Kafka のみをサポートしています。

2. デザイン思考

古典的なメッセージ キューでは、プロデューサー/コンシューマーはメッセージ メディアを介して情報コンテンツを送信し、メッセージは特定のチャネル メッセージ チャネルを経由する必要があります。メッセージ チャネル内のサブインターフェイス Subscribable Channel がメッセージを消費し、MessageHandler が責任を負います。送信と受信。

Spring Cloud Streamでは、バインダーを中間層として定義することで、アプリケーションとメッセージミドルウェアの詳細との分離を実現している。メッセージ バインダーでは、INPUT はコンシューマーに対応し、OUTPUT はプロデューサーに対応し、ストリーム内のメッセージ通信方法はパブリッシュ/サブスクライブ モードに従います。つまり、トピックによるブロードキャスト (RabbitMQ の対応する交換スイッチと Kafka トピックの交換スイッチ) です。

3. Spring Cloud Stream エンコーディング API と共通のアノテーション

ここに画像の説明を挿入

2. Spring Cloud Stream ケースの実践

メッセージのプロデューサーとコンシューマーに対応する 3 つの新しいサブモジュールを作成します。

モジュール名 マイクロサービス関数cloud-stream-rabbitmq-provider8801プロデューサー、メッセージ送信モジュールcloud-stream-rabbitmq-consumer8802コンシューマー、メッセージ受信モジュールcloud-stream-rabbitmq-consumer8803コンシューマー、メッセージ受信モジュール

1. メッセージ駆動型メッセージプロデューサー

新しいモジュールを作成します:cloud-stream-rabbitmq-provider8801 は、メッセージを送信するためのメッセージ プロデューサーとして使用されます。その POM ファイルには、web、actuator、eureka-client などの必要なスターターを導入することに加えて、 RabbitMQ 起動デバイスの依存関係を実装する Spring Cloud Stream:

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

構成ファイル application.yml を作成します。

server:
  port: 8801
 
spring:
  application:
    name: cloud-stream-provider
  cloud:
    stream:
      binders: # 在此处配置要绑定的rabbitmq的服务信息;
        defaultRabbit: # 表示定义的名称,用于于binding整合
          type: rabbit # 消息组件类型
          environment: # 设置rabbitmq的相关的环境配置
            spring:
              rabbitmq:
                host: localhost
                port: 5672
                username: guest
                password: guest
      bindings: # 服务的整合处理
        output: # 这个名字是一个通道的名称,OUTPUT表示这是消息的发送方
          destination: testExchange # 表示要使用的Exchange名称定义
          content-type: application/json # 设置消息类型,本次为json,文本则设置“text/plain”
          binder: defaultRabbit # 设置要绑定的消息服务的具体设置
 
eureka:
  client: # 客户端进行Eureka注册的配置
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
  instance:
    lease-renewal-interval-in-seconds: 2 # 设置心跳的时间间隔(默认是30秒)
    lease-expiration-duration-in-seconds: 5 # 如果现在超过了5秒的间隔(默认是90秒)
    instance-id: send-8801.com  # 在信息列表时显示主机名称
    prefer-ip-address: true     # 访问的路径变为IP地址

メインの起動クラスを記述した後、ビジネス クラスを記述します。ビジネスでは、送信メッセージ インターフェイスとその実装クラスをそれぞれ記述し、送信の実装クラスでメッセージをバインドするための **@EnableBinding アノテーションをプッシュ パイプラインに追加します。インターフェイス message 、メッセージプロデューサーによってバインドされたメッセージプッシュパイプラインは org.springframework.cloud.stream.messaging.Source** です。

package cn.sher6j.sprincloud.service;
 
/**
 * 发送消息接口
 * @author sher6j
 * @create 2020-05-25-12:20
 */
public interface IMessageProvider {
    
    
    public String send();
}
----------------------------------------------------------------------
package cn.sher6j.sprincloud.service.impl;
 
import cn.sher6j.sprincloud.service.IMessageProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.MessageBuilder;
import java.util.UUID;
 
/**
 * 发送消息接口实现类
 * @author sher6j
 * @create 2020-05-25-12:21
 */
@EnableBinding(Source.class) //定义消息的推送管道
public class MessageProviderImpl implements IMessageProvider {
    
    
 
    @Autowired
    private MessageChannel output; //消息发送管道
 
    @Override
    public String send() {
    
    
        String serial = UUID.randomUUID().toString();
        output.send(MessageBuilder.withPayload(serial).build());//发送消息
        System.out.println("========serial:" + serial);
        return null;
    }
}

このサービスは従来の意味でコントローラーや DAO データなどと対話するサービスではなく、バインダーでバインドする必要があるサービスであるため、サービス実装クラスに @Service アノテーションが不要になったことに注意してください。 。

次に、ビジネス層のコントローラーを作成します。

@RestController
public class SendMessageController {
    
    
    @Autowired
    private IMessageProvider messageProvider;
 
    @GetMapping("/sendMessage")
    public String sendMessage() {
    
    
        return messageProvider.send();
    }
}

サービス登録センターと RabbitMQ を開始した後、メッセージ プロデューサー マイクロサービスを開始します。RabbitMQ コントロール パネルに testExchange という名前の追加スイッチが表示されます。このスイッチは、前に構成ファイルで構成したスイッチの名前とまったく同じです。
ここに画像の説明を挿入

次に、http://localhost:8801/sendMessage にアクセスし、メッセージ プロデューサー マイクロサービスを使用してメッセージを送信します。マイクロサービスのバックグラウンドで、出力されたメッセージが表示されます。
ここに画像の説明を挿入

RabbitMQ のコントロール パネルでは、メッセージが実際に送信されたことも確認できました。
ここに画像の説明を挿入

2. メッセージ駆動型のメッセージ コンシューマ

新しいモジュールを作成します:cloud-stream-rabbitmq-consumer8802/8803 は、メッセージを受信するメッセージ プロデューサーとして使用されます。その POM ファイルに導入されたイニシエーターの依存関係は、メッセージ プロデューサー マイクロサービスの依存関係とほぼ同じであり、その構成を書き込みますファイル application.yml の構成ファイルの記述は、メッセージ プロデューサーの記述とほぼ同じです。メッセージ プロデューサー マイクロサービスによって使用されるチャネルは OUTPUT であるのに対し、メッセージ コンシューマー マイクロサービスによって使用されるチャネルは INPUT であることに注意してください。その他の設定ファイル情報 ポート番号と登録されているサービス名の違いにのみ注意する必要があります。

spring:
  cloud:
      bindings: 
        input: # 这个名字是一个通道的名称,INPUT表示消息消费者

メインのスタートアップ クラスを作成した後、メッセージ コンシューマーのビジネス クラスを作成します。これはコンシューマーなので、コントローラーを作成するだけで済みます。そのコントローラーには、プッシュ パイプラインをバインドするための **@EnableBinding アノテーションも追加する必要がありますメッセージの、メッセージ コンシューマーによってバインドされたメッセージ プッシュ パイプラインは import org.springframework.cloud.stream.messaging.Sink です。メッセージの受信メソッドでは、@StreamListner** アノテーションを使用してバインドされたメッセージ プッシュを監視する必要がありますパイプライン:

package cn.sher6j.springcloud.controller;
 
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.cloud.stream.messaging.Sink;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;
 
/**
 * @author sher6j
 * @create 2020-05-25-12:58
 */
@Component
@EnableBinding(Sink.class)
public class ReceiveMessageController {
    
    
    
    @Value("${server.port}")
    private String serverPort;
    
    @StreamListener(Sink.INPUT)
    public void input(Message<String> message) {
    
    
        System.out.println("消费者" + serverPort + "号,收到消息:" + message.getPayload());
    }
}

次に、メッセージ送信コンシューマー サービスを開始し、プロデューサーを使用してメッセージを送信すると、メッセージがコンシューマー側で正常に受信できることがわかります。
ここに画像の説明を挿入

3. グループ消費と持続性

1. リピート消費問題

プロデューサがメッセージを送信すると、現時点ではコンシューマはすべてメッセージを受け入れて消費します。つまり、同じメッセージが複数のメッセージ コンシューマによって消費されます。
ここに画像の説明を挿入

上記の問題はメッセージの繰り返し消費の問題ですが、なぜこの問題がそれほど重要なのでしょうか? 実際、繰り返し消費の問題自体はひどいものではなく、繰り返し消費した後の冪等性をどのように確保するかが考慮されていないことが恐ろしいのです。(冪等性とは、平たく言えば、1 つのデータまたは 1 つのリクエストに対して何度も繰り返され、対応するデータが変更されず、間違いが発生しないことを保証する必要があります)。分散マイクロサービス アプリケーションで高可用性と負荷分散を実現するために、実際には、同じ機能を持つサービスに対して複数の特定のサービス インスタンスがデプロイされます。たとえば、データベースへのデータの挿入を要求するメッセージを含むシステムがあるとします。メッセージが 2 回消費されると、結果として 2 つのデータがデータベースに挿入されます。このようにして、データはただし、メッセージが 2 回目に消費される場合、メッセージはすでに消費されていると判断でき、メッセージは直接破棄されます。実際に消費されると、データは 1 つだけになります。データベースに挿入され、システムの冪等性が保証されます。

上記では、メッセージの繰り返し消費の問題を簡単に紹介しましたが、この繰り返し消費の問題を解決するには、グループ化と永続属性グループ操作を実行し、Spring Cloud Stream でメッセージ グループ化を使用してこの問題を解決する必要があります。ストリーム内の同じグループ内の複数のメッセージ コンシューマは競合関係にあることに注目しました。これは、プロデューサによって送信された同じメッセージが、コンシューマの 1 つによって 1 回だけ消費されることが保証されていることを意味します。異なるグループのコンシューマはメッセージを完全に消費 (繰り返し消費) でき、同じグループ内でのみ競合が発生します。

RabbitMQ では、デフォルトのグループ化が異なり、グループのシリアル番号も異なり、別のグループとみなされます。testExchange スイッチを確認すると、2 つのメッセージ コンシューマー 8802 と 8803 が異なるグループに属していることがわかり、送信されたメッセージは8801 メッセージ プロデューサによるメッセージは、次の 2 つのコンシューマによって繰り返し消費できます。
ここに画像の説明を挿入

2. 反復消費問題を解決する団体

上で RabbitMQ コントロール パネルで確認したグループのシリアル番号は、システムによってランダムに割り当てられますが、これは間違いなく制御が難しいため、構成グループをカスタマイズし、2 つのメッセージ コンシューマー マイクロサービス 8802/8803 を同じグループに分割する必要があります。メッセージが繰り返し消費される問題を解決するために、まずグループ化をカスタマイズする方法を説明します。

8802/8803 マイクロサービスの構成ファイルにグループ名属性を追加します。

spring:
  cloud:
    stream:
      bindings:
        input:
          group: A/B ## 分组名称

ここでは、8802 をグループ A、8803 をグループ B に設定し、メッセージ コンシューマーの 2 つのマイクロサービスを再起動し、グループのシリアル番号を再度確認しました。その結果、長いランダムなグループ シリアル番号ではなく、次のように変更されたことがわかりました。カスタム グループ化になりました。
ここに画像の説明を挿入

現時点では、8802/8803 は 2 つの異なるグループに属しているため、競合はなく、メッセージ プロデューサがメッセージを送信した後も、メッセージは繰り返し消費されます。

次に、2 つのメッセージ コンシューマ マイクロサービスを同じコンシューマ グループに分割します。これにより、コンシューマは一度に 1 つだけになり、メッセージ プロデューサーによって送信されたメッセージは 8802 または 8803 のいずれかでのみ受信できるようになり、重複が回避されます。 、8802 と 8803 のグループ名を A に変更し、2 つのメッセージ コンシューマ マイクロサービスを再度再起動すると、グループ A の下にすでに 2 つのコンシューマが存在することがわかります。
ここに画像の説明を挿入

次に、プロデューサーを使用して 5 つのメッセージを送信すると、8802/8803 がそれぞれ 3 つと 2 つの異なるメッセージを消費し、繰り返し消費されるという問題がないことがわかりました。

ここに画像の説明を挿入

時間の都合上、他の友人Liijia Hengbaoが記事を転送しました。クリックして元のテキストを表示します

ここで Spring Cloud Stream の学習は終了しました。次の記事では、Spring Cloud Stream の分散リンク追跡について学び、学習と更新を続けます。次のセクションはさらにエキサイティングな内容になります。お友達の「いいね」やフォローも大歓迎です!ありがたい!ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/weixin_39570655/article/details/131834057