TCP 閘道

輸入 TCP 閘道 TcpInboundGateway 和輸出 TCP 閘道 TcpOutboundGateway 分別使用伺服器和用戶端連線工廠。每個連線一次可以處理單個請求或回應。

輸入閘道在建構包含傳入有效負載的訊息並將其傳送到 requestChannel 後,會等待回應,並透過將回應訊息的有效負載寫入連線來傳送。

對於輸入閘道,您必須保留或填入 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 新增到傳送的訊息。