@@ -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
@@ -485,110 +486,77 @@ func (c *Connector) findAndConnectBackend(ctx context.Context, frontendConn net.
485486 WithField ("player" , playerInfo ).
486487 Info ("Connecting to backend" )
487488
488- var backendConn net.Conn
489- var err error
490-
491- if nextState == mcproto .StateStatus {
492- // Status request: try to connect once with backendStatusTimeout
493- backendConn , err = net .DialTimeout ("tcp" , backendHostPort , backendStatusTimeout )
494- if err != nil {
489+ // We want to try to connect to the backend every backendRetryInterval
490+ var backendTry retry.Backoff
491+
492+ switch nextState {
493+ case mcproto .StateStatus :
494+ // Status request: try to connect once with backendStatusTimeout
495+ backendTry = retry .NewConstant (backendStatusTimeout )
496+ backendTry = retry .WithMaxRetries (0 , backendTry )
497+ case mcproto .StateLogin :
498+ backendTry = retry .NewConstant (backendRetryInterval )
499+ // Connect request: if autoscaler is enabled, try to connect until backendTimeout is reached
500+ if waker != nil {
501+ // Autoscaler enabled: retry until backendTimeout is reached
502+ backendTry = retry .WithMaxDuration (backendTimeout , backendTry )
503+ } else {
504+ // Autoscaler disabled: try to connect once with backendRetryInterval
505+ backendTry = retry .WithMaxRetries (0 , backendTry )
506+ }
507+ default :
508+ // Unknown state, do nothing
495509 logrus .
496- WithError (err ).
497510 WithField ("client" , clientAddr ).
498511 WithField ("serverAddress" , serverAddress ).
499- WithField ("backend " , backendHostPort ).
512+ WithField ("nextState " , nextState ).
500513 WithField ("player" , playerInfo ).
501- Warn ("Unable to connect to backend for status request" )
502- c .metrics .Errors .With ("type" , "backend_failed" ).Add (1 )
514+ Error ("Unknown state, unable to connect to backend" )
515+ return
516+ }
503517
504- if c .connectionNotifier != nil {
505- notifyErr := c .connectionNotifier .NotifyFailedBackendConnection (ctx , clientAddr , serverAddress , playerInfo , backendHostPort , err )
506- if notifyErr != nil {
507- logrus .WithError (notifyErr ).Warn ("failed to notify failed backend connection" )
508- }
509- }
518+ var backendConn net.Conn
519+ if retryErr := retry .Do (ctx , backendTry , func (ctx context.Context ) error {
520+ logrus .Debug ("Attempting to connect" )
521+ var err error
522+ backendConn , err = net .Dial ("tcp" , backendHostPort )
523+ if err != nil { return retry .RetryableError (err ) }
524+ return nil
525+ }); retryErr != nil {
526+ logrus .
527+ WithError (retryErr ).
528+ WithField ("client" , clientAddr ).
529+ WithField ("serverAddress" , serverAddress ).
530+ WithField ("backend" , backendHostPort ).
531+ WithField ("player" , playerInfo ).
532+ Warn ("Unable to connect to backend" )
533+ c .metrics .Errors .With ("type" , "backend_failed" ).Add (1 )
510534
511- // Return fakeOnline MOTD
512- if c .fakeOnline && waker != nil {
513- logrus .Info ("Server is offline, sending fakeOnlineMOTD for status request" )
514- writeStatusErr := mcproto .WriteStatusResponse (
515- frontendConn ,
516- c .fakeOnlineMOTD ,
517- )
518- if writeStatusErr != nil {
519- logrus .
520- WithError (writeStatusErr ).
521- WithField ("client" , clientAddr ).
522- WithField ("serverAddress" , serverAddress ).
523- WithField ("backend" , backendHostPort ).
524- WithField ("player" , playerInfo ).
525- Error ("Failed to write status response" )
526- }
535+ if c .connectionNotifier != nil {
536+ notifyErr := c .connectionNotifier .NotifyFailedBackendConnection (ctx , clientAddr , serverAddress , playerInfo , backendHostPort , retryErr )
537+ if notifyErr != nil {
538+ logrus .WithError (notifyErr ).Warn ("failed to notify failed backend connection" )
527539 }
528- return
529540 }
530- } else if nextState == mcproto .StateLogin {
531- // Connect request
532- if waker != nil {
533- logrus .Debug ("Connect: Autoscaler is enabled, waiting for backend to be ready" )
534- // Autoscaler enabled: retry until backendTimeout is reached
535- deadline := time .Now ().Add (backendTimeout )
536- for {
537- backendConn , err = net .DialTimeout ("tcp" , backendHostPort , backendRetryInterval )
538- logrus .Debug ("Tries to connect to backend" )
539-
540- if err == nil {
541- break
542- }
543- if time .Now ().After (deadline ) {
544- logrus .
545- WithError (err ).
546- WithField ("client" , clientAddr ).
547- WithField ("serverAddress" , serverAddress ).
548- WithField ("backend" , backendHostPort ).
549- WithField ("player" , playerInfo ).
550- Warn ("Unable to connect to backend after retries (autoscaler enabled)" )
551- c .metrics .Errors .With ("type" , "backend_failed" ).Add (1 )
552- if c .connectionNotifier != nil {
553- notifyErr := c .connectionNotifier .NotifyFailedBackendConnection (ctx , clientAddr , serverAddress , playerInfo , backendHostPort , err )
554- if notifyErr != nil {
555- logrus .WithError (notifyErr ).Warn ("failed to notify failed backend connection" )
556- }
557- }
558- return
559- }
560- time .Sleep (backendRetryInterval )
561- }
562- } else {
563- logrus .Debug ("Connect: Autoscaler is disabled, trying to connect once" )
564- // Autoscaler disabled: try to connect once with backendTimeout
565- backendConn , err = net .DialTimeout ("tcp" , backendHostPort , backendTimeout )
566- if err != nil {
541+
542+ if nextState == mcproto .StateStatus && c .fakeOnline && waker != nil {
543+ logrus .Info ("Server is offline, sending fakeOnlineMOTD for status request" )
544+ writeStatusErr := mcproto .WriteStatusResponse (
545+ frontendConn ,
546+ c .fakeOnlineMOTD ,
547+ )
548+
549+ if writeStatusErr != nil {
567550 logrus .
568- WithError (err ).
551+ WithError (writeStatusErr ).
569552 WithField ("client" , clientAddr ).
570553 WithField ("serverAddress" , serverAddress ).
571554 WithField ("backend" , backendHostPort ).
572555 WithField ("player" , playerInfo ).
573- Warn ("Unable to connect to backend (autoscaler disabled)" )
574- c .metrics .Errors .With ("type" , "backend_failed" ).Add (1 )
575- if c .connectionNotifier != nil {
576- notifyErr := c .connectionNotifier .NotifyFailedBackendConnection (ctx , clientAddr , serverAddress , playerInfo , backendHostPort , err )
577- if notifyErr != nil {
578- logrus .WithError (notifyErr ).Warn ("failed to notify failed backend connection" )
579- }
580- }
581- return
556+ Error ("Failed to write status response" )
582557 }
583558 }
584- } else {
585- // Unknown state, do nothing
586- logrus .
587- WithField ("client" , clientAddr ).
588- WithField ("serverAddress" , serverAddress ).
589- WithField ("nextState" , nextState ).
590- WithField ("player" , playerInfo ).
591- Warn ("Unknown state, unable to connect to backend" )
559+
592560 return
593561 }
594562
0 commit comments