前回の記事では、シンプルなログシステムを構築しました。ログメッセージを複数の受信者にブロードキャストできます。
この記事では、将来的にメッセージの一部のみを受信する機能を追加します。たとえば、一部のエラーログのみをファイルに保存し、すべてのログをコンソールに出力します。
1.バインディング
前回の記事ではバインディングを作成しました。コードは次のとおりです。
channel.queueBind(queueName, EXCHANGE_NAME, "");
バインディングは、交換とキューの間の関係です。これは、次のように簡単に理解できます。このキューは、それに関連する交換メッセージに関心があります(元のテキストは、キューがこの交換からのメッセージに関心があることです)。
バインディングでは、既存のroutingKeyパラメータを使用できます。basic_publishパラメーターとの混同を避けるために、これをバインディングキーと呼びます。以下は、キーを使用してバインディングを作成する方法です。
channel.queueBind(queueName, EXCHANGE_NAME, "black");
バインディングキーの意味は、交換の種類によって異なる場合があります。タイプFanoutの交換の場合、バインディングキーは無視されます。
2.直接交換
前の記事のログシステムは、すべてのログメッセージをすべてのコンシューマーにブロードキャストします。ログレベルに基づいてログメッセージをフィルタリングするように拡張します。例:エラーレベルのログのみをディスクファイルに書き込み、他のレベルのログメッセージは除外します。
以前にファンアウトタイプの交換を使用しましたが、この方法では柔軟性があまりありません。
ここでは、直接タイプの交換を使用します。直接型交換のルーティングアルゴリズムは非常に単純です。メッセージがこのキューに到達できる場合、バインディングキーとルーティングキーは正確に一致する必要があります。
この真実を説明するには、以下の説明をご覧ください。
このような構造では、直接型の交換Xを見ることができ、それにバインドされた2つのキューがあります。最初のキューはバインドキーとしてオレンジとXを交換するようにバインドされ、2番目のキューは2つのバインドキー(黒と緑)とXを交換するようにバインドされています。
このような設定では、メッセージはエクスチェンジにプッシュされます。使用されているルーティングキーがオレンジの場合、メッセージはQ1にルーティングされます。使用されているルーティングキーが黒または緑の場合、メッセージはQ2にルーティングされます。で。他のすべてのメッセージは破棄されます。
3.複数のバインディング
同じバインディングを使用して、複数のキューを同じ交換にバインドすることもできます。たとえば、前の例に基づいて、XとQ1の間にバインディングキー名blackを追加します。この場合、ここでの直接型交換はファンアウト型と同じであり、メッセージをすべてのキューにプッシュできます。ルーティングキーが黒のメッセージはQ1とQ2にプッシュされます。
4.ログの送信(ログの送信)
ファンアウトタイプの交換ではなく、直接タイプを使用する代わりに、このモデルを使用します。ログレベルをルーティングキーとして使用し、受信側は、設定したログレベルをバインディングキーとしてメッセージを受信します。最初に起動ログを確認します。
前と同じように、まず交換を作成します。
channel.exchangeDeclare(EXCHANGE_NAME、 "direct");
次に、メッセージを送信する準備をします。
channel.basicPublish(EXCHANGE_NAME、severity、null、message.getBytes());
ここでの「重大度」は、「情報」、「警告」、「エラー」などです。
5.サブスクリプション(サブスクリプション)
ここで受信されるメッセージは、前のブログ投稿と同じですが、1つの例外があります。対象の各ログレベルをバインドします。
文字列queueName = channel.queueDeclare()。getQueue();
for(String severity:argv){
channel.queueBind(queueName、EXCHANGE_NAME、severity);
}
6、最终实现
EmitLogDirect.java的代码:
复制代码
public class EmitLogDirect {
private static final String EXCHANGE_NAME =“ direct_logs”;
public static void main(String [] argv)
は、java.io.IOExceptionをスローします{
ConnectionFactory factory = new ConnectionFactory();
factory.setHost( "localhost");
接続connection = factory.newConnection();
チャネルチャネル= connection.createChannel();
//声明direct类型的exchange
channel.exchangeDeclare(EXCHANGE_NAME, "direct");
//ログレベルを取得します
。String severity = getSeverity(argv);
//拿到日志消息
String message = getMessage(argv);
//指定routing key,发送消息
channel.basicPublish(EXCHANGE_NAME, severity, null, message.getBytes());
System.out.println(" [x] Sent '" + severity + "':'" + message + "'");
channel.close();
connection.close();
}
//..
}
复制代码
ReceiveLogsDirect.java的代码:
复制代码
public class ReceiveLogsDirect {
private static final String EXCHANGE_NAME =“ direct_logs”;
public static void main(String [] argv)
は、java.io.IOException、
java.lang.InterruptedExceptionをスローします{
ConnectionFactory factory = new ConnectionFactory();
factory.setHost( "localhost");
接続connection = factory.newConnection();
チャネルチャネル= connection.createChannel();
//声明direct类型的exchange
channel.exchangeDeclare(EXCHANGE_NAME, "direct");
String queueName = channel.queueDeclare().getQueue();
if (argv.length < 1){
System.err.println("Usage: ReceiveLogsDirect [info] [warning] [error]");
System.exit(1);
}
//绑定我们需要接收的日志级别
for(String severity : argv){
channel.queueBind(queueName, EXCHANGE_NAME, severity);
}
System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume(queueName, true, consumer);
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
String routingKey = delivery.getEnvelope().getRoutingKey();
System.out.println(" [x] Received '" + routingKey + "':'" + message + "'");
}
}
}
コードをコピー
:3つのジャーナルレシーバ実行する
受信エラーレベルのログと情報を:
エラーレベルのログを受信します。
情報レベルのログを受信します。
2つのログジェネレーターを実行します。
エラーレベルのログを生成します。
、
情報レベルのログを生成します。
受信側の変更を確認し
ます。エラーレベルの受信側を受信し、エラーレベルのログのみを受信します。
情報レベルの受信者を受信し、情報レベルのログのみを受信します。
エラーレベルと情報レベルのログ、および情報レベルとエラーレベルのログの両方のレシーバー:
7.まとめ:
プロデューサー側のルーティングキーを覚えてから、コンシューマー側のバインディングキーを以前のルーティングキーとして設定するには、直接タイプの交換を使用して、必要な情報を取得できます。