gpt4 book ai didi

java - Spring集成DSL TCP : How to prevent excessive logging of Connection refused on the client side

转载 作者:太空宇宙 更新时间:2023-11-04 09:47:38 26 4
gpt4 key购买 nike

我使客户端和服务器都能够等待彼此连接,因此它们可以以任何顺序独立启动。解决方案described here开箱即用,但客户端不断将大量堆栈跟踪打印到我们的日志中,其中包含 java.net.ConnectException: Connection returned: connect,后面是 46 行长的堆栈跟踪,直到服务器启动并发生连接。这并不理想。

我的问题是:如何应用我的自定义逻辑来微调记录内容和时间。

到目前为止我发现日志是由org.springframework.integration.handler.LoggingHandler打印的。这充当某种错误 channel ,错误总是在那里发送。我找不到这一组在哪里,因此我可以将其替换为我自己的实现。我设法配置了自己的默认错误 channel ,但该 channel 是与预配置的 LoggingHandler channel 一起添加的,而不是替换它。

另一种方法可能是在发送第一条消息时设置更长的超时。我也在为此苦苦挣扎。我尝试在 outboundGateway 上将其设置为 .handle(Tcp.outboundGateway(clientConnectionFactory).remoteTimeout(1_000_000L)) 但没有任何效果。

最佳答案

好的,解决了。

问题实际上并不在于 LoggingHandler 或任何错误 channel ,而是如果服务器未立即准备就绪,org.springframework.integration.ip.tcp.connection.TcpNetClientConnectionFactory.createSocket() 会抛出异常,而 TcpOutboundGateway 然后以老式方式记录此异常;只有这样,错误才会被分派(dispatch)到 errorChannel 并可以对其使用react;默认的 SI react 是再次打印它:)这是我最初没有注意到的,异常被记录了两次。可以通过使用自定义错误消息处理程序来阻止第二个日志,但不能阻止第一个日志。

TcpNetClientConnectionFactory.createSocket() 调用默认 Java 的 createSocket(),并且没有设置超时的选项。如果接收者尚未准备好,则方法调用几乎立即失败。参见JDK的增强请求JDK-4414843 .

可能的解决方案是重写 TcpNetClientConnectionFactory.createSocket() 以重复与服务器的连接尝试,直到成功。

等待TcpNetClientConnectionFactory

public class WaitingTcpNetClientConnectionFactory extends TcpNetClientConnectionFactory {
private final SocketConnectionListener socketConnectionListener;
private final int waitBetweenAttemptsInMs;
private final Logger log = LogManager.getLogger();

public WaitingTcpNetClientConnectionFactory(
String host, int port,
int waitBetweenAttemptsInMs,
SocketConnectionListener socketConnectionListener) {
super(host, port);
this.waitBetweenAttemptsInMs = waitBetweenAttemptsInMs;
this.socketConnectionListener = socketConnectionListener;
}

@Override
protected Socket createSocket(String host, int port) throws IOException {
Socket socket = null;
while (socket == null) {
try {
socket = super.createSocket(host, port);
socketConnectionListener.onConnectionOpen();
} catch (ConnectException ce) {
socketConnectionListener.onConnectionFailure();
log.warn("server " + host + ":" + port + " is not ready yet ..waiting");
try {
Thread.sleep(waitBetweenAttemptsInMs);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new IOException("interrupted while wating between connection attempts", ie);
}
}
}
return socket;
}
}

作为额外的奖励,我还设置了我自己的自定义接口(interface) SocketConnectionListener 的成功或失败,以便应用程序的其他部分可以与其同步;例如,等待流式传输,直到服务器/对等节点准备就绪。

使用 WaitingTcpNetClientConnectionFactory 的方式与 TcpNetClientConnectionFactory 相同。

HeartbeatClientConfig(仅相关位):

@Bean
public TcpNetClientConnectionFactory clientConnectionFactory(
ConnectionStatus connectionStatus) {
TcpNetClientConnectionFactory connectionFactory = new WaitingTcpNetClientConnectionFactory("localhost", 7777, 2000, connectionStatus);
connectionFactory.setSerializer(new ByteArrayLengthHeaderSerializer());
connectionFactory.setDeserializer(new ByteArrayLengthHeaderSerializer());
return connectionFactory;
}

现在它只打印:

INFO [           main] o.b.e.d.s.h.client.HeartbeatClientRun    : Started HeartbeatClientRun in 1.042 seconds (JVM running for 1.44)
WARN [ask-scheduler-1] h.c.WaitingTcpNetClientConnectionFactory : server localhost:7777 is not ready yet ..waiting
WARN [ask-scheduler-1] h.c.WaitingTcpNetClientConnectionFactory : server localhost:7777 is not ready yet ..waiting
WARN [ask-scheduler-1] h.c.WaitingTcpNetClientConnectionFactory : server localhost:7777 is not ready yet ..waiting
WARN [ask-scheduler-1] h.c.WaitingTcpNetClientConnectionFactory : server localhost:7777 is not ready yet ..waiting

像往常一样,完整的项目源代码可以在我的 git here is the relevant commit 上找到。 .

关于java - Spring集成DSL TCP : How to prevent excessive logging of Connection refused on the client side,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55213889/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com