TCP 閘道器

入站 TCP 閘道器 TcpInboundGateway 和出站 TCP 閘道器 TcpOutboundGateway 分別使用伺服器和客戶端連線工廠。每個連線一次只能處理一個請求或響應。

入站閘道器在根據收到的 payload 構造訊息並將其傳送到 requestChannel 後,會等待響應,然後透過將響應訊息中的 payload 寫入連線來發送響應。

對於入站閘道器,您必須保留或填充 ip_connectionId 訊息頭,因為它用於將訊息與連線關聯。從閘道器發起的訊息會自動設定此訊息頭。如果回覆是作為新訊息構造的,則需要設定該訊息頭。訊息頭的值可以從入站訊息中捕獲。

與入站介面卡一樣,入站閘道器通常使用 type="server" 連線工廠,該工廠監聽入站連線請求。在某些情況下,您可能希望反向建立連線,即入站閘道器連線到外部伺服器,然後在該連線上等待並回復入站訊息。

透過在入站閘道器上使用 client-mode="true" 來支援這種拓撲。在這種情況下,連線工廠必須是 client 型別,並且 single-use 必須設定為 false

另外兩個屬性支援此機制。retry-interval 指定(以毫秒為單位)框架在連線失敗後嘗試重新連線的頻率。scheduler 提供一個 TaskScheduler 來排程連線嘗試並測試連線是否仍處於活動狀態。

如果閘道器已啟動,您可以透過傳送 <control-bus/> 命令 @adapter_id.retryConnection() 強制閘道器建立連線,並使用 @adapter_id.isClientModeConnected() 檢視當前狀態。

出站閘道器在透過連線傳送訊息後,會等待響應,構造一個響應訊息,並將其放入回覆通道。連線上的通訊是單執行緒的。一次只能處理一條訊息。如果在收到當前響應之前另一個執行緒嘗試傳送訊息,它將阻塞,直到之前的請求完成(或超時)。但是,如果客戶端連線工廠配置為單次使用連線,則每個新請求都會獲得自己的連線並立即處理。以下示例配置了一個入站 TCP 閘道器

<int-ip:tcp-inbound-gateway id="inGateway"
    request-channel="tcpChannel"
    reply-channel="replyChannel"
    connection-factory="cfServer"
    reply-timeout="10000"/>

如果使用配置了預設序列化器或反序列化器的連線工廠,訊息將是 \r\n 分隔的資料,並且閘道器可以被 telnet 等簡單客戶端使用。

以下示例展示了一個出站 TCP 閘道器

<int-ip:tcp-outbound-gateway id="outGateway"
    request-channel="tcpChannel"
    reply-channel="replyChannel"
    connection-factory="cfClient"
    request-timeout="10000"
    remote-timeout="10000"/> <!-- or e.g. remote-timeout-expression="headers['timeout']" -->

目前出站閘道器不支援 client-mode

從 5.2 版本開始,出站閘道器可以配置 closeStreamAfterSend 屬性。如果連線工廠配置為 single-use(每個請求/回覆使用一個新連線),閘道器將關閉輸出流;這向伺服器傳送 EOF 訊號。如果伺服器使用 EOF 來確定訊息結束,而不是流中的某個分隔符,並且保持連線開啟以接收回復,則此屬性非常有用。

通常,呼叫執行緒會在閘道器中阻塞,等待回覆(或超時)。從 5.3 版本開始,您可以在閘道器上設定 async 屬性,傳送執行緒將被釋放去執行其他工作。回覆(或錯誤)將在接收執行緒上傳送。這僅在使用 TcpNetClientConnectionFactory 時有效,使用 NIO 時會忽略此屬性,因為存在競態條件,即在收到回覆後發生的 socket 錯誤可能在回覆到達閘道器之前被傳遞給閘道器。

使用共享連線(singleUse=false)時,如果另一個請求正在處理中,新請求將被阻塞,直到收到當前回覆。如果您希望在長連線池上支援併發請求,請考慮使用 CachingClientConnectionFactory

從 5.4 版本開始,入站閘道器可以配置 unsolicitedMessageChannel。未經請求的入站訊息以及延遲的回覆(客戶端超時)將傳送到此通道。為了在伺服器端支援這一點,您現在可以向連線工廠註冊多個 TcpSender。閘道器和通道介面卡會自動註冊。從伺服器傳送未經請求的訊息時,必須向傳送的訊息新增相應的 IpHeaders.CONNECTION_ID