You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Integration TCP客户端警告与超时异常相关技术咨询

Spring Integration TCP客户端相关问题

我在Spring Boot环境中使用Spring Integration,配置了基于TcpNetClientConnectionFactory的TCP客户端与TcpOutboundGateway。生产环境中出现「No publisher available to publish」警告,经排查该警告由org.springframework.context.ApplicationEventPublisher为null导致。目前TCP服务器可正常接收客户端消息,但存在两个疑问:

  1. 该警告是否会产生影响?请详细解释此警告,当前虽有警告但消息传输正常。
  2. 近期生产环境出现「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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 04:24:13