跳到主要内容
版本:7.0.2

TCP 网关

DeepSeek V3 中英对照 TCP Gateways

入站 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 时会被忽略,因为存在一种竞态条件:在收到回复后发生的套接字错误可能会在回复之前传递给网关。

important

当使用共享连接(singleUse=false)时,如果另一个请求正在处理中,新的请求将被阻塞,直到收到当前回复。如果您希望在长连接池上支持并发请求,请考虑使用 CachingClientConnectionFactory

从版本5.4开始,入站连接可以通过 unsolicitedMessageChannel 进行配置。未经请求的入站消息以及延迟回复(当客户端超时时)将被发送到此通道。为了在服务器端支持此功能,您现在可以向连接工厂注册多个 TcpSender。网关和通道适配器会自动注册自身。当从服务器发送未经请求的消息时,您必须在发送的消息中添加适当的 IpHeaders.CONNECTION_ID