springboot でマイクロサービス 02-rabbitmq を使用する方法 (その 1)

目次

序文: 上記に送信

-> Rabbitmq ポータルをインストールします。

-> Rabbitmq は問題を使用してポータルを解決します。

1. Rabbitmq の 6 つのモード: 

1.1 シンプルモード:(1対1)

-> ビジネスシナリオ: 

1.2 作業モード: (1 対多)

-> ビジネスシナリオ: 

1.3 パブリッシュおよびサブスクライブ モード:(ブロードキャスト)

1.4 ルーティングモード: 

 -> ビジネスシナリオ

1.5 テーマモード:(ルーティングアップグレードバージョン)

-> ビジネスシナリオ

1.6 RPC 非同期呼び出しモード

-> ビジネスシナリオ

2. RabbitMQ の動作メカニズムには主に次のものが含まれます。

3. Springboot 統合 RabbitMq の準備

ps: RabbitTemplate と AmqpTemplate の書き方は 2 つあります

3.1 2 つの springboot プロジェクトを作成します (通常の作成では依存関係を追加する必要はありません)

3.2 依存関係の追加

3.3 application.yml を変更する

 3.4 テストの開始 

 起動失敗の解決策

4. 6つのモードの実際の動作

4.0 コール シミュレーション (時間制限付きスケジューリング タスク)

→ 4.0.1 プロデューサー起動クラス

->4.0.2 コンシューマ起動クラス

4.1 シンプルモード

-> 4.1.1 プロデューサーコード

-> 4.1.2 コンシューマコード

4.2 作業モード

-> 4.2.1 プロデューサーコード

-> 4.2.2 コンシューマコード

4.3 メッセージとサブスクリプション モード (ブロードキャスト)

-> 4.3.0 コンシューマでファンアウトスイッチを宣言する

-> 4.3.1 コンシューマコード

-> 4.3.2 プロデューサーコード

この記事の概要と次のポータル

→ 次へ: springboot で 03-rabbitmq を使用する方法 (その 2)


序文: 上記に送信

-> Rabbitmq ポータルをインストールします。

 01-rabbitmq アプリケーションのシナリオとインストール (docker)

-> Rabbitmq は問題を使用してポータルを解決します。

  00-rabbitmqの異常と解決策

1. Rabbitmq の 6 つのモード: 

1.1 シンプルモード:(1対1)

送信者はキューにメッセージを送信し、受信者はキューからメッセージを受信します。

-> ビジネスシナリオ: 

注文の作成、電子メールの送信、その他消費者がプロセスを意識しない操作

1.2 作業モード: (1 対多)

複数のワーカーが同じキューからメッセージを同時に受信して処理し、各メッセージは 1 つのワーカーのみによって処理されます。

-> ビジネスシナリオ: 

 複数の消費者が、1 人の消費者と同様に、一緒に圧力に抵抗し、一緒に圧力を受ける

1.3 パブリッシュおよびサブスクライブ モード:(ブロードキャスト)

送信者がメッセージを交換機に送信すると、交換機はそのメッセージを、それぞれが受信者を持つ複数のキューに分散します。

1.4 ルーティングモード: 

パブリッシュ/サブスクライブ パターンと同様に、メッセージが「ルーティング キー」によってキュー内の受信者と照合される点が異なります。

 -> ビジネスシナリオ

ログ収集や別注文処理など、ルーティングモードが使用できる場合はトピックモードを使用しないでください。

1.5 テーマモード:(ルーティングアップグレードバージョン)

より柔軟なワイルドカード一致ルールが使用されます。

-> ビジネスシナリオ

E コマース プラットフォームはトピック モードを使用して、製品の販売情報をさまざまなキューに送信できます。

1.6 RPC 非同期呼び出しモード

一意の識別子が必要であり、クライアントはその識別子を使用してリクエストを送信し、サーバーはリクエストの処理後に応答とともに識別子をクライアントに送り返すため、クライアントはリクエストとレスポンスを正しく照合できます。

-> ビジネスシナリオ

たとえば、電子商取引プラットフォームは、非同期呼び出しモードを使用して在庫管理システムと注文システムの間の対話を実現でき、注文が作成されると、注文システムは在庫管理システムを呼び出して商品在庫を削減します。在庫管理システムの処理が完了すると、その結果がコールバックキューに送られ、受注システムはコールバックキューから処理結果を取得し、対応する処理を実行します。

