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 时将忽略此属性,因为存在竞争条件,即在收到答复后发生的套接字错误可能会在答复之前传递给网关。

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

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