4ルーティング


公式文書アドレス: 4ルーティング


メッセージを選択的に受信します。

前提条件

このチュートリアルは、RabbitMQがインストールされており、ローカルホストポート(5672)で実行されていることを前提としています。

ルーティング

前のチュートリアルでは、簡単なログシステムを構築しました。ログメッセージを多くの受信者にブロードキャストできます。

このチュートリアルでは、それに機能を追加します-メッセージのサブセットのみをサブスクライブします。たとえば、重要なエラーメッセージのみをログファイルに送信し(ディスク領域を節約するため)、コンソールにすべてのログメッセージを出力することはできます。

練る

前の例では、バインディングを作成しました。次のようにコードを思い出してください。

channel.queueBind(queueName, EXCHANGE_NAME, "");

バインディングは、スイッチとキューの間の関係です。これは、次のように簡単に理解できます。キューはこの交換からのメッセージに関心があります。

バインディングは追加のroutingKeyパラメーターを使用できます。basic_publishパラメータとの混同を避けるために、これをと呼びますbinding keyバインディングキーを作成します。

channel.queueBind(queueName, EXCHANGE_NAME, "black");

バインディングキーの役割は、exchangeタイプによって異なります。以前に使用したfanoutスイッチ、その値を無視します。

ダイレクトスイッチ

前のチュートリアルのログシステムは、すべてのユーザーにメッセージをブロードキャストします。これを拡張して、重大度に基づいてメッセージをフィルタリングできるようにします。たとえば、errorレベルのログメッセージのみをディスクに書き込み、メッセージをディスクに書き込んwarningだりinfoログに記録したりしたくない場合があります。

私たちはfanoutスイッチを使用していますが、これはあまり柔軟性がなく、盲目的にしかブロードキャストできません。

我々はなりますdirectそれを交換してスイッチ。directスイッチの背後にあるルーティングアルゴリズムは単純です。メッセージは、バインディングbinding keyキーがメッセージのルーティングキーとrouting key完全に一致するキューに入ります

この点を説明するために、次の設定について考えてみます。

この設定では、direct交換がX2つのキューにバインドされていることがわかります。最初のキューはバインディングキーorangeでバインドされ、2番目のキューには2つのバインディングがあります。1つはバインディングキーblackで、もう1つはバインディングキーバインドされますgreen

このような設定では、ルーティングキーorange使用してスイッチに投稿されたメッセージはキューにルーティングされますQ1メッセージ付きblackまたはgreenルーティングキーがに行きますQ2その他のメッセージは破棄されます。

マルチバインディング


同じバインディングキーで複数のキューをバインドすることは完全に合法です。この例ではXとのQ1間にバインディングキーを追加できblackます。この場合、direct交換は交換のようにfanout機能し、一致するすべてのキューにメッセージをブロードキャストします。ルーティングキーblackを含むメッセージはとに送信さQ1Q2ます。

問題のログ

このモデルをロギングシステムで使用します。メッセージは、direct取引所ではなく取引所に送信されますfanout例としてログの重大度を示しrouting keyます。このようにして、受信プログラムは重大度に基づいてログを選択的に受信できるようになります。まず、ログを発行するコードを見てみましょう。

いつものように、最初にスイッチを作成する必要があります。

channel.exchangeDeclare(EXCHANGE_NAME, "direct");

メッセージを送信する準備ができました:

channel.basicPublish(EXCHANGE_NAME, severity, null, message.getBytes());

簡素化の問題のために、我々は、ログレベルがあることを前提とseverityすることができinfowarningerror

サブスクリプション

メッセージの受信は、1つの例外を除いて、前のチュートリアルと同じように機能します。関心のある重大度ごとに新しいバインディングを作成します。

String queueName = channel.queueDeclare().getQueue();

for(String severity : argv){
    
    
  channel.queueBind(queueName, EXCHANGE_NAME, severity);
}

それらをまとめる

