Connection was broken: java.util.concurrent.TimeoutException: Ping started at 1667335510986 hasn't completed by 1667335750987 at hudson.remoting.PingThread.ping(PingThread.java:134) at hudson.remoting.PingThread.run(PingThread.java:90)
上面报错 行的代码如下:
1 2
onDead(new TimeoutException("Ping started at "+start+" hasn't completed by "+System.currentTimeMillis()));//.initCause(e)
* Periodically perform a ping. * * Useful when a connection needs to be kept alive by sending data, * or when the disconnection is not properly detected. * * {@link #onDead()} method needs to be overridden to define * what to do when a connection appears to be dead.
private static final Logger LOGGER = Logger.getLogger(ChannelPinger.class.getName()); private static final String TIMEOUT_SECONDS_PROPERTY = ChannelPinger.class.getName() + ".pingTimeoutSeconds"; private static final String INTERVAL_MINUTES_PROPERTY_DEPRECATED = ChannelPinger.class.getName() + ".pingInterval"; // 这个属性 已经不再建议使用了 private static final String INTERVAL_SECONDS_PROPERTY = ChannelPinger.class.getName() + ".pingIntervalSeconds";
/** * Timeout for the ping in seconds. */ private int pingTimeoutSeconds = SystemProperties.getInteger(TIMEOUT_SECONDS_PROPERTY, PING_TIMEOUT_SECONDS_DEFAULT, Level.WARNING);
/** * Interval for the ping in seconds. */ private int pingIntervalSeconds = PING_INTERVAL_SECONDS_DEFAULT;
public ChannelPinger() { // 构造方法,主要就是用来 初始化 pingIntervalSeconds, 超时 pingTimeoutSeconds 那个已经在 类定义时候 设置 初始值了。 Integer interval = SystemProperties.getInteger(INTERVAL_SECONDS_PROPERTY, null, Level.WARNING); // if interval wasn't set we read the deprecated property in minutes if (interval == null) { interval = SystemProperties.getInteger(INTERVAL_MINUTES_PROPERTY_DEPRECATED,null, Level.WARNING); if (interval != null) { LOGGER.warning(INTERVAL_MINUTES_PROPERTY_DEPRECATED + " property is deprecated, " + INTERVAL_SECONDS_PROPERTY + " should be used"); interval *= 60; //to seconds } } if (interval != null) { pingIntervalSeconds = interval; } }
@VisibleForTesting /*package*/ void install(Channel channel, @CheckForNull SlaveComputer c) { if (pingTimeoutSeconds < 1 || pingIntervalSeconds < 1) { LOGGER.warning("Agent ping is disabled"); return; }
// set up ping from both directions, so that in case of a router dropping a connection, // both sides can notice it and take compensation actions. try { channel.call(new SetUpRemotePing(pingTimeoutSeconds, pingIntervalSeconds)); LOGGER.fine("Set up a remote ping for " + channel.getName()); } catch (Exception e) { LOGGER.log(Level.SEVERE, "Failed to set up a ping for " + channel.getName(), e); }
十一月 02, 2022 1:51:18 下午 详细 hudson.slaves.ChannelPinger Set up a remote ping for JNLP4-connect connection from 192.168.1.116/192.168.1.116:35028 // 这个就是 install方法里面 调用完 channel.call() 之后 打印的 十一月 02, 2022 1:51:18 下午 详细 hudson.slaves.ChannelPinger setting up ping on JNLP4-connect connection from 192.168.1.116/192.168.1.116:35028 with a 300 seconds interval and 240 seconds timeout // 这个是 setUpPingForChannel() 方法的 第一句 打印。
十一月 02, 2022 1:51:18 下午 详细 hudson.slaves.ChannelPinger Ping thread started for hudson.remoting.Channel@3055f449:JNLP4-connect connection from 192.168.1.116/192.168.1.116:35028 with a 300 seconds interval and a 240 seconds timeout // 这个是 setUpPingForChannel() 方法的 最后 句 打印。
十一月 02, 2022 1:51:18 下午 详细 hudson.remoting.PingThread pinging JNLP4-connect connection from 192.168.1.116/192.168.1.116:35028 十一月 02, 2022 1:51:18 下午 详细 hudson.remoting.PingThread waiting 239s on JNLP4-connect connection from 192.168.1.116/192.168.1.116:35028 十一月 02, 2022 1:51:18 下午 详细 hudson.remoting.PingThread ping succeeded on JNLP4-connect connection from 192.168.1.116/192.168.1.116:35028
node 节点上的日志
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
十一月 02, 2022 1:51:03 下午 详细 hudson.slaves.ChannelPinger setting up ping on JNLP4-connect connection to 192.168.1.75/192.168.1.75:37743 with a 300 seconds interval and 240 seconds timeout // 这个是 setUpPingForChannel() 方法的 第一句 打印。
十一月 02, 2022 1:51:03 下午 警告 hudson.remoting.PingThread public PingThread(Channel channel, long timeout, long interval) // PingThread 构造方法里面打印的,自己加的 打印。。。。
十一月 02, 2022 1:51:03 下午 详细 hudson.slaves.ChannelPinger Ping thread started for hudson.remoting.Channel@401bc256:JNLP4-connect connection to 192.168.1.75/192.168.1.75:37743 with a 300 seconds interval and a 240 seconds timeout // 这个是 setUpPingForChannel() 方法的 最后 句 打印。
十一月 02, 2022 1:51:03 下午 警告 hudson.remoting.PingThread ping pinging JNLP4-connect connection to 192.168.1.75/192.168.1.75:37743 十一月 02, 2022 1:51:03 下午 警告 hudson.remoting.PingThread ping waiting 239s on JNLP4-connect connection to 192.168.1.75/192.168.1.75:37743 十一月 02, 2022 1:51:04 下午 警告 hudson.remoting.PingThread ping ping succeeded on JNLP4-connect connection to 192.168.1.75/192.168.1.75:37743 十一月 02, 2022 1:51:04 下午 警告 hudson.remoting.PingThread$Ping call class Ping pool-1-thread-6 for JNLP4-connect connection to 192.168.1.75/192.168.1.75:37743 id=7, 47, bright.ma, /tmp
class Ping Computer.threadPoolForRemoting [#3] for JNLP4-connect connection from 10.0.12.116/10.0.12.116:37260 id=22, 388, mamh, /home/mamh/work/github/jenkins class Ping pool-1-thread-5 for JNLP4-connect connection to 10.0.61.75/10.0.61.75:37743 id=8, 28, bright.ma, /tmp
@VisibleForTesting @Restricted(NoExternalUse.class) public static void setUpPingForChannel(final Channel channel, final SlaveComputer computer, int timeoutSeconds, int intervalSeconds, final boolean analysis) { LOGGER.log(Level.FINE, "setting up ping on {0} with a {1} seconds interval and {2} seconds timeout", new Object[] {channel.getName(), intervalSeconds, timeoutSeconds}); final AtomicBoolean isInClosed = new AtomicBoolean(false);
final PingThread t = new PingThread(channel, TimeUnit.SECONDS.toMillis(timeoutSeconds), TimeUnit.SECONDS.toMillis(intervalSeconds)) { // 实例化 PingThread 类, 。。。。 省略 这些 };
@VisibleForTesting @Restricted(NoExternalUse.class) public static class SetUpRemotePing extends MasterToSlaveCallable<Void, IOException> { private final int pingTimeoutSeconds; private final int pingIntervalSeconds;
public SetUpRemotePing(int pingTimeoutSeconds, int pingIntervalSeconds) { this.pingTimeoutSeconds = pingTimeoutSeconds; this.pingIntervalSeconds = pingIntervalSeconds; }
@Override public void run() { try { while(true) { long nextCheck = System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(interval);
ping();
// wait until the next check long diff; while((diff = nextCheck - System.nanoTime()) > 0) { TimeUnit.NANOSECONDS.sleep(diff); } } } catch (ChannelClosedException e) { LOGGER.fine(getName()+" is closed. Terminating"); } catch (IOException e) { onDead(e); } catch (InterruptedException e) { // use interruption as a way to terminate the ping thread. LOGGER.fine(getName()+" is interrupted. Terminating"); } }
private void ping() throws IOException, InterruptedException { LOGGER.log(Level.WARNING, "pinging {0}", channel.getName()); Future<?> f = channel.callAsync(new Ping()); long start = System.currentTimeMillis();
long end = System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(timeout); long remaining = end - System.nanoTime();
do { LOGGER.log(Level.WARNING, "waiting {0}s on {1}", new Object[] {TimeUnit.NANOSECONDS.toSeconds(remaining), channel.getName()}); try { f.get(Math.max(1,remaining),TimeUnit.NANOSECONDS); LOGGER.log(Level.WARNING, "ping succeeded on {0}", channel.getName()); return; } catch (ExecutionException e) { if (e.getCause() instanceof RequestAbortedException) return; // connection has shut down orderly. onDead(e); return; } catch (TimeoutException e) { // get method waits "at most the amount specified in the timeout", // so let's make sure that it really waited enough } remaining = end - System.nanoTime(); } while(remaining>0);
onDead(new TimeoutException("Ping started at "+start+" hasn't completed by "+System.currentTimeMillis()));//.initCause(e) 我们最开始的那个报错 就是 从这里 onDead 抛出的。 }