RabbitMQ架構 - queueBind

源碼解析

queueBind

channel.queueBind(...)爲例,展開分析。

將一個隊列綁定到一個交換器。

Queue.BindOk queueBind(String queue, String exchange, String routingKey) throws IOException;

Queue.BinkOk queueBind(String queue, String exchange, String routingKey, Map<String, Object> arguments) throws IOException;

void queueBindNoWait(String queue, String exchange, String routingKey, Map<String, Object> arguments) throws IOException;

很明顯前兩種是帶有響應返回值,後一種沒有響應返回值。

  • queue:隊列的名字。
  • exchange:交換器的名字。
  • routingKey:用於綁定的路由鍵。
  • arguments:用於綁定的參數

接下來看下它們的源碼。

public AMQP.Queue.BindOk queueBind(String queue, String exchange, String routingKey, Map<String, Object> arguments) throws IOException {
    AMQP.Queue.BindOk ok = delegate.queueBind(queue, exchange, routingKey, arguments);
    recordQueueBinding(queue, exchange, routingKey, arguments);
    return ok;
}

recordQueueBinding(...)方法如下:
在這裏插入圖片描述

在這裏插入圖片描述

首先要保證隊列的長度小於等於255。

exnWrappingRpc(...)相當於經過封裝相關屬性,然後返回一個AMQCommand。
在這裏插入圖片描述

在這裏插入圖片描述

  • _rpcTimeout:RPC調用的超時時間。
  • NO_RPC_TIMEOUT:0。

可以看出privateRpc()方法分爲兩個步驟。第一是發起僞RPC調用。第二是獲取調用的結果。

發起僞RPC調用
在這裏插入圖片描述
在這裏插入圖片描述

先來看看enqueueRpc(...)方法。

在這裏插入圖片描述
在這裏插入圖片描述

  • _activeRpc:RpcWrapper類型,表示當前的未完成的RPC請求。這裏是RpcContinuationRpcWrapper實例。

方法的字面意思是將rpc入隊。實際上一個隊列都沒有用到,只是調用wait()等待。然後再獲取結果。本人感到頗爲意外。

再來看下quiescingTransmit(...)方法。

在這裏插入圖片描述

在這裏插入圖片描述

  • _channelMutex:普通Object對象。
  • _blockContent:boolean類型。
  • _trafficListener:TrafficListener類型,write(…)方法這裏僅僅是記錄信息。

ensureIsOpen()方法用來確保此時是開放狀態,通過判斷ShutdownSignalException屬性是否爲空來判斷,如果它爲空,表示此時是開放狀態;否則表示此時是關閉狀態。

hasContent():表示有消息頭或者消息體。

TrafficListener#write(…):表示通知每一個向外的Command。以LogTrafficListener這個實現類爲例,僅僅是日誌記錄。

接着看AMQPCommandtransmit方法,如下:

public void transmit(AMQChannel channel) throws IOException {
	/* 獲取_channelNumber屬性,也就是通道編號 */
    int channelNumber = channel.getChannelNumber();
    /* 獲取_connection屬性,也就是關聯的連接 */
    AMQConnection connection = channel.getConnection();
    /* CommandAssembler,負責從一系列的Frame中拼湊出一個命令 */
    synchronized (assembler) {
        Method m = this.assembler.getMethod();
        if (m.hasContent()) {
            byte[] body = this.assembler.getContentBody();
            Frame headerFrame = this.assembler.getContentHeader().toFrame(channelNumber, body.length);
			/* 獲取_frameMax屬性,也就是最大的Frame長度,0表示不受限制 */
            int frameMax = connection.getFrameMax();
            boolean cappedFrameMax = frameMax > 0;
            /* EMPTY_FRAME_SIZE :8 */
            int bodyPayloadMax = cappedFrameMax ? frameMax - EMPTY_FRAME_SIZE : body.length;
            if (cappedFrameMax && headerFrame.size() > frameMax) {
                String msg = String.format("Content headers exceeded max frame size: %d > %d", headerFrame.size(), frameMax);
                throw new IllegalArgumentException(msg);
            }
            connection.writeFrame(m.toFrame(channelNumber));
            connection.writeFrame(headerFrame);
            for (int offset = 0; offset < body.length; offset += bodyPayloadMax) {
                int remaining = body.length - offset;
                int fragmentLength = (remaining < bodyPayloadMax) ? remaining
                        : bodyPayloadMax;
                Frame frame = Frame.fromBodyFragment(channelNumber, body,
                        offset, fragmentLength);
                connection.writeFrame(frame);
            }
        } else {
            connection.writeFrame(m.toFrame(channelNumber));
        }
    }
    connection.flush();
}

CommandAssembler:負責從一系列的Frame中拼湊出一個命令。

Frame:表示AMQP wire-protocol的Frame,帶有Frame的類型,通道編號和負載。

在這裏插入圖片描述

刷新緩衝區。實際上就是DataOutputStream調用flush()方法。
在這裏插入圖片描述

ErrorOnWriteListener接口:監聽連接在socket上寫數據是否遇到IO錯誤。這個可以用來觸發連接恢復。
void handle(Connection connection, IOException exception) throws IOException;

發送消息到broker的核心方法
在這裏插入圖片描述

HeartbeatSender:管理心跳的發送。

public void signalActivity() {
    this.lastActivityTime = System.nanoTime();
}

將Frame寫到數據連接中
在這裏插入圖片描述

在這裏插入圖片描述

  • accumulator:是ByteArrayOutputStream。

實際上隊列與交換機的綁定,還是將相關數據寫入到數據流中。

獲取調用的結果
在這裏插入圖片描述

  • _blocker:BlockingValueOrException類型。

在這裏插入圖片描述

等待獲取結果直到超時,不響應中斷。
在這裏插入圖片描述

  • NANOS_IN_MILLI:1000L * 1000L。
  • INFINITY:-1。

等待獲取值。如果已經有值,不需要再等待,返回這個值。達到超時時間,還沒有值到達,會拋出TimeoutException異常。
在這裏插入圖片描述

  • INFINITY:-1。
  • NANOS_IN_MILLI :1000L * 1000L。
  • _filled:表示值還沒有被填充。
  • _value:表示被填充的值。

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章