MQを用いたマイクロサービス - RabbitMQの

コンセプト

メッセージは何ですか

  • これは、2つの別々のシステム間のメッセージのデータ転送を指します。両方のシステムは、2つのプロセスすることができ、二つのコンピュータすることができます。
  • メッセージは、プラットフォームに依存しないと、言語に依存しません!

キューとは何ですか

  • キューは、内部的に実装されるデータ構造、配列またはリンクされたリストです、
  • キューの末尾の特性は、キューヘッドは除去のみに配置される、すなわち先入れ先出し[FIFO]
  • キューの操作は、チームとチームをしている
    あなたはプログラムが生成したコンテンツを持っているし、その後チーム(プロデューサー)に、ある
    別のプログラムは、コンテンツを読み込んで、コンテンツチーム(消費者)

メッセージキューとは何ですか

  • 容器等のキューが送信メッセージ中にメッセージを保持するために使用:これは単にことを意味します。
    キューチャネルは、メッセージは、コンテナに格納され、送信メッセージである
    状況に応じて、FIFO、優先キューとの間の差があってもよいです。

なぜあなたは、メッセージキューを使用したくありません

デカップリング

メッセージキューは、ビジネス・ロジックを分離することができ、呼び出し側は、全体のみロジックが終了するのを待つのではなく、注文を与える必要があります!

たとえば:あなたは、登録の3つのサービスを呼び出すために必要がある場合、これらの3つのサービスは、独立して、3台のサーバー、非同期呼び出しに直接メッセージを送信するためにどのステップの実装に配置することができます。登録された効率ははるかに高速で
、確認用のリンクを登録メッセージを送信する:メールサービスを呼び出すために
第三者検証サービスを呼び出す:真と偽のアイデンティティ情報を確認、
ユーザのサービスを呼び出す:ユーザー登録を。

同期非同期転送

プロセスが非同期に処理することができます同期する
メッセージキューにメッセージを書き込み、非本質的なビジネスロジックが非同期で動作し、応答速度の

オーダーが終了し、直接ユーザーに結果を返した、唯一の50ミリ秒を要し、その後、MQを通知フォローアップのことを行います。

クリッピング

時間[]サービス要求の高度に並行シナリオ平滑短いスパンで
シャント:要求キューに大きなバースト要求は、後端に耐えることができます。

使用している場合のメッセージは、それをキューに

RPC / RESTで、下流の実行結果をフォロー
MQと、実行結果下流と心配していない、RPC / RESTずに
敏感、トランザクションおよび遅延のための強い必要があることを保証するために、RPCメッセージキューよりも優れています。
例:
サーバーは、増加することができないバックエンド容量の場合には、10秒間1000件の受注を1秒、1秒のスパイク活動のための100件の受注を扱うが、来ることができ
ますが、メッセージがキュー圧力万の要求の合計をキューに使用することができますここで、元の消費者(むしろ直接注文データの損失ダウンよりも)すべての要求を処理し終えた100秒後に、バックグラウンドを処理する能力に応じ。

注意を払います

MQの懸念は、「通知」ではなく「契約です

簡単に言えば:MQメッセージは、消費者に知らせるために合わせて保証することができ、例えば、消費者の処理ロジックを保証することはできません。順序は実行されません。
3つのメッセージがあるとしますM1(テキストメッセージ)、M2(電子メール)、M3(プッシュステーション)
消費がこの順であるときM3、M2、M1 MQがメッセージを確実に、:順序キューではある
が、保証することはできません消費者は、最初に、最終的には、電子メール、テキストメッセージなどを送って、ステーションをプッシュ送信し、しなければならない
3つのコンシューマー営業時間、受信したメッセージの実行が同じではない可能性が高いため。

インストールラビットMQ

インストールアーラン

Erlangのは、([「əは:læŋ])CS-Labの開発の管轄下にスウェーデンの通信機器メーカー、エリクソンから構成され、一般的な目的指向並行プログラミング言語は、それが大規模な同時アクティビティに対応できるプログラミング言語を作成することを目指していますおよび動作環境。

RPM --import https://packages.erlang-solutions.com/rpm/erlang_solutions.asc

VI /etc/yum.repos.d/xxx(xxxはYUMファイルの既存のリストの任意のディレクトリである)
次の書類の含有量の増加:

[erlang-solutions]
name=Centos $releasever - $basearch - Erlang Solutions
baseurl=https://packages.erlang-solutions.com/rpm/centos/$releasever/$basearch
gpgcheck=1
gpgkey=https://packages.erlang-solutions.com/rpm/erlang_solutions.asc
enabled=1

