web-dev-qa-db-ja.com

RabbitMQ--キューからメッセージを選択的に取得する

私はRabbitMQを初めて使用し、熟考しているこの問題への優れたアプローチを考えていました。キューにサブスクライブし、特定の条件を満たすメッセージのみをプルするサービスを作成したいと思います。たとえば、特定の件名ヘッダーがメッセージに含まれている場合です。

私はまだRabbitMQについて学んでおり、これに取り組む方法のヒントを探していました。私の質問は次のとおりです。コンシューマーはどのようにしてキューから特定のメッセージのみをプルできますか?プロデューサーはどのようにしてメッセージに件名ヘッダーを設定できますか(それが正しい用語である場合でも)

15
larryq

RabbitMQはこの状況に最適です。あなたはあなたがやりたいことをするための多くのオプションがあります。理解を深めるために、ドキュメントを読むことをお勧めします。トピックまたは直接交換を使用することをお勧めします。トピックはより柔軟です。こんなふうになります。

プロデューサーコードはRabbitMQブローカーに接続し、特定の名前でExchangeを作成します。

プロデューサーは交換のために公開します。公開される各メッセージは、ルーティングキーとともに公開されます。

コンシューマーはRabbitMQブローカーに接続します。

コンシューマーがキューを作成

コンシューマーは、キューをエクスチェンジにバインドします。これは、プロデューサーで定義されているのと同じエクスチェンジです。バインディングには、この特定のコンシューマーに必要な各メッセージのルーティングキーも含まれます。

ログメッセージを公開していたとしましょう。ルーティングキーは、「log.info」、「log.warn」、「log.error」のようなものです。プロデューサーによって発行された各メッセージには、関連するルーティングキーが添付されます。次に、すべてのエラーメッセージを送信して電子メールで送信するコンシューマーと、すべてのエラーメッセージをファイルに書き込むコンシューマーがあります。したがって、メール送信者は、ルーティングキー「log.error」を使用して、キューから交換へのバインディングを定義します。このように、エクスチェンジはすべてのメッセージを受信しますが、メール送信者用に定義されたキューにはエラーメッセージのみが含まれます。ファイルロガーは、同じ取引所にバインドされた新しい個別のキューを定義し、異なるルーティングキーを設定します。必要な3つの異なるルーティングキーに対して3つの個別のバインディングを実行するか、ワイルドカード「log。*」を使用して、logで始まる交換からのすべてのメッセージを要求できます。

これは、やりたいことをどのように達成できるかを示す簡単な例です。

コード例については、 ここ を参照してください。具体的にはチュートリアル番号5です。

24
robthewolf

RabbitMQからメッセージを取得するには、最初にRabbitMQサーバーに接続する必要があります

public WebClient GetRabbitMqConnection(string userName, string password)
{
    var client = new WebClient(); 
    client.Credentials = new NetworkCredential(userName, password);
    return client;
}

次に、以下のコードを使用してRabbitMQからメッセージを取得します。

public string GetRabbitMQMessages(string domainName, string port, 
    string queueName, string virtualHost, WebClient client, string methodType)
{
    string messageResult = string.Empty;
    string strUri = "http://" + domainName + ":" + port + 
                    "/api/queues/" + virtualHost + "/";
    var data = client.DownloadString(strUri + queueName + "/");
    var queueInfo = JsonConvert.DeserializeObject<QueueInfo>(data);
    if (queueInfo == null || queueInfo.messages == 0)
               return string.Empty;
    if (methodType == "POST")
    {
        string postbody = "  
        {\"ackmode\":\"ack_requeue_true\",\"count\":
         \"$totalMessageCount\",\"name\":\"${DomainName}\",
         \"requeue\":\"false\",\"encoding\":\"auto\",\"vhost\" :
         \"${QueueName}\"}";
         postbody = postbody
                       .Replace("$totalMessageCount", queueInfo.messages.ToString())
                       .Replace("${DomainName}", domainName)
                       .Replace("${QueueName}", queueName);
         messageResult = client.UploadString(strUri + queueName + 
                          "/get", "POST", postbody);
    }
    return messageResult;
} 

これは、RabbitMQの実装に役立つと思います。

1
Punit Pandya

Rabbitmqの交換/ルーティングを最大限に活用することをお勧めします。メッセージの内容に応じて確認したい場合は、次のコードが1つの解決策です。

キューからメッセージを取得して確認し、関心のあるメッセージを選択的に確認します。

1つのメッセージをプル

GetResponse resp = channel.basicGet(QUEUE_NAME, false);

1つのメッセージを確認

channel.basicAck(resp.getEnvelope().getDeliveryTag(), false);

import com.rabbitmq.client.*;

public class ReceiveLogs {
    private final static String QUEUE_NAME = "hello";

    public static void main(String[] argv) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        try(Connection connection = factory.newConnection();
            Channel channel = connection.createChannel();){

            channel.queueDeclare(QUEUE_NAME, true, false, false, null);

            // pull one message and ack manually and exit
            GetResponse resp = channel.basicGet(QUEUE_NAME, false);
            if( resp != null ){
                String message = new String(resp.getBody(), "UTF-8");
                System.out.println(" [x] Received '" + message + "'");
                channel.basicAck(resp.getEnvelope().getDeliveryTag(), false);
            }
            System.out.println();
        }
    }
}

依存関係

compile group: 'com.rabbitmq', name: 'amqp-client', version: '5.8.0'
0
sully

一度に1つのメッセージを取得する場合は、取得コードに次のプロパティを追加してください。

Boolean autoAck = false;
model.BasicConsume(Queuename, autoAck);
model.BasicGet("Queuename", false);
model.BasicGet("Queuename", false); 

RabbitMQのこのプロパティを追加することにより、キューからメッセージを1つずつ取得できます。FIFO基準と同じ)

0