@@ -21,12 +21,13 @@ import (
2121 "github.com/juju/ratelimit"
2222 "github.com/pires/go-proxyproto"
2323 "github.com/sirupsen/logrus"
24+ "github.com/sethvargo/go-retry"
2425)
2526
2627const (
2728 handshakeTimeout = 5 * time .Second
2829 backendTimeout = 30 * time .Second
29- backendRetryInterval = 5 * time .Second
30+ backendRetryInterval = 3 * time .Second
3031 backendStatusTimeout = 1 * time .Second
3132)
3233
@@ -402,110 +403,77 @@ func (c *Connector) findAndConnectBackend(ctx context.Context, frontendConn net.
402403 WithField ("player" , playerInfo ).
403404 Info ("Connecting to backend" )
404405
405- var backendConn net.Conn
406- var err error
407-
408- if nextState == mcproto .StateStatus {
409- // Status request: try to connect once with backendStatusTimeout
410- backendConn , err = net .DialTimeout ("tcp" , backendHostPort , backendStatusTimeout )
411- if err != nil {
406+ // We want to try to connect to the backend every backendRetryInterval
407+ var backendTry retry.Backoff
408+
409+ switch nextState {
410+ case mcproto .StateStatus :
411+ // Status request: try to connect once with backendStatusTimeout
412+ backendTry = retry .NewConstant (backendStatusTimeout )
413+ backendTry = retry .WithMaxRetries (0 , backendTry )
414+ case mcproto .StateLogin :
415+ backendTry = retry .NewConstant (backendRetryInterval )
416+ // Connect request: if autoscaler is enabled, try to connect until backendTimeout is reached
417+ if waker != nil {
418+ // Autoscaler enabled: retry until backendTimeout is reached
419+ backendTry = retry .WithMaxDuration (backendTimeout , backendTry )
420+ } else {
421+ // Autoscaler disabled: try to connect once with backendRetryInterval
422+ backendTry = retry .WithMaxRetries (0 , backendTry )
423+ }
424+ default :
425+ // Unknown state, do nothing
412426 logrus .
413- WithError (err ).
414427 WithField ("client" , clientAddr ).
415428 WithField ("serverAddress" , serverAddress ).
416- WithField ("backend " , backendHostPort ).
429+ WithField ("nextState " , nextState ).
417430 WithField ("player" , playerInfo ).
418- Warn ("Unable to connect to backend for status request" )
419- c .metrics .Errors .With ("type" , "backend_failed" ).Add (1 )
431+ Error ("Unknown state, unable to connect to backend" )
432+ return
433+ }
420434
421- if c .connectionNotifier != nil {
422- notifyErr := c .connectionNotifier .NotifyFailedBackendConnection (ctx , clientAddr , serverAddress , playerInfo , backendHostPort , err )
423- if notifyErr != nil {
424- logrus .WithError (notifyErr ).Warn ("failed to notify failed backend connection" )
425- }
426- }
435+ var backendConn net.Conn
436+ if retryErr := retry .Do (ctx , backendTry , func (ctx context.Context ) error {
437+ logrus .Debug ("Attempting to connect" )
438+ var err error
439+ backendConn , err = net .Dial ("tcp" , backendHostPort )
440+ if err != nil { return retry .RetryableError (err ) }
441+ return nil
442+ }); retryErr != nil {
443+ logrus .
444+ WithError (retryErr ).
445+ WithField ("client" , clientAddr ).
446+ WithField ("serverAddress" , serverAddress ).
447+ WithField ("backend" , backendHostPort ).
448+ WithField ("player" , playerInfo ).
449+ Warn ("Unable to connect to backend" )
450+ c .metrics .Errors .With ("type" , "backend_failed" ).Add (1 )
427451
428- // Return fakeOnline MOTD
429- if c .fakeOnline && waker != nil {
430- logrus .Info ("Server is offline, sending fakeOnlineMOTD for status request" )
431- writeStatusErr := mcproto .WriteStatusResponse (
432- frontendConn ,
433- c .fakeOnlineMOTD ,
434- )
435- if writeStatusErr != nil {
436- logrus .
437- WithError (writeStatusErr ).
438- WithField ("client" , clientAddr ).
439- WithField ("serverAddress" , serverAddress ).
440- WithField ("backend" , backendHostPort ).
441- WithField ("player" , playerInfo ).
442- Error ("Failed to write status response" )
443- }
452+ if c .connectionNotifier != nil {
453+ notifyErr := c .connectionNotifier .NotifyFailedBackendConnection (ctx , clientAddr , serverAddress , playerInfo , backendHostPort , retryErr )
454+ if notifyErr != nil {
455+ logrus .WithError (notifyErr ).Warn ("failed to notify failed backend connection" )
444456 }
445- return
446457 }
447- } else if nextState == mcproto .StateLogin {
448- // Connect request
449- if waker != nil {
450- logrus .Debug ("Connect: Autoscaler is enabled, waiting for backend to be ready" )
451- // Autoscaler enabled: retry until backendTimeout is reached
452- deadline := time .Now ().Add (backendTimeout )
453- for {
454- backendConn , err = net .DialTimeout ("tcp" , backendHostPort , backendRetryInterval )
455- logrus .Debug ("Tries to connect to backend" )
456-
457- if err == nil {
458- break
459- }
460- if time .Now ().After (deadline ) {
461- logrus .
462- WithError (err ).
463- WithField ("client" , clientAddr ).
464- WithField ("serverAddress" , serverAddress ).
465- WithField ("backend" , backendHostPort ).
466- WithField ("player" , playerInfo ).
467- Warn ("Unable to connect to backend after retries (autoscaler enabled)" )
468- c .metrics .Errors .With ("type" , "backend_failed" ).Add (1 )
469- if c .connectionNotifier != nil {
470- notifyErr := c .connectionNotifier .NotifyFailedBackendConnection (ctx , clientAddr , serverAddress , playerInfo , backendHostPort , err )
471- if notifyErr != nil {
472- logrus .WithError (notifyErr ).Warn ("failed to notify failed backend connection" )
473- }
474- }
475- return
476- }
477- time .Sleep (backendRetryInterval )
478- }
479- } else {
480- logrus .Debug ("Connect: Autoscaler is disabled, trying to connect once" )
481- // Autoscaler disabled: try to connect once with backendTimeout
482- backendConn , err = net .DialTimeout ("tcp" , backendHostPort , backendTimeout )
483- if err != nil {
458+
459+ if nextState == mcproto .StateStatus && c .fakeOnline && waker != nil {
460+ logrus .Info ("Server is offline, sending fakeOnlineMOTD for status request" )
461+ writeStatusErr := mcproto .WriteStatusResponse (
462+ frontendConn ,
463+ c .fakeOnlineMOTD ,
464+ )
465+
466+ if writeStatusErr != nil {
484467 logrus .
485- WithError (err ).
468+ WithError (writeStatusErr ).
486469 WithField ("client" , clientAddr ).
487470 WithField ("serverAddress" , serverAddress ).
488471 WithField ("backend" , backendHostPort ).
489472 WithField ("player" , playerInfo ).
490- Warn ("Unable to connect to backend (autoscaler disabled)" )
491- c .metrics .Errors .With ("type" , "backend_failed" ).Add (1 )
492- if c .connectionNotifier != nil {
493- notifyErr := c .connectionNotifier .NotifyFailedBackendConnection (ctx , clientAddr , serverAddress , playerInfo , backendHostPort , err )
494- if notifyErr != nil {
495- logrus .WithError (notifyErr ).Warn ("failed to notify failed backend connection" )
496- }
497- }
498- return
473+ Error ("Failed to write status response" )
499474 }
500475 }
501- } else {
502- // Unknown state, do nothing
503- logrus .
504- WithField ("client" , clientAddr ).
505- WithField ("serverAddress" , serverAddress ).
506- WithField ("nextState" , nextState ).
507- WithField ("player" , playerInfo ).
508- Warn ("Unknown state, unable to connect to backend" )
476+
509477 return
510478 }
511479
0 commit comments