ヤムキャッシュ情報が生成さ
yumをmakecache

アーランを取り付け
アーラン-Yインストールyumを

インストール結果を確認し、Erlangのバージョンを参照
ERLの-versionを

インストールうさぎMqを

  • wgetのhttps://www.rabbitmq.com/releases/rabbitmq-server/v3.6.6/rabbitmq-server-3.6.6-1.el6.noarch.rpm --no-チェックイン証明書

  • RPM --import https://www.rabbitmq.com/rabbitmq-release-signing-key.asc

  • yumをRabbitMQのサーバ・3.6.6-1.el6.noarch.rpmをインストール-y

リファレンスを挙げることができる:
マウントラビットMQ

ラビットMQを開始

:デーモンはroot権限で実行し、システムを自動的に起動するように設定されている
のchkconfig RabbitMQのサーバー-ON
のRabbitMQサービス開始
サービスのRabbitMQサーバースタートを

RabbitMQのサービス状況確認
サービスのRabbitMQサーバのステータス

WEB管理インターフェイスのRabbitMQのインストール

RabbitMQの-プラグインはrabbitmq_managementを有効にします

RabbitMQのユーザー設定と権限付与

アカウントの作成
rabbitmqctlのADD_USERテスト123456
設定されたユーザーの役割
rabbitmqctl set_user_tagsテストの管理者
ユーザー権限を設定する
「rabbitmqctl set_permissions -p「/」テスト」。「「*」。」
セットアップが完了した後、あなたは現在のユーザーとロールを表示することができます(サービスを開く必要があります)
rabbitmqctlのlist_users

管理インタフェースにアクセスするためのWEBブラウザ

HTTP://のRabbitMQ-SERVER-IP:15672
のRabbitMQ RabbitMQの-SERVER-IP IPに従ってホストの物理的なマシンです。
15672を提供RabbitMQのWEB管理インターフェイスポート

RabbitMQの原理

回路図

メッセージ

ヘッダとボディ:2つの部分があります。
ヘッダーには、プロデューサーに設定された各種属性は、追加で
これらのプロパティは、キューを受け取ったキャッシュは、優先度が非常に似ているかどうかのメッセージを制御することができます。
ボディは、送信時に影響はありません、それは目に見えるブローカーバイナリデータストリームではなく、データを送信するために実際に必要です。
(RabbitMQので、メッセージ)をシリアライズ(直列化を実装する必要があり、Javaオブジェクトの任意の型に格納されてもよいです)

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

クライアントアプリケーションは、スイッチに発表されたメッセージであります

消費者の消費者ニュース

これは、メッセージキューからメッセージを取得するために、クライアント・アプリケーションを表します。

交換スイッチ。

キューのプロデューサーとメッセージをルーティングするサーバーから送信されたメッセージを受信します。
スイッチの3つの一般的なタイプの
ダイレクト(完全一致をパブリッシュおよびサブスクライブ)
ファンアウト(ブロードキャスト)
トピック(テーマ、ルールマッチ)

ルーティングルーティングキーのキー

RabbitMQのは、どのルールキューにメッセージを配信することを決定しました。
スイッチのルーティングキーでキューにバインドされました。
MQメッセージがサーバに送信され、メッセージは、ルーティングキーを持っても、空の場合も、一致および結合のために使用されるのRabbitMQルーティングキー。
それらが一致する場合は、メッセージがキューに配信されます。
ない場合は、メッセージがブラックホールに入ります。

バインドバインド

メッセージキュー[]および[]スイッチとの間の関連付けのために。結合は、キーベースのルーティングルールおよびメッセージキューを接続するスイッチであり、スイッチが結合することにより構成されるルーティングテーブルであると理解することができます。

キューのメッセージ・キュー。

消費者に送信されるまでメッセージを保存します。
これは、メッセージのコンテナで、メッセージは終わりです。メッセージは、1つ以上のキューに入れることができます。
メッセージは、消費者がそれを削除します。このキューにリンクするのを待っている、内部のキューに入っています。

接続

これは、確立されたTCPリンクウサギのサーバーやサービスを指します。

チャネル

仮想TCPリンクされたチャネル、。TCPは、コネクション上の複数のチャネルを作成することができます。
TCPは、開封後、それはAMQPチャネルを作成します。解放メッセージかどうか、メッセージ、サブスクリプションのキューを受け、これらのアクションは、チャネルを介して達成されます

