@@ -25,7 +25,9 @@ import (
2525
2626const (
2727 handshakeTimeout = 5 * time .Second
28- backendTimeout = 1 * time .Second
28+ backendTimeout = 30 * time .Second
29+ backendRetryInterval = 5 * time .Second
30+ backendStatusTimeout = 1 * time .Second
2931)
3032
3133var noDeadline time.Time
@@ -428,7 +430,7 @@ func (c *Connector) cleanupBackendConnection(ctx context.Context, clientAddr net
428430}
429431
430432func (c * Connector ) findAndConnectBackend (ctx context.Context , frontendConn net.Conn ,
431- clientAddr net.Addr , preReadContent io.Reader , serverAddress string , playerInfo * PlayerInfo , nextState mcproto.State ) {
433+ clientAddr net.Addr , preReadContent io.Reader , serverAddress string , playerInfo * PlayerInfo , nextState mcproto.State ) {
432434
433435 backendHostPort , resolvedHost , waker , _ := Routes .FindBackendForServerAddress (ctx , serverAddress )
434436 cleanupMetrics := false
@@ -458,72 +460,137 @@ func (c *Connector) findAndConnectBackend(ctx context.Context, frontendConn net.
458460 }
459461 }
460462
461- if backendHostPort == "" {
463+ if backendHostPort == "" {
464+ logrus .
465+ WithField ("serverAddress" , serverAddress ).
466+ WithField ("resolvedHost" , resolvedHost ).
467+ WithField ("player" , playerInfo ).
468+ Warn ("Unable to find registered backend" )
469+ c .metrics .Errors .With ("type" , "missing_backend" ).Add (1 )
470+
471+ if c .connectionNotifier != nil {
472+ err := c .connectionNotifier .NotifyMissingBackend (ctx , clientAddr , serverAddress , playerInfo )
473+ if err != nil {
474+ logrus .WithError (err ).Warn ("failed to notify missing backend" )
475+ }
476+ }
477+
478+ return
479+ }
480+
481+ logrus .
482+ WithField ("client" , clientAddr ).
483+ WithField ("server" , serverAddress ).
484+ WithField ("backendHostPort" , backendHostPort ).
485+ WithField ("player" , playerInfo ).
486+ Info ("Connecting to backend" )
487+
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 {
495+ logrus .
496+ WithError (err ).
497+ WithField ("client" , clientAddr ).
498+ WithField ("serverAddress" , serverAddress ).
499+ WithField ("backend" , backendHostPort ).
500+ WithField ("player" , playerInfo ).
501+ Warn ("Unable to connect to backend for status request" )
502+ c .metrics .Errors .With ("type" , "backend_failed" ).Add (1 )
503+
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+ }
510+
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+ }
527+ }
528+ return
529+ }
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 {
567+ logrus .
568+ WithError (err ).
569+ WithField ("client" , clientAddr ).
570+ WithField ("serverAddress" , serverAddress ).
571+ WithField ("backend" , backendHostPort ).
572+ 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
582+ }
583+ }
584+ } else {
585+ // Unknown state, do nothing
462586 logrus .
463- WithField ("serverAddress" , serverAddress ).
464- WithField ("resolvedHost" , resolvedHost ).
465- WithField ("player" , playerInfo ).
466- Warn ("Unable to find registered backend" )
467- c .metrics .Errors .With ("type" , "missing_backend" ).Add (1 )
468-
469- if c .connectionNotifier != nil {
470- err := c .connectionNotifier .NotifyMissingBackend (ctx , clientAddr , serverAddress , playerInfo )
471- if err != nil {
472- logrus .WithError (err ).Warn ("failed to notify missing backend" )
473- }
474- }
475-
476- return
477- }
478-
479- logrus .
480- WithField ("client" , clientAddr ).
481- WithField ("server" , serverAddress ).
482- WithField ("backendHostPort" , backendHostPort ).
483- WithField ("player" , playerInfo ).
484- Info ("Connecting to backend" )
485-
486- backendConn , err := net .DialTimeout ("tcp" , backendHostPort , backendTimeout )
487- if err != nil {
488- logrus .
489- WithError (err ).
490587 WithField ("client" , clientAddr ).
491588 WithField ("serverAddress" , serverAddress ).
492- WithField ("backend " , backendHostPort ).
589+ WithField ("nextState " , nextState ).
493590 WithField ("player" , playerInfo ).
494- Warn ("Unable to connect to backend" )
495- c .metrics .Errors .With ("type" , "backend_failed" ).Add (1 )
496-
497- if c .connectionNotifier != nil {
498- notifyErr := c .connectionNotifier .NotifyFailedBackendConnection (ctx , clientAddr , serverAddress , playerInfo , backendHostPort , err )
499- if notifyErr != nil {
500- logrus .WithError (notifyErr ).Warn ("failed to notify failed backend connection" )
501- }
502- }
503-
504- // Verify that the packet is a status request && autoScaleUp is enabled
505- if c .fakeOnline && waker != nil && nextState == mcproto .StateStatus {
506- logrus .Info ("Server is offline, sending fakeOnlineMOTD" )
507-
508- // Send a response to the client indicating that the server is sleeping
509- writeStatusErr := mcproto .WriteStatusResponse (
510- frontendConn ,
511- c .fakeOnlineMOTD ,
512- )
513-
514- if writeStatusErr != nil {
515- logrus .
516- WithError (writeStatusErr ).
517- WithField ("client" , clientAddr ).
518- WithField ("serverAddress" , serverAddress ).
519- WithField ("backend" , backendHostPort ).
520- WithField ("player" , playerInfo ).
521- Error ("Failed to write status response" )
522- }
523- }
524-
525- return
526- }
591+ Warn ("Unknown state, unable to connect to backend" )
592+ return
593+ }
527594
528595 if c .connectionNotifier != nil {
529596 err := c .connectionNotifier .NotifyConnected (ctx , clientAddr , serverAddress , playerInfo , backendHostPort )
0 commit comments