EmitLogDirect.javaクラスコード:

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 * @author wangbo
 * @date 2019/10/23 11:24
 */
public class EmitLogDirect {
    
    
    //交换器名称
    private final static String EXCHANGE_NAME = "direct_logs";

    public static void main(String[] args) throws IOException, TimeoutException {
    
    
        //创建一个连接器连接到服务器
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        try(Connection connection = factory.newConnection()){
    
    
            //创建一个通道
            Channel channel = connection.createChannel();
            //声明交换器,设置交换器类型
            channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
            //从命令行接受参数
            //日志级别,路由键
            String severity = getSeverity(args);
            //日志消息
            String message = getMessage(args);
            //发布消息到交换器,并设置路由键
            channel.basicPublish(EXCHANGE_NAME, severity, null, message.getBytes("UTF-8"));
            System.out.println(" [x] Sent '" + message + "'");
        }
    }

    private static String getSeverity(String[] strings) {
    
    
        if (strings.length < 1) {
    
    
            return "info";
        }
        return strings[0];
    }

    private static String getMessage(String[] strings) {
    
    
        if (strings.length < 2) {
    
    
            return "Hello World!";
        }
        return joinStrings(strings, " ", 1);
    }

    private static String joinStrings(String[] strings, String delimiter, int startIndex) {
    
    
        int length = strings.length;
        if (length == 0) {
    
    
            return "";
        }
        if (length <= startIndex) {
    
    
            return "";
        }
        StringBuilder words = new StringBuilder(strings[startIndex]);
        for (int i = startIndex + 1; i < length; i++) {
    
    
            words.append(delimiter).append(strings[i]);
        }
        return words.toString();
    }
}

ReceiveLogsDirect.javaクラスコード:

import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 * @author wangbo
 * @date 2019/10/22 18:25
 */
public class ReceiveLogsDirect {
    
    
    //交换器名称
    private final static String EXCHANGE_NAME = "direct_logs";

    public static void main(String[] args) throws IOException, TimeoutException {
    
    
        //创建一个连接器连接到服务器
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        //创建一个通道
        Channel channel = connection.createChannel();
        //声明交换器,设置交换器类型
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
        //获取临时队列的名称
        String queueName = channel.queueDeclare().getQueue();
        //将临时队列和交换器绑定,进行多重绑定
        if (args.length < 1) {
    
    
            System.err.println("Usage: ReceiveLogsDirect [info] [warning] [error]");
            System.exit(1);
        }
        for (String severity : args) {
    
    
            channel.queueBind(queueName, EXCHANGE_NAME, severity);
        }
        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
        //回调对象
        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
    
    
            String message = new String(delivery.getBody(), "UTF-8");
            System.out.println(" [x] Received '" + message + "'");
        };
        //消费者监听
        channel.basicConsume(queueName, true, deliverCallback, consumerTag -> {
    
    });
    }
}

通常どおりにコンパイルします(コンパイルとクラスパスの提案については、チュートリアル1を参照してください)。便宜上、例を実行するときは、クラスパスの環境変数$CP(つまりWindows、上記%CP%)を使用します。

javac -cp $CP ReceiveLogsDirect.java EmitLogDirect.java

情報をファイルに保存warningしてerror(ではなくinfo)ログに記録したいだけの場合は、コンソールを開いて次のように入力します。

java -cp $CP ReceiveLogsDirect warning error > logs_from_rabbit.log

画面にすべてのログ情報を表示する場合は、新しいターミナルを開きます。

java -cp $CP ReceiveLogsDirect info warning error
# => [*] Waiting for logs. To exit press CTRL+C

たとえば、errorログメッセージを発行するには、次のように入力します。

java -cp $CP EmitLogDirect error "Run. Run. Or it will explode."
# => [x] Sent 'error':'Run. Run. Or it will explode.'

5パターンに基づいてメッセージを聞く方法を学ぶためにレッスンを読み続けてください

おすすめ

転載: blog.csdn.net/wb1046329430/article/details/115283884