仮想ホスト

これは、スイッチ、メッセージキュー、および関連オブジェクトのセットを表します。
これは、独自のキュー、スイッチ、結合権威機構のバーチャルホストで、本質的RabbitMQのサーバのミニバージョンです。
同様に、N個のデータベースとしてMySQLがあります。

Borker

これは、メッセージキューサーバエンティティを表します。RabbitMQのは、全体的なアプリケーションです。

交換機とキューの関係

キースイッチとメッセージがルーティングキューとキースイッチの試合でルーティングのキーを持っている場合は、一緒にバインドされたキューをルーティングすることにより、そのメッセージは、結合キューにルーティングされます。
つまり、プロセスメッセージキューで、メッセージが特定のメッセージキューに一致させることにより、第一のスイッチを介して分散キーの次の経路指定スイッチを移動します。
ルーティングルールは、キーマッチとして理解することができます。

なぜRabbitMQのチャネルが必要なのでしょうか?なぜTCP通信を指示しませんか?

特に大規模なTCPの創造と破壊のオーバーヘッド。
3ウェイハンドシェイクを作成する必要が、解散し、4回を破壊する必要があります。
あなたが信じていない場合は、そのアプリケーションが第2ピークのリンクあたりのメッセージ数十万人が第二のTCPリンク数あたりの資源の巨大な廃棄物、およびオペレーティングシステムの原因となりますと、TCPラビットにリンクします何で制限され、パフォーマンスのボトルネックが発生します。
原理は、TCP接続を用いて、チャネル、マルチスレッド、複数のチャネルのスレッドチャネルです。TCPコネクションは、1秒あたりの要求数千ものパフォーマンスのボトルネックになっていない、無制限のチャネルを収容することができます。

一般的なプロセス

ブローカーへの消費者の登録キューリスナー(RabbitMQの)

消費者の最初のニュースの消費量は、時にキューの状態が変化し、キューの状態を監視するために、キューリスナーを登録し
、登録キューリスナーの時間を提供する必要があります。

  • 交換(スイッチ)情報:
    交換タイプ(Dircet直接、トピックトピック、ファンアウト放送)は、自動的に削除するかどうか、名前を切り替えます
  • キュー(待ち行列)情報、
    自動的に削除するかどうかの名前、
  • そして、ルーティングキー情報(キーをルーティング)。
    キー定義された値ので、この値は、キューExchangeと接続識別です。

プロデューサーは、キューにメッセージを送信します

交換(スイッチ)メッセージヘッダ内の情報を指定し、プロデューサのRabbitMQにメッセージを送信し、ルーティングキー(キールーティング)情報

ブローカー(RabbitMQの)一致

プロデューサーによるRebbitMQ交換器は、Exchange名を指定し、ルーティングのキーを指定することで、対応するキューを見つけ、メッセージがキューに登録されました。
キューの状態が変化し、消費者のリスナーはを通じて、消費メッセージが表示されます。

ニュースの消費のクラスタを行うにはどのように消費者

私はテキストメッセージサービスを送信すると仮定し、SMSの安定性を確保するために、SMSは、クラスタサービスを作った、この時間MQメッセージが消費される方法です。

交換

その役割:サーバーのキューにメッセージプロデューサとルートに送信されたメッセージを受信します。

取引所は、対応するキューのルーティングキーにマッチしています。

我々は、Exchangeキュー内型とのRabbitMQを知っておく必要があり、同様にルーティングキーは、最終消費者によって提供され、
その後プロデューサーのみExchangeルーティングキーを提供し、ブローカは、プロデューサの名前を提供するために、取引に応じて、対応するスイッチを見つけ、
ルーティングキーに応じ対応するキューと一致するように、メッセージキューに置か。

取引所のいくつかの種類があります:
ルーティングキー直接交換は、全体のマッチの種類です。
取引所の主要なトピック別のルーティングは、一致またはあいまい一致の一部です。
取引所のルーティングキーファンアウト型が一致を放棄することです。
同じ試合では必ず取引所で制限されている、Exchangeは同じ試合です。

信頼性のメッセージ処理

消息持久化

メッセージはMQで失われていないことを確認してください。

メッセージの損失の場合

  • 消費者は、起動しない、とプロデューサーは、メッセージが失われます、メッセージを送りました。
  • 消費者のダウンタイムの全てが、キューが自動削除される場合は、メッセージはまだ失われてしまいます

メッセージ受信確認。