2. RabbitMQ の動作メカニズムには主に次のものが含まれます。

  1. メッセージプロデューサー (パブリッシャー): RabbitMQ にメッセージを送信するアプリケーション。

  2. メッセージ キュー (キュー): メッセージを保存するために使用されるバッファ。キューの最大長、キュー メッセージの有効期限など、必要に応じてキューのプロパティを設定できます。

  3. Exchange (Exchange): プロデューサーによって送信されたメッセージを受信し、それらを対応するキューにルーティングするために使用されます。交換のタイプには、ダイレクト モード、トピック モード、ファン モード、ヘッド モードなどがあります。

  4. バインド: 指定されたルーティング キー (ルーティング キー) を介してスイッチとキューをバインドします。バインド関係は多対多にすることができます。

  5. メッセージ コンシューマ (コンシューマ): キューからメッセージを取得して処理するアプリケーション。

  6. 仮想ホスト: RabbitMQ を使用すると、仮想ホストを通じて論理メッセージを分離できます。異なる仮想ホストは互いに独立しており、独自の独立したスイッチ、キュー、権限などを持つことができます。

動作メカニズム全体では、プロデューサは指定されたスイッチにメッセージを送信し、スイッチはルーティング キーに従ってメッセージを対応するキューに分配し、コンシューマは処理のためにキューからメッセージを取り出します。RabbitMQ は、メッセージの永続化、メッセージの優先順位の設定、メッセージのトランザクション処理などの操作を高い信頼性と可用性で実行することもできます。


3. Springboot 統合 RabbitMq の準備

ps: RabbitTemplate と AmqpTemplate の書き方は 2 つあります

この 2 つは、両社がパッケージ化した 2 つの機能が効果を発揮し、どちらかを選択することができると理解できます。 

準備

3.1 2 つの springboot プロジェクトを作成します (通常の作成では依存関係を追加する必要はありません)

Rabbitmq プロバイダー プロデューサー

Rabbitmq-consumer コンシューマー

マイクロサービス プロジェクトのシミュレーションには登録センターは必要ありません

3.2 依存関係の追加

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>

3.3 application.yml を変更する

spring:
  rabbitmq:
    host: *
    username: pzy
    password: *
    virtual-host: pingzhuyan
    listener:
      simple:
        prefetch: 1 #设置每次预抓取的数量是1,处理完之前不收下一条 默认250
server:
  port: 9501
spring:
  rabbitmq:
    host: *
    username: pzy
    password: *
    virtual-host: pingzhuyan
    listener:
      simple:
        prefetch: 1 #设置每次预抓取的数量是1,处理完之前不收下一条 默认250
server:
  port: 9502

 3.4 テストの開始 

 起動失敗の解決策

1. ポート番号の競合: ポートを変更します。

2. Bean の競合: キャッシュをクリアして再起動する

3. 削除後、pom と xml が灰色になり、右クリックして Maven プロジェクトを追加します

その他の Baidu、rabbitmq が接続できず、サービスが起動しているかどうかを確認できません

4. 6つのモードの実際の動作

4.0 コール シミュレーション (時間制限付きスケジューリング タスク)

非同期スレッド プール。ここでは紹介されていない他の記事を参照してください。

→ 4.0.1 プロデューサー起動クラス

package cn.pingzhuyan.rabbitmq;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;

@EnableAsync
@EnableScheduling
@SpringBootApplication
public class RabbitProviderApp {

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

}

->4.0.2 コンシューマ起動クラス

package cn.pingzhuyan.rabbitmq;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class RabbitConsumerApp {

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

}

4.1 シンプルモード

package cn.pingzhuyan.rabbitmq.config;

import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author pzy
 * @version 0.1.0
 * @description: TODO
 */
@Configuration
public class RabbitConfig {

    /**
     * 声明一个简单队列
     * @return
     */
    @Bean
    public Queue helloQueue(){
//        return new Queue("PZY",true,false,false);
        return new Queue("PZY");
    }



}

-> 4.1.1 プロデューサーコード

package cn.pingzhuyan.rabbitmq.singleM1;

import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

/**
 * 简单模式生产者
 * @author pzy
 * @version 0.1.0
 * @description: TODO
 */

@Component
public class SingleM1Provider {

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Scheduled(cron = "*/1 * * * * ?" )
    public void singleSend01() {
        System.out.println("生产者: <简单队列>定时(1次/s)发送 -> 今天天气真好!");

        amqpTemplate.convertAndSend("PZY", "今天天气真好!");
    }

}

-> 4.1.2 コンシューマコード

package cn.pingzhuyan.rabbitmq.singleM1;

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

/**
 * @author pzy
 * @version 0.1.0
 * @description: TODO
 */
//@Component
public class RabbitConsumerM1 {


