Spring Integration TCP双连接轮询客户端无法接收服务器消息求助
问题排查:Spring Integration TCP客户端无法接收服务器响应
你需要向双IP/端口的TCP服务器轮询发送消息(长连接),已实现发送但无法接收响应,核心问题出在序列化器不匹配、入站适配器模式错误和连接工厂配置不合理三个方面,具体排查和修正如下:
1. 长度头序列化器不匹配服务器格式
当前使用的ByteArrayLengthHeaderSerializer默认采用二进制长度编码,但服务器要求的是4字节ASCII字符串格式的长度头(例如"0128"标识消息体长度为128字节),这种不匹配会导致客户端无法解析服务器返回的消息,表现为收不到数据。
修正代码:
private ByteArrayLengthHeaderSerializer codec() { ByteArrayLengthHeaderSerializer serializer = new ByteArrayLengthHeaderSerializer(); serializer.setMaxMessageSize(8 * 1024); serializer.setInclusive(false); // 启用ASCII格式长度头,指定头部长度为4字节 serializer.setAscii(true); serializer.setHeaderLength(4); return serializer; }
2. 入站适配器未启用客户端模式
TcpReceivingChannelAdapter默认工作在服务器模式(监听本地端口等待连接),但你的场景是作为客户端复用已建立的长连接接收响应,必须启用客户端模式,否则适配器不会关联发送handler创建的客户端连接,无法接收服务器返回的数据。
修正代码:
在两个入站适配器配置中添加setClientMode(true):
@Bean public MessageProducer tcpInboundChannelOne() { TcpReceivingChannelAdapter inboundChannelAdapter = new TcpReceivingChannelAdapter(); inboundChannelAdapter.setConnectionFactory(failoverClientConnectionFactoryOne()); inboundChannelAdapter.setOutputChannel(inboundChannel()); // 启用客户端模式,复用客户端连接接收消息 inboundChannelAdapter.setClientMode(true); return inboundChannelAdapter; } @Bean public MessageProducer tcpInboundChannelTwo() { TcpReceivingChannelAdapter inboundChannelAdapter = new TcpReceivingChannelAdapter(); inboundChannelAdapter.setConnectionFactory(failoverClientConnectionFactoryTwo()); inboundChannelAdapter.setOutputChannel(inboundChannel()); inboundChannelAdapter.setClientMode(true); return inboundChannelAdapter; }
3. 连接工厂配置冗余不符合轮询需求
你当前配置的两个FailoverClientConnectionFactory核心是故障转移(连接失败时切换),而非轮询分发。重复的配置可能导致连接资源冲突,且难以保证发送/接收复用同一个长连接。
如果你的核心需求是轮询两个固定TCP连接,推荐使用RoundRobinClientConnectionFactory简化配置,同时确保发送和接收复用同一连接:
优化后的配置示例:
// 轮询连接工厂 @Bean public RoundRobinClientConnectionFactory roundRobinCF() { List<AbstractClientConnectionFactory> factories = new ArrayList<>(); factories.add(tcpNetClientConnectionFactoryOne()); factories.add(tcpNetClientConnectionFactoryTwo()); RoundRobinClientConnectionFactory cf = new RoundRobinClientConnectionFactory(factories); cf.setLeaveOpen(true); cf.setSingleUse(false); cf.setSoKeepAlive(true); return cf; } // 单个发送handler实现轮询 @Bean @ServiceActivator(inputChannel = "outboundChannel") public MessageHandler tcpOutboundHandler() { TcpSendingMessageHandler handler = new TcpSendingMessageHandler(); handler.setConnectionFactory(roundRobinCF()); handler.setClientMode(true); return handler; } // 单个入站适配器复用轮询连接工厂 @Bean public MessageProducer tcpInboundAdapter() { TcpReceivingChannelAdapter inboundChannelAdapter = new TcpReceivingChannelAdapter(); inboundChannelAdapter.setConnectionFactory(roundRobinCF()); inboundChannelAdapter.setOutputChannel(inboundChannel()); inboundChannelAdapter.setClientMode(true); return inboundChannelAdapter; }
内容的提问来源于stack exchange,提问作者ShadowStorm
相关产品推荐
相关产品推荐