必要性

消費者は、その後ackをされていない場合、異常なまたはネットワークの中断を発揮するために消費プログラムのプロセスにメッセージを受け取る、MQは、データの損失を引き起こし、削除されたメッセージを入れました。

プロセス

ニュースは消費者にプッシュRabbitMQの、RabbitMQのは、メッセージのロックされた状態でロックするニュースはプッシュが二次消費者で繰り返されることはありません壊れます。
他の消費者は、次のメッセージを過ごすRabbitMQのにACKを送信し続けることができ、RabbitMQのが削除されますと、確認完了後のニュース消費者ニュースの消費者。
特定の時間のRabbitMQ消費者よりも多くがACKを受信しない場合、ニュースはメッセージの順序を保証するため、バックキューの先頭に、ロックが解除されます。

メモリー・リークが発生します。

消費者は、メッセージ確認を扱っていない場合、それは深刻な結果につながります。
消費者のすべてが通常のフィードバック情報を確認し、状態を聞いてやめなかったと仮定すると、そのメッセージを永続的に保存され、メッセージは通常消費されるまでロックアップされます。
メッセージプロデューサは、メッセージがRabbitMQのは、「メモリリーク」の問題をもたらすサーバ用メモリのために蓄積する、RabbitMQのにメッセージを送信し続ける続けます。

ソリューション:

  • コンフィギュレーション・メッセージの再試行。
    グローバルコンフィギュレーションファイルによって、メッセージの再試行メカニズムの消費を開き、再試行回数を設定します。
    RabbitMQのは、消費者からのフィードバックの確認を受けていない場合は再試行の回数を決定するメッセージをプッシュし、使用時後の再試行の回数は、関係なく、それが承認フィードバックを受信したかどうかの、RabbitMQのは、構成に応じて可能なメモリリークを回避するために、メッセージを削除します。
    次のように最後には、消費者の具体的な構成は以下のとおりです。
#开启重试
spring.rabbitmq.listener.retry.enabled=true
#重试次数,默认为3次
spring.rabbitmq.listener.retry.max-attempts=5
  • 例外処理の符号化
    符号によってモード例外処理は、通常の実行メッセージの確認機構を確実にします。
    以下のような:catchブロック、未処理のメッセージの成功は、MQを再送信します。
    例えば:キャッチコード、ローカル再試行ロジック(タイミングスレッドプールタスクを使用して3回繰り返す。)
    としては:キャッチコード、メッセージは、メッセージを消去するためにDBの例外は、タイミングタスクに格納されています。

繰り返さ消費

  • 待っているのRabbitMQは、ACKタイムアウトは1秒であると仮定し、消費者のニュースの消費者は2Sを必要とし、このメッセージが戻って消費を繰り返し登場キューの中に、ACK待ちタイムアウトを表示されます。
  • 接続割り込みニュース消費者を受け取った後、メッセージがキューに再配置されます、消費が繰り返されます。
  • 異常が確認応答メカニズムを送信できない場合、メッセージ処理システムの消費者側が起こると仮定する。

[ソリューション]

  • テスト消費者の実行の持続時間、および時間MQのACKタイムアウトの合理的な長さを定義します。
  • メッセージバージョンやタイムスタンプなどの追加、またはビジネスIDに基づいて再宣告します。
    複製することはできませんあなたは必須消費がない場合は、判断することが最善ではありません。

RabbitMQのメッセージの確認応答がデフォルトで有効になって、それが閉じられたことはお勧めしません。

ダイレクト・スイッチ

標準的なスイッチを[パブリッシュ/サブスクライブ]達成するポイント(地点間)です。ここで、交換は(交流)です。

ビジネスシーン

生産者側のコード実装

ポンポン依存

継承スプリング・ブート・スターター・親
導入のRabbitMQ:春AMQP-ブートStarter-
RabbitMQの依存。RabbitMQのは、ばねブートアクセスの実装を統合するために行われました。
春の雲も作られた統合ロジックをspringboot。春の雲の中で直接使用するためのRabbitMQ依存。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.bjsxt</groupId>
    <artifactId>rabbitmq-direct-producer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>rabbitmq-direct-producer</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.13.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        
        <!-- rabbitMQ的依赖。rabbitmq已经被spring-boot做了整合访问实现。
            spring cloud也对springboot做了整合逻辑。所以rabbitmq的依赖可以在spring cloud中直接使用。
         -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

コンフィギュレーションのRabbitMQ

spring.application.name=direct-producer

server.port=8082