    @RabbitListener(queues = "PZY")
    public void singleReceive1(String msg) {

        System.out.printf("消费者接收到: %s\n", msg);
    }


}

4.2 作業モード

-> 4.2.1 プロデューサーコード

package cn.pingzhuyan.rabbitmq.workM2;

import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

/**
 * 简单模式生产者
 * @author pzy
 * @version 0.1.0
 * @description: TODO
 */

@Component
public class WorkM2Provider {

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Async
    @Scheduled(cron = "*/1 * * * * ?" )
    public void workSend01() {
        System.out.println("生产者1: <工作模式>定时(1次/s)发送 -> 今天天气真好!");

        amqpTemplate.convertAndSend("PZY", "今天天气真好!");
    }
    @Async
    @Scheduled(cron = "*/1 * * * * ?" )
    public void workSend02() {
        System.out.println("生产者2: <工作模式>定时(1次/s)发送 -> 今天天气真好!");

        amqpTemplate.convertAndSend("PZY", "今天天气真好!");
    }

}

-> 4.2.2 コンシューマコード

package cn.pingzhuyan.rabbitmq.workM2;

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

/**
 * @author pzy
 * @version 0.1.0
 * @description: TODO
 */
@Component
public class RabbitConsumerM2 {


    @RabbitListener(queues = "PZY")
    public void workReceiveM2One(String msg) {

        System.out.printf("消费者1 接收到: %s\n", msg);
    }

    @RabbitListener(queues = "PZY")
    public void workReceiveM2Two(String msg) {

        System.out.printf("消费者2 接收到: %s\n", msg);
    }


}

4.3 メッセージとサブスクリプション モード (ブロードキャスト)

-> 4.3.0 コンシューマでファンアウトスイッチを宣言する

package cn.pingzhuyan.rabbitmq.config;

import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * rabbitmq的默认手动确认模式
 * @author pzy
 * @version 0.1.0
 * @description: TODO
 */
@Configuration
public class RabbitConfig {

    /**
     * 创建(声明)一个简单队列
     * @return
     */
    @Bean
    public Queue helloQueue(){
//        return new Queue("PZY",true,false,false);
        return new Queue("PZY");
    }

    /**
     * 创建radioFanout交换机
     * 消费者需要绑定此交换机
     * @return
     */
    @Bean
    public FanoutExchange radioFanout(){
        return new FanoutExchange("PZY_RADIO",false,false);
    }




}

-> 4.3.1 コンシューマコード

package cn.pingzhuyan.rabbitmq.faoutM3;

import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

/**
 * 发布与订阅模式的消费者
 *
 * @author pzy
 * @version 0.1.0
 * @description: TODO
 */
@Component
public class FanoutF3Consumer {

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue,  //不写就是随机队列, false true true
            exchange = @Exchange(name = "PZY_RADIO", declare = "false")//交换机(PZY_RADIO, 不创建并使用已经存在的交换机)
    ))
    public void radioFanoutMessage1(String msg) {
        System.out.printf("消费者1接收到: %s\n", msg);
    }

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue,
            exchange = @Exchange(name = "PZY_RADIO", declare = "false")//队列绑定交换机
    ))
    public void radioFanoutMessage2(String msg) {
        System.out.printf("消费者2接收到: %s\n", msg);
    }

}

-> 4.3.2 プロデューサーコード

package cn.pingzhuyan.rabbitmq.fanoutM3;

import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

/**
 * 发布和订阅模式生产者
 *
 * @author pzy
 * @version 0.1.0
 * @description: TODO
 */

@Component
public class FanoutF3Provider {

    @Autowired
    private AmqpTemplate amqpTemplate;


    /**
     * 注意一下:
     * 下面发送的时候 一定要绑定交换机 不要绑定路由键(没有意义 全是默认)
     *  amqpTemplate.convertAndSend("PZY_RADIO", str);//错误写法
     */
    @Async
    @Scheduled(cron = "*/1 * * * * ?")
    public void fanoutSend01() {

        String str = Math.random() * 1000 + "" + Math.random() * 1000;

        System.out.println("生产者1: <发布和订阅模式>定时(1次/s)发送 -> " + str);

        amqpTemplate.convertAndSend("PZY_RADIO","", str);
    }


}

この記事の概要と次のポータル

この記事が書かれた中で最も一般的な最初の 3 つは

RabbitTemplateの書き方はこれとよく似ており、効果は全く同じです

→ 次へ: springboot で 03-rabbitmq を使用する方法 (その 2)

 導入後の3つのモード

おすすめ

転載: blog.csdn.net/pingzhuyan/article/details/131528433