首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

RabbitMQ 進階教程(四):RPC 遠程過程調用模式實戰

     編輯:Java 綜合教學

RPC 模式核心思想

客戶端發送請求 → 服務端處理 → 返回響應。RabbitMQ 通過 Callback Queue + Correlation ID 實現異步請求-響應匹配。

關鍵消息屬性

架構流程

  1. 客戶端啟動 → 聲明獨占匿名回調隊列(隨機名、連接關閉自動刪除)。
  2. 發送請求到 rpc_queue,附帶 replyTo(回調隊列)+ correlationId(UUID)。
  3. 服務端消費 rpc_queue,處理業務,發送結果到 replyTo 隊列,攜帶相同 correlationId。
  4. 客戶端監聽回調隊列,收到消息比對 correlationId,匹配則返回調用者。

服務端代碼

public class RPCServer {
    private static final String RPC_QUEUE = "rpc_queue";

    public static void main(String[] args) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        try (Connection conn = factory.newConnection();
             Channel ch = conn.createChannel()) {
            ch.queueDeclare(RPC_QUEUE, false, false, false, null);
            ch.basicQos(1); // 公平分發,每次只處理一條
            QueueingConsumer consumer = new QueueingConsumer(ch);
            ch.basicConsume(RPC_QUEUE, false, consumer);
            System.out.println("RPC Server awaiting requests...");

            while (true) {
                QueueingConsumer.Delivery delivery = consumer.nextDelivery();
                AMQP.BasicProperties props = delivery.getProperties();
                AMQP.BasicProperties replyProps = new AMQP.BasicProperties.Builder()
                    .correlationId(props.getCorrelationId()).build();

                String msg = new String(delivery.getBody(), "UTF-8");
                int n = Integer.parseInt(msg);
                System.out.println("Computing fib(" + n + ")");
                String response = String.valueOf(fib(n));

                ch.basicPublish("", props.getReplyTo(), replyProps, response.getBytes());
                ch.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
            }
        }
    }

    private static int fib(int n) {
        return (n == 0 || n == 1) ? n : fib(n-1) + fib(n-2);
    }
}

客戶端代碼

public class RPCClient {
    private final Connection conn;
    private final Channel ch;
    private final String replyQueue;
    private final QueueingConsumer consumer;

    public RPCClient() throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        conn = factory.newConnection();
        ch = conn.createChannel();
        replyQueue = ch.queueDeclare().getQueue(); // 匿名獨占隊列
        consumer = new QueueingConsumer(ch);
        ch.basicConsume(replyQueue, true, consumer);
    }

    public String call(String msg) throws Exception {
        String corrId = UUID.randomUUID().toString();
        AMQP.BasicProperties props = new AMQP.BasicProperties.Builder()
            .correlationId(corrId).replyTo(replyQueue).build();
        ch.basicPublish("", "rpc_queue", props, msg.getBytes("UTF-8"));

        while (true) {
            QueueingConsumer.Delivery delivery = consumer.nextDelivery();
            if (delivery.getProperties().getCorrelationId().equals(corrId)) {
                return new String(delivery.getBody(), "UTF-8");
            }
        }
    }

    public void close() throws Exception { conn.close(); }

    public static void main(String[] args) throws Exception {
        try (RPCClient client = new RPCClient()) {
            System.out.println("Requesting fib(20)");
            String resp = client.call("20");
            System.out.println("Got: " + resp);
        }
    }
}

關鍵點解析

  • Correlation ID 去重:服務端重啟可能導致重複響應,客戶端必須忽略未知/重複 ID。
  • basicQos(1):防止單個消費者積壓,實現負載均衡。
  • 匿名回調隊列:每客戶端一個,隔離響應,自動清理。
  • 擴展性:可啟動多個 RPCServer 實例,隊列自動分發。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
屬性用途
replyTo回調隊列名稱,服務端發送響應目標
correlationId唯一請求標識,客戶端匹配響應
deliveryMode持久化(2)或瞬態(1)
contentTypeMIME 類型,如 application/json