# 必要配置
# 配置rabbitmq链接相关信息。key都是固定的。是springboot要求的。
# rabbitmq安装位置
spring.rabbitmq.host=192.168.1.122
# rabbitmq的端口
spring.rabbitmq.port=5672
# rabbitmq的用户名
spring.rabbitmq.username=test
# rabbitmq的用户密码
spring.rabbitmq.password=123456

メッセージのキャリアオブジェクトを作成します。

  • オブジェクトは、直列化インターフェイスを実装する必要があります。
    ここでgetterメソッドとsetterメソッドは省略。
/**
 * 消息内容载体,在rabbitmq中,存储的消息可以是任意的java类型的对象。
 * 强制要求,作为消息数据载体的类型,必须是Serializable的。
 * 如果消息数据载体类型未实现Serializable,在收发消息的时候,都会有异常发生。
 */
public class LogMessage implements Serializable {

    private Long id;
    private String msg;
    private String logLevel;
    private String serviceType;
    private Date createTime;
    private Long userId;
    public LogMessage() {
        super();
    }
    public LogMessage(Long id, String msg, String logLevel, String serviceType, Date createTime, Long userId) {
        super();
        this.id = id;
        this.msg = msg;
        this.logLevel = logLevel;
        this.serviceType = serviceType;
        this.createTime = createTime;
        this.userId = userId;
    }
    @Override
    public String toString() {
        return "LogMessage [id=" + id + ", msg=" + msg + ", logLevel=" + logLevel + ", serviceType=" + serviceType
                + ", createTime=" + createTime + ", userId=" + userId + "]";
    }
}

テストクラスを書きます

[AmqpTemplateデフォルト実装RabbitMQのインタフェース[R] RabbitTemplateオブジェクトがメッセージを送信提供スプリングブートを使用します。
前記convertAndSend方法は、メッセージを送信することができる:
この方法では、入ってくる通常のJavaオブジェクトであり、必要性のRabbitMQとする対象におけるメッセージ・タイプに変換され、RabbitMQのにメッセージを送信します。
パラメータ:スイッチの名前。文字列の入力
パラメータの二つを:ルーティングキー。文字列型
パラメータ3:メッセージを、メッセージ・コンテンツ・オブジェクトが送信されるべきです。タイプオブジェクト

/**
 * Direct交换器
 * Producer测试。
 * 注意:
 * 在rabbitmq中,consumer都是listener监听模式消费消息的。
 * 一般来说,在开发的时候,都是先启动consumer,确定有什么exchange、queue、routing-key。
 * 然后再启动producer发送消息。
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes=SpringbootServerApplication.class)
public class QueueTest {

    @Autowired
    private AmqpTemplate rabbitAmqpTemplate;
    /*
     * 测试消息队列
     */
    @Test
    public void testSendInfo()throws Exception{
        Long id = 1L;
        while(true){
            Thread.sleep(1000);
            final LogMessage logMessage = new LogMessage(id, "test log", "info", "订单服务", new Date(), id);
                           
            this.rabbitAmqpTemplate.convertAndSend("log.direct", "log.error.routing.key", logMessage);
            id++;
        }
    }
    /*
     * 测试消息队列
     */
    @Test
    public void testSendError()throws Exception{
        Long id = 1L;
        while(true){
            Thread.sleep(1000);
            final LogMessage logMessage = new LogMessage(id, "test log", "info", "订单服务", new Date(), id);
            this.rabbitAmqpTemplate.convertAndSend("log.direct", "log.info.routing.key", logMessage);
            id++;
        }
    }
}

消費者側の実装

ポンポン

そして、同じプロデューサーを終了

情報レベルのログコンシューマコードを書きます

@Component
@RabbitListener(
            bindings=@QueueBinding(
                    value=@Queue(value="log.error",autoDelete="false"),
                    exchange=@Exchange(value="log.direct",type=ExchangeTypes.DIRECT),
                    key="log.error.routing.key"
            )
        )
public class ErrorReceiver {

    /**
     * 消费消息的方法。采用消息队列监听机制
     * @RabbitHandler - 代表当前方法是监听队列状态的方法,就是队列状态发生变化后,执行的消费消息的方法。
     * 方法参数。就是处理的消息的数据载体类型。
     */
    @RabbitHandler
    public void process(LogMessage msg){
        System.out.println("Error..........receiver: "+msg);
    }
}

