52
52
import java .security .cert .CertificateException ;
53
53
import java .security .cert .X509Certificate ;
54
54
import java .security .interfaces .RSAPublicKey ;
55
+ import java .time .Duration ;
55
56
import java .util .ArrayList ;
56
57
import java .util .Arrays ;
57
58
import java .util .Base64 ;
101
102
import org .jenkinsci .remoting .protocol .cert .PublicKeyMatchingX509ExtendedTrustManager ;
102
103
import org .jenkinsci .remoting .protocol .impl .ConnectionRefusalException ;
103
104
import org .jenkinsci .remoting .util .KeyUtils ;
105
+ import org .jenkinsci .remoting .util .RetryUtils ;
104
106
import org .jenkinsci .remoting .util .VersionNumber ;
105
107
import org .jenkinsci .remoting .util .https .NoCheckHostnameVerifier ;
106
108
import org .jenkinsci .remoting .util .https .NoCheckTrustManager ;
@@ -193,6 +195,12 @@ public Thread newThread(@NonNull final Runnable r) {
193
195
194
196
private boolean noReconnect = false ;
195
197
198
+ private int delay = 10 ;
199
+
200
+ private double jitterFactor = 0 ;
201
+
202
+ private int jitter = 0 ;
203
+
196
204
/**
197
205
* Determines whether the socket will have {@link Socket#setKeepAlive(boolean)} set or not.
198
206
*
@@ -412,6 +420,21 @@ public void setNoReconnect(boolean noReconnect) {
412
420
this .noReconnect = noReconnect ;
413
421
}
414
422
423
+ @ Restricted (NoExternalUse .class )
424
+ public void setDelay (int delay ) {
425
+ this .delay = delay ;
426
+ }
427
+
428
+ @ Restricted (NoExternalUse .class )
429
+ public void setJitterFactor (double jitterFactor ) {
430
+ this .jitterFactor = jitterFactor ;
431
+ }
432
+
433
+ @ Restricted (NoExternalUse .class )
434
+ public void setJitter (int jitter ) {
435
+ this .jitter = jitter ;
436
+ }
437
+
415
438
/**
416
439
* Determines if JNLPAgentEndpointResolver will not perform certificate validation in the HTTPs mode.
417
440
*
@@ -742,8 +765,8 @@ public void closeRead() throws IOException {
742
765
}
743
766
events .onDisconnect ();
744
767
while (true ) {
745
- // TODO refactor various sleep statements into a common method
746
- TimeUnit . SECONDS . sleep (10 );
768
+ Duration duration = RetryUtils . getDuration ( delay , jitterFactor , jitter );
769
+ Thread . sleep (duration . toMillis () );
747
770
// Unlike JnlpAgentEndpointResolver, we do not use $jenkins/tcpSlaveAgentListener/, as that will be a 404 if the TCP port is disabled.
748
771
URL ping = new URL (hudsonUrl , "login" );
749
772
try {
@@ -809,9 +832,9 @@ private void innerRun(IOHub hub, SSLContext context, ExecutorService service) {
809
832
endpoint = resolver .resolve ();
810
833
} catch (IOException e ) {
811
834
if (!noReconnect ) {
812
- events . status ( "Could not locate server among " + candidateUrls + "; waiting 10 seconds before retry" , e );
813
- // TODO refactor various sleep statements into a common method
814
- TimeUnit . SECONDS . sleep (10 );
835
+ Duration duration = RetryUtils . getDuration ( delay , jitterFactor , jitter );
836
+ events . status ( "Could not locate server among " + candidateUrls + "; waiting " + RetryUtils . formatDuration ( duration ) + " seconds before retry" , e );
837
+ Thread . sleep (duration . toMillis () );
815
838
continue ;
816
839
} else {
817
840
if (Boolean .getBoolean (Engine .class .getName () + ".nonFatalJnlpAgentEndpointResolutionExceptions" )) {
@@ -929,26 +952,35 @@ private void innerRun(IOHub hub, SSLContext context, ExecutorService service) {
929
952
}
930
953
931
954
private JnlpEndpointResolver createEndpointResolver (List <String > jenkinsUrls , String agentName ) {
932
- JnlpEndpointResolver resolver ;
933
955
if (directConnection == null ) {
934
956
SSLSocketFactory sslSocketFactory = null ;
935
957
try {
936
958
sslSocketFactory = getSSLSocketFactory (candidateCertificates , disableHttpsCertValidation );
937
959
} catch (Exception e ) {
938
960
events .error (e );
939
961
}
940
- resolver = new JnlpAgentEndpointResolver (jenkinsUrls , agentName , credentials , proxyCredentials , tunnel ,
941
- sslSocketFactory , disableHttpsCertValidation );
962
+ JnlpAgentEndpointResolver jnlpAgentEndpointResolver =
963
+ new JnlpAgentEndpointResolver (
964
+ jenkinsUrls ,
965
+ agentName ,
966
+ credentials ,
967
+ proxyCredentials ,
968
+ tunnel ,
969
+ sslSocketFactory ,
970
+ disableHttpsCertValidation );
971
+ jnlpAgentEndpointResolver .setDelay (delay );
972
+ jnlpAgentEndpointResolver .setJitterFactor (jitterFactor );
973
+ jnlpAgentEndpointResolver .setJitter (jitter );
974
+ return jnlpAgentEndpointResolver ;
942
975
} else {
943
- resolver = new JnlpAgentEndpointConfigurator (directConnection , instanceIdentity , protocols , proxyCredentials );
976
+ return new JnlpAgentEndpointConfigurator (directConnection , instanceIdentity , protocols , proxyCredentials );
944
977
}
945
- return resolver ;
946
978
}
947
979
948
980
private void onConnectionRejected (String greeting ) throws InterruptedException {
949
- events . status ( "reconnect rejected, sleeping 10s: " , new Exception ( "The server rejected the connection: " + greeting ) );
950
- // TODO refactor various sleep statements into a common method
951
- TimeUnit . SECONDS . sleep (10 );
981
+ Duration duration = RetryUtils . getDuration ( delay , jitterFactor , jitter );
982
+ events . status ( "reconnect rejected, sleeping " + RetryUtils . formatDuration ( duration ) + "s: " , new Exception ( "The server rejected the connection: " + greeting ));
983
+ Thread . sleep (duration . toMillis () );
952
984
}
953
985
954
986
/**
@@ -970,8 +1002,8 @@ private Socket connectTcp(@NonNull JnlpAgentEndpoint endpoint) throws IOExceptio
970
1002
if (retry ++>10 ) {
971
1003
throw e ;
972
1004
}
973
- // TODO refactor various sleep statements into a common method
974
- TimeUnit . SECONDS . sleep (10 );
1005
+ Duration duration = RetryUtils . getDuration ( delay , jitterFactor , jitter );
1006
+ Thread . sleep (duration . toMillis () );
975
1007
events .status (msg +" (retrying:" +retry +")" ,e );
976
1008
}
977
1009
}
0 commit comments