Spring Integration TCP客户端警告与超时异常相关技术咨询
我在Spring Boot环境中使用Spring Integration,配置了基于TcpNetClientConnectionFactory的TCP客户端与TcpOutboundGateway。生产环境中出现「No publisher available to publish」警告,经排查该警告由org.springframework.context.ApplicationEventPublisher为null导致。目前TCP服务器可正常接收客户端消息,但存在两个疑问:
- 该警告是否会产生影响?请详细解释此警告,当前虽有警告但消息传输正常。
- 近期生产环境出现「org.springframework.messaging.MessagingException: Exception while awaiting reply; nested exception is java.net.SocketTimeoutException: Read timed out」异常,当时telnet服务器端口连通,但消息未被接收,重启TCP服务器后恢复。请问该异常是否与上述警告相关?(注:TCP服务器为外部系统,不由我方维护)
相关代码
网关配置类
@Bean @ServiceActivator(inputChannel = "a04A08OutgoingChannel") public MessageHandler a04A08OutgoingGate() { final TcpOutboundGateway gate = new TcpOutboundGateway(); // Connection configured in client mode to send the message over the TCP socket // and wait for acknowledgement gate.setConnectionFactory(connectionFactory.connectionFactory(host, port)); gate.setReplyChannelName("a04A08ReplyToString"); gate.setRemoteTimeout(60_000); return gate; } @Transformer(inputChannel = "a04A08ReplyToString") public String transform(byte[] bytes) { String reply = new String(bytes); log.debug("transform - a04A08ReplyToString channel " + reply); return new String(bytes); } public String outgoingMessage(String message) { String reply = null; log.info("Message being Sent : " + message); try { // Send the message to the TCP socket and wait for acknowledgement reply = a04a08OutgoingGateway.sendMessage(message); } catch (ConnectException e) { log.error(e.getMessage(),e); } log.info("Acknowledgement received : " + reply); return reply; }
ConnectionFactory.java
public AbstractClientConnectionFactory connectionFactory(String host, int port) { final AbstractClientConnectionFactory connectionFactory = new TcpNetClientConnectionFactory(host, port); connectionFactory.setSerializer(customDeserializer); connectionFactory.setDeserializer(customDeserializer); //connectionFactory.setSoKeepAlive(true); connectionFactory.setSingleUse(true);// This property when set to false ensures that one shared connection is used for all // request/replies and each caller blocks waiting for the socket return connectionFactory; }
CustomDeserializer.java
@Override public void serialize(String object, OutputStream outputStream) throws IOException { log.info("[Serialize] Serializing data : length ==> " + object.length()); outputStream.write(object.getBytes()); log.info("[Serialize] data posted to stream"); } @Override public byte[] deserialize(InputStream inputStream) throws IOException { log.info("[Deserialize] De-Serializing data"); BufferedReader input = new BufferedReader(new InputStreamReader(inputStream)); StringBuffer stringbuffer = new StringBuffer(); while (true) { int value = input.read(); if (value == 28) { break; } else { if (value != -1) { stringbuffer.append((char) value + ""); } else { break; } } } log.info("[deserialize.readFromSocket()]: " + stringbuffer.toString()); return stringbuffer.toString().getBytes(); }
1. 「No publisher available to publish」警告的影响与解释
这个警告来自Spring Integration的TCP连接组件,当ApplicationEventPublisher为null时,组件无法发布连接相关的事件(比如连接建立、断开、异常等事件)。
当前消息传输正常是因为核心的TCP收发逻辑不依赖事件发布,事件机制仅用于监控和扩展场景(比如监听事件做告警、连接状态统计等)。所以这个警告不会影响基础的消息发送接收功能,但会带来以下限制:
- 无法通过Spring事件机制获取连接状态变化的通知
- 若后续有基于这些事件的扩展逻辑(比如自定义监控),会直接失效
- 本质是组件初始化的小瑕疵,通常因连接工厂Bean未被Spring容器完全管理导致(比如手动创建Bean但未注入
ApplicationEventPublisher)
解决该警告的方法:给connectionFactory方法添加@Bean注解,让Spring容器自动初始化并注入所需依赖(包括ApplicationEventPublisher)。
2. SocketTimeoutException与警告的关联性
该超时异常和「No publisher available to publish」警告无直接关联。
超时异常的核心原因是:客户端发送消息后,在配置的60秒remoteTimeout内未收到服务器响应,触发读超时。结合你描述的场景(telnet连通但消息未被接收,重启服务器后恢复),问题大概率出在外部TCP服务器:
- 服务器端口连通但内部线程池耗尽、消息队列阻塞,导致无法处理客户端消息,自然不会返回响应
- 服务器存在连接泄漏或状态异常,新连接虽建立但消息无法被正确路由到处理逻辑
另外可检查CustomDeserializer:deserialize方法以ASCII码28(文件分隔符)作为响应结束标记,若服务器返回的响应中无该字符,客户端会一直读取直到超时。但这属于响应格式问题,和警告仍无关联。
内容的提问来源于stack exchange,提问作者Shanmuga Priya