@RabbitListener

 可以注解类和方法,
    注解类:当表当前类的对象是一个rabbit listener。监听逻辑明确,可以由更好的方法定义规范。 必须配合@RabbitHandler才能实现rabbit消息消费能力。
    注解方法:代表当前方法是一个rabbit listener处理逻辑。方便开发,一个类中可以定义若干个listener逻辑。方法定义规范可能不合理。
    代表当前类型是一个rabbitmq的监听器。
     bindings:绑定队列

@QueueBinding

    @RabbitListener.bindings属性的类型。绑定一个队列。
     value:绑定队列, Queue类型。
     exchange:配置交换器, Exchange类型。
     key:路由键,字符串类型。

@Queue - キュー。

    value:队列名称
     autoDelete:是否是一个临时队列(也就是所有的consumer关闭后是否删除队列)
         true : 删除
         false:如果queue中有消息未消费,无论是否有consumer,都保存queue。

@Exchange -スイッチ
value:为交换器起个名称 type:指定具体的交换器类型
@RabbitHandler

  代表当前方法是监听队列状态的方法,就是队列状态发生变化后,执行的消费消息的方法。

コードレベルのログの消費を書くエラー

@Component
@RabbitListener(
            bindings=@QueueBinding(
                    value=@Queue(value="log.info",autoDelete="false"),
                    exchange=@Exchange(value="log.direct",type=ExchangeTypes.DIRECT),
                    key="log.info.routing.key"
            )
        )
public class InfoReceiver {

    @RabbitHandler
    public void process(LogMessage msg){
        System.out.println("Info........receiver: "+msg);
    }
}

トピックスイッチ

シーン

顧客サービス、注文サービス、商品およびサービスの3つのサービスがあり、各サービスがログを持っていますが、ログは情報、エラーが分割され、他のレベルは、ログを収集するためにMQを使用して達成することができます。
ダイレクトスイッチを使用して、あなたは、少なくとも6つのキューを定義する必要があります。

トピック交換器は、消費者側の開発を簡素化することとします。

実現

  • POM、上記と同様の依存性を示します。
  • 修正最終消費者Exchangeルーティングキーの主な種類と対応するルール

    消費者側

    消費者の取り扱いエラーログ
@Component
@RabbitListener(
            bindings=@QueueBinding(
                    value=@Queue(value="${mq.config.queue.error}",autoDelete="true"),
                    exchange=@Exchange(value="${mq.config.exchange}",type=ExchangeTypes.TOPIC),
                    key="*.log.error"
            )
        )
public class ErrorReceiver {

    @RabbitHandler
    public void process(String msg){
        System.out.println("......Error........receiver: "+msg);
    }
}

消費者の情報を扱うログイン

@Component
@RabbitListener(
            bindings=@QueueBinding(
                    value=@Queue(value="${mq.config.queue.info}",autoDelete="true"),
                    exchange=@Exchange(value="${mq.config.exchange}",type=ExchangeTypes.TOPIC),
                    key="*.log.info"
            )
        )
public class InfoReceiver {
    @RabbitHandler
    public void process(String msg){
        System.out.println("......Info........receiver: "+msg);
    }
}

生産終了

コモディティログ情報

@Component
public class ProductSender {

    @Autowired
    private AmqpTemplate rabbitAmqpTemplate;
        /*
     * 发送消息的方法
     */
    public void send(String msg){
        //向消息队列发送消息
        //参数一:交换器名称。
        //参数二:路由键
        //参数三:消息
        this.rabbitAmqpTemplate.convertAndSend("log.topic","product.log.info", "product.log.info....."+msg);
        this.rabbitAmqpTemplate.convertAndSend("log.topic","product.log.error", "product.log.error....."+msg);
    }
}

ユーザーがメッセージを送信します

@Component
public class UserSender {

    @Autowired
    private AmqpTemplate rabbitAmqpTemplate;
    
    /*
     * 发送消息的方法
     */
    public void send(String msg){
        //向消息队列发送消息
        //参数一:交换器名称。
        //参数二:路由键
        //参数三:消息
        this.rabbitAmqpTemplate.convertAndSend("log.topic","user.log.info", "user.log.info....."+msg);
        this.rabbitAmqpTemplate.convertAndSend("log.topic","user.log.error", "user.log.error....."+msg);
    }
}

注文コードのように省略。

ファンアウト・スイッチ

これは簡単です、あなたは直接、リスト上の最終消費者と生産者のルーティングキーの上に配置する必要はありません。

おすすめ

転載: www.cnblogs.com/wangsen/p/11057714.html