Java 如何使用spring集成在TCP连接上实现保持活动连接?
我有一个TCP客户端,它是使用SpringIntegrationTCP构建的,服务器支持保持活动消息(乒乓风格)。连接是使用Java 如何使用spring集成在TCP连接上实现保持活动连接?,java,spring,sockets,tcp,spring-integration,Java,Spring,Sockets,Tcp,Spring Integration,我有一个TCP客户端,它是使用SpringIntegrationTCP构建的,服务器支持保持活动消息(乒乓风格)。连接是使用CachingClientConnectionFactory配置的,我想利用这一服务器功能。下面是我的bean配置: private static final int SERIALIZER_HEADER_SIZE = 2; /** * Serializer used by connection factory to send and receive messages
CachingClientConnectionFactory
配置的,我想利用这一服务器功能。下面是我的bean配置:
private static final int SERIALIZER_HEADER_SIZE = 2;
/**
* Serializer used by connection factory to send and receive messages
*/
@Bean
public ByteArrayLengthHeaderSerializer byteArrayLengthHeaderSerializer() {
return new ByteArrayLengthHeaderSerializer(SERIALIZER_HEADER_SIZE);
}
@Bean
public AbstractClientConnectionFactory tcpClientConnectionFactory() {
TcpNetClientConnectionFactory connFactory =
new TcpNetClientConnectionFactory(props.getUrl(), props.getPort());
connFactory.setSerializer(byteArrayLengthHeaderSerializer());
connFactory.setDeserializer(byteArrayLengthHeaderSerializer());
connFactory.setSoTimeout(props.getSoTimeout());
if (props.isUseSSL()) {
connFactory.setTcpSocketFactorySupport(new DefaultTcpNetSSLSocketFactorySupport(() -> {
return SSLContext.getDefault();
}));
}
return connFactory;
}
/**
* Connection factory used to create TCP client socket connections
*/
@Bean
public AbstractClientConnectionFactory tcpCachedClientConnectionFactory() {
CachingClientConnectionFactory cachingConnFactory =
new CachingClientConnectionFactory(tcpClientConnectionFactory(), props.getMaxPoolSize());
cachingConnFactory.setConnectionWaitTimeout(props.getMaxPoolWait());
return cachingConnFactory;
}
使用此处发布的解决方案,我可以保持连接处于打开状态,但我还希望利用这些服务器保持活动消息,并不时发送这些消息,以检查连接是否仍处于活动状态。这可以提高客户端的性能,因为如果套接字已关闭,则无需重新连接/创建新连接
基于此,是否有人对如何使用spring集成实现此功能提出了建议 使用简单的客户端连接工厂时,使用
@InboundChannelAdapter
设置应用程序级心跳消息非常容易
简单的例子:
@SpringBootApplication
public class So46918267Application {
public static void main(String[] args) throws IOException {
// Simulated Server
final ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(1234);
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(() -> {
try {
Socket socket = server.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
if (line.equals("keep_alive")) {
socket.getOutputStream().write("OK\r\n".getBytes());
}
}
}
catch (IOException e) {
e.printStackTrace();
}
});
ConfigurableApplicationContext context = SpringApplication.run(So46918267Application.class, args);
System.out.println("Hit enter to terminate");
System.in.read();
executor.shutdownNow();
context.close();
server.close();
}
@Bean
public TcpNetClientConnectionFactory client() {
return new TcpNetClientConnectionFactory("localhost", 1234);
}
@ServiceActivator(inputChannel = "toTcp")
@Bean
public TcpOutboundGateway gateway() {
TcpOutboundGateway gateway = new TcpOutboundGateway();
gateway.setConnectionFactory(client());
return gateway;
}
// HEARTBEATS
private final Message<?> heartbeatMessage = MessageBuilder.withPayload("keep_alive")
.setReplyChannelName("heartbeatReplies")
.build();
@InboundChannelAdapter(channel = "toTcp", poller = @Poller(fixedDelay = "25000"))
public Message<?> heartbeat() {
return this.heartbeatMessage;
}
@ServiceActivator(inputChannel = "heartbeatReplies")
public void reply(byte[] reply) {
System.out.println(new String(reply));
}
}
将保持最多5个连接打开。它不会打开新连接(如果至少有一个),但如果池包含5个或更多连接,则至少有5个连接将保持打开状态。如果没有打开的连接,它将只打开一个。不清楚您的确切意思。您可以将
soKeepAlive
设置为true,以便操作系统通过发送ping来保持套接字打开。然后,如果不设置soTimeout
,套接字将无限期地保持打开状态。服务器将期望类似于KEEP\u ALIVE\u请求的内容
,并将返回KEEP\u ALIVE\u响应
。我的问题是使用它来保持连接打开,但根据您的回答,soKeepAlive
和soTimeout
一起可以完成此任务。更新:@GaryRussell服务器将在30秒不活动后关闭套接字。基于此,spring integration是否具有任何功能,我可以使用这些功能(以后台方式)发送特定的保持活动的消息,以便重新使用客户端套接字?非常感谢您的快速响应,这正是我想要的。每次客户端必须打开一个新连接时,都需要一些时间,因此我们希望维护池中打开的几个连接。
@InboundChannelAdapter(channel = "toTcp",
poller = @Poller(fixedDelay = "25000", maxMessagesPerPoll = "5"))