go-micro.dev/v5@v5.12.0/server/rpc_server.go (about)

     1  package server
     2  
     3  import (
     4  	"context"
     5  	"io"
     6  	"net"
     7  	"runtime/debug"
     8  	"sort"
     9  	"strconv"
    10  	"strings"
    11  	"sync"
    12  	"time"
    13  
    14  	"github.com/pkg/errors"
    15  
    16  	"go-micro.dev/v5/broker"
    17  	"go-micro.dev/v5/codec"
    18  	log "go-micro.dev/v5/logger"
    19  	"go-micro.dev/v5/metadata"
    20  	"go-micro.dev/v5/registry"
    21  	"go-micro.dev/v5/transport"
    22  	"go-micro.dev/v5/transport/headers"
    23  	"go-micro.dev/v5/util/addr"
    24  	"go-micro.dev/v5/util/backoff"
    25  	mnet "go-micro.dev/v5/util/net"
    26  	"go-micro.dev/v5/util/socket"
    27  )
    28  
    29  type rpcServer struct {
    30  	opts Options
    31  	// Subscribe to service name
    32  	subscriber broker.Subscriber
    33  	// Goal:
    34  	// router Router
    35  	router *router
    36  	exit   chan chan error
    37  
    38  	handlers    map[string]Handler
    39  	subscribers map[Subscriber][]broker.Subscriber
    40  	// Graceful exit
    41  	wg *sync.WaitGroup
    42  	// Cached service
    43  	rsvc *registry.Service
    44  
    45  	sync.RWMutex
    46  	// Marks the serve as started
    47  	started bool
    48  	// Used for first registration
    49  	registered bool
    50  }
    51  
    52  // NewRPCServer will create a new default RPC server.
    53  func NewRPCServer(opts ...Option) Server {
    54  	options := NewOptions(opts...)
    55  	router := newRpcRouter()
    56  	router.hdlrWrappers = options.HdlrWrappers
    57  	router.subWrappers = options.SubWrappers
    58  
    59  	return &rpcServer{
    60  		opts:        options,
    61  		router:      router,
    62  		handlers:    make(map[string]Handler),
    63  		subscribers: make(map[Subscriber][]broker.Subscriber),
    64  		exit:        make(chan chan error),
    65  		wg:          wait(options.Context),
    66  	}
    67  }
    68  
    69  func (s *rpcServer) Init(opts ...Option) error {
    70  	s.Lock()
    71  	defer s.Unlock()
    72  
    73  	for _, opt := range opts {
    74  		opt(&s.opts)
    75  	}
    76  
    77  	// update router if its the default
    78  	if s.opts.Router == nil {
    79  		r := newRpcRouter()
    80  		r.hdlrWrappers = s.opts.HdlrWrappers
    81  		r.serviceMap = s.router.serviceMap
    82  		r.subWrappers = s.opts.SubWrappers
    83  		s.router = r
    84  	}
    85  
    86  	s.rsvc = nil
    87  
    88  	return nil
    89  }
    90  
    91  // ServeConn serves a single connection.
    92  func (s *rpcServer) ServeConn(sock transport.Socket) {
    93  	logger := s.opts.Logger
    94  
    95  	// Global error tracking
    96  	var gerr error
    97  
    98  	// Keep track of Connection: close header
    99  	var closeConn bool
   100  
   101  	// Streams are multiplexed on Micro-Stream or Micro-Id header
   102  	pool := socket.NewPool()
   103  
   104  	// Waitgroup to wait for processing to finish
   105  	// A double waitgroup is used to block the global waitgroup incase it is
   106  	// empty, but only wait for the local routines to finish with the local waitgroup.
   107  	wg := NewWaitGroup(s.getWg())
   108  
   109  	defer func() {
   110  		// Only wait if there's no error
   111  		if gerr != nil {
   112  			select {
   113  			case <-s.exit:
   114  			default:
   115  				// EOF is expected if the client closes the connection
   116  				if !errors.Is(gerr, io.EOF) {
   117  					logger.Logf(log.ErrorLevel, "error while serving connection: %v", gerr)
   118  				}
   119  			}
   120  		} else {
   121  			wg.Wait()
   122  		}
   123  
   124  		// Close all the sockets for this connection
   125  		pool.Close()
   126  
   127  		// Close underlying socket
   128  		if err := sock.Close(); err != nil {
   129  			logger.Logf(log.ErrorLevel, "failed to close socket: %v", err)
   130  		}
   131  
   132  		// recover any panics
   133  		if r := recover(); r != nil {
   134  			logger.Log(log.ErrorLevel, "panic recovered: ", r)
   135  			logger.Log(log.ErrorLevel, string(debug.Stack()))
   136  		}
   137  	}()
   138  
   139  	for {
   140  		msg := transport.Message{
   141  			Header: make(map[string]string),
   142  		}
   143  
   144  		// Close connection if Connection: close header was set
   145  		if closeConn {
   146  			return
   147  		}
   148  
   149  		// Process inbound messages one at a time
   150  		if err := sock.Recv(&msg); err != nil {
   151  			// Set a global error and return.
   152  			// We're saying we essentially can't
   153  			// use the socket anymore
   154  			gerr = errors.Wrapf(err, "%s-%s | %s", s.opts.Name, s.opts.Id, sock.Remote())
   155  
   156  			return
   157  		}
   158  
   159  		// Keep track of when to close the connection
   160  		if c := msg.Header["Connection"]; c == "close" {
   161  			closeConn = true
   162  		}
   163  
   164  		// Check the message header for micro message header, if so handle
   165  		// as micro event
   166  		if t := msg.Header[headers.Message]; len(t) > 0 {
   167  			// Process the event
   168  			ev := newEvent(msg)
   169  
   170  			if err := s.HandleEvent(ev.Topic())(ev); err != nil {
   171  				msg.Header[headers.Error] = err.Error()
   172  				logger.Logf(log.ErrorLevel, "failed to handle event: %v", err)
   173  			}
   174  			// Write back some 200
   175  			if err := sock.Send(&transport.Message{Header: msg.Header}); err != nil {
   176  				gerr = err
   177  				break
   178  			}
   179  
   180  			continue
   181  		}
   182  
   183  		// business as usual
   184  
   185  		// use Micro-Stream as the stream identifier
   186  		// in the event its blank we'll always process
   187  		// on the same socket
   188  		var (
   189  			stream bool
   190  			id     string
   191  		)
   192  
   193  		if s := getHeader(headers.Stream, msg.Header); len(s) > 0 {
   194  			id = s
   195  			stream = true
   196  		} else {
   197  			// If there's no stream id then its a standard request
   198  			// use the Micro-Id
   199  			id = msg.Header[headers.ID]
   200  		}
   201  
   202  		// Check if we have an existing socket
   203  		psock, ok := pool.Get(id)
   204  
   205  		// If we don't have a socket and its a stream
   206  		// Check if its a last stream EOS error
   207  		if !ok && stream && msg.Header[headers.Error] == errLastStreamResponse.Error() {
   208  			closeConn = true
   209  			pool.Release(psock)
   210  
   211  			continue
   212  		}
   213  
   214  		// Got an existing socket already
   215  		if ok {
   216  			// we're starting processing
   217  			wg.Add(1)
   218  
   219  			// Pass the message to that existing socket
   220  			if err := psock.Accept(&msg); err != nil {
   221  				// Release the socket if there's an error
   222  				pool.Release(psock)
   223  			}
   224  
   225  			wg.Done()
   226  
   227  			continue
   228  		}
   229  
   230  		// No socket was found so its new
   231  		// Set the local and remote values
   232  		psock.SetLocal(sock.Local())
   233  		psock.SetRemote(sock.Remote())
   234  
   235  		// Load the socket with the current message
   236  		if err := psock.Accept(&msg); err != nil {
   237  			logger.Logf(log.ErrorLevel, "Socket failed to accept message: %v", err)
   238  		}
   239  
   240  		// Now walk the usual path
   241  
   242  		// We use this Timeout header to set a server deadline
   243  		to := msg.Header["Timeout"]
   244  		// We use this Content-Type header to identify the codec needed
   245  		contentType := msg.Header["Content-Type"]
   246  
   247  		// Copy the message headers
   248  		header := make(map[string]string, len(msg.Header))
   249  		for k, v := range msg.Header {
   250  			header[k] = v
   251  		}
   252  
   253  		// Set local/remote ips
   254  		header["Local"] = sock.Local()
   255  		header["Remote"] = sock.Remote()
   256  
   257  		// Create new context with the metadata
   258  		ctx := metadata.NewContext(context.Background(), header)
   259  
   260  		// Set the timeout from the header if we have it
   261  		if len(to) > 0 {
   262  			if n, err := strconv.ParseUint(to, 10, 64); err == nil {
   263  				var cancel context.CancelFunc
   264  
   265  				ctx, cancel = context.WithTimeout(ctx, time.Duration(n))
   266  				defer cancel()
   267  			}
   268  		}
   269  
   270  		// If there's no content type default it
   271  		if len(contentType) == 0 {
   272  			msg.Header["Content-Type"] = DefaultContentType
   273  			contentType = DefaultContentType
   274  		}
   275  
   276  		// Setup old protocol
   277  		cf := setupProtocol(&msg)
   278  
   279  		// No legacy codec needed
   280  		if cf == nil {
   281  			var err error
   282  			// Try get a new codec
   283  			if cf, err = s.newCodec(contentType); err != nil {
   284  				// No codec found so send back an error
   285  				if err = sock.Send(&transport.Message{
   286  					Header: map[string]string{
   287  						"Content-Type": "text/plain",
   288  					},
   289  					Body: []byte(err.Error()),
   290  				}); err != nil {
   291  					gerr = err
   292  				}
   293  
   294  				pool.Release(psock)
   295  
   296  				continue
   297  			}
   298  		}
   299  
   300  		// Create a new rpc codec based on the pseudo socket and codec
   301  		rcodec := newRPCCodec(&msg, psock, cf)
   302  		// Check the protocol as well
   303  		protocol := rcodec.String()
   304  
   305  		// Internal request
   306  		request := rpcRequest{
   307  			service:     getHeader(headers.Request, msg.Header),
   308  			method:      getHeader(headers.Method, msg.Header),
   309  			endpoint:    getHeader(headers.Endpoint, msg.Header),
   310  			contentType: contentType,
   311  			codec:       rcodec,
   312  			header:      msg.Header,
   313  			body:        msg.Body,
   314  			socket:      psock,
   315  			stream:      stream,
   316  		}
   317  
   318  		// Internal response
   319  		response := rpcResponse{
   320  			header: make(map[string]string),
   321  			socket: psock,
   322  			codec:  rcodec,
   323  		}
   324  
   325  		// Wait for two coroutines to exit
   326  		// Serve the request and process the outbound messages
   327  		wg.Add(2)
   328  
   329  		// Process the outbound messages from the socket
   330  		go func(psock *socket.Socket) {
   331  			defer func() {
   332  				if r := recover(); r != nil {
   333  					logger.Log(log.ErrorLevel, "panic recovered in outbound goroutine: ", r)
   334  					logger.Log(log.ErrorLevel, string(debug.Stack()))
   335  				}
   336  				// TODO: don't hack this but if its grpc just break out of the stream
   337  				// We do this because the underlying connection is h2 and its a stream
   338  				if protocol == "grpc" {
   339  					if err := sock.Close(); err != nil {
   340  						logger.Logf(log.ErrorLevel, "Failed to close socket: %v", err)
   341  					}
   342  				}
   343  
   344  				s.deferer(pool, psock, wg)
   345  			}()
   346  
   347  			for {
   348  				// Get the message from our internal handler/stream
   349  				m := new(transport.Message)
   350  				if err := psock.Process(m); err != nil {
   351  					return
   352  				}
   353  
   354  				// Send the message back over the socket
   355  				if err := sock.Send(m); err != nil {
   356  					return
   357  				}
   358  			}
   359  		}(psock)
   360  
   361  		// Serve the request in a go routine as this may be a stream
   362  		go func(psock *socket.Socket) {
   363  			defer func() {
   364  				if r := recover(); r != nil {
   365  					logger.Log(log.ErrorLevel, "panic recovered in serveReq goroutine: ", r)
   366  					logger.Log(log.ErrorLevel, string(debug.Stack()))
   367  				}
   368  				s.deferer(pool, psock, wg)
   369  			}()
   370  
   371  			s.serveReq(ctx, msg, &request, &response, rcodec)
   372  		}(psock)
   373  	}
   374  }
   375  
   376  func (s *rpcServer) NewHandler(h interface{}, opts ...HandlerOption) Handler {
   377  	return s.router.NewHandler(h, opts...)
   378  }
   379  
   380  func (s *rpcServer) Handle(h Handler) error {
   381  	s.Lock()
   382  	defer s.Unlock()
   383  
   384  	if err := s.router.Handle(h); err != nil {
   385  		return err
   386  	}
   387  
   388  	s.handlers[h.Name()] = h
   389  
   390  	return nil
   391  }
   392  
   393  func (s *rpcServer) Register() error {
   394  	config := s.Options()
   395  	logger := config.Logger
   396  
   397  	// Registry function used to register the service
   398  	regFunc := s.newRegFuc(config)
   399  
   400  	// Directly register if service was cached
   401  	rsvc := s.getCachedService()
   402  	if rsvc != nil {
   403  		if err := regFunc(rsvc); err != nil {
   404  			return errors.Wrap(err, "failed to register service")
   405  		}
   406  
   407  		return nil
   408  	}
   409  
   410  	// Only cache service if host IP valid
   411  	addr, cacheService, err := s.getAddr(config)
   412  	if err != nil {
   413  		return err
   414  	}
   415  
   416  	node := &registry.Node{
   417  		// TODO: node id should be set better. Add native option to specify
   418  		// host id through either config or ENV. Also look at logging of name.
   419  		Id:       config.Name + "-" + config.Id,
   420  		Address:  addr,
   421  		Metadata: s.newNodeMetedata(config),
   422  	}
   423  
   424  	service := &registry.Service{
   425  		Name:      config.Name,
   426  		Version:   config.Version,
   427  		Nodes:     []*registry.Node{node},
   428  		Endpoints: s.getEndpoints(),
   429  	}
   430  
   431  	registered := s.isRegistered()
   432  	if !registered {
   433  		logger.Logf(log.InfoLevel, "Registry [%s] Registering node: %s", config.Registry.String(), node.Id)
   434  	}
   435  
   436  	// Register the service
   437  	if err := regFunc(service); err != nil {
   438  		return errors.Wrap(err, "failed to register service")
   439  	}
   440  
   441  	// Already registered? don't need to register subscribers
   442  	if registered {
   443  		return nil
   444  	}
   445  
   446  	s.Lock()
   447  	defer s.Unlock()
   448  
   449  	s.registered = true
   450  
   451  	// Cache service
   452  	if cacheService {
   453  		s.rsvc = service
   454  	}
   455  
   456  	// Set what we're advertising
   457  	s.opts.Advertise = addr
   458  
   459  	return nil
   460  }
   461  
   462  func (s *rpcServer) Deregister() error {
   463  	config := s.Options()
   464  	logger := config.Logger
   465  
   466  	addr, _, err := s.getAddr(config)
   467  	if err != nil {
   468  		return err
   469  	}
   470  
   471  	// TODO: there should be a better way to do this than reconstruct the service
   472  	// Edge case is that if service is not cached
   473  	node := &registry.Node{
   474  		// TODO: also update node id naming
   475  		Id:      config.Name + "-" + config.Id,
   476  		Address: addr,
   477  	}
   478  
   479  	service := &registry.Service{
   480  		Name:    config.Name,
   481  		Version: config.Version,
   482  		Nodes:   []*registry.Node{node},
   483  	}
   484  
   485  	logger.Logf(log.InfoLevel, "Registry [%s] Deregistering node: %s", config.Registry.String(), node.Id)
   486  
   487  	if err := config.Registry.Deregister(service); err != nil {
   488  		return err
   489  	}
   490  
   491  	s.Lock()
   492  	defer s.Unlock()
   493  
   494  	s.rsvc = nil
   495  
   496  	if !s.registered {
   497  		return nil
   498  	}
   499  
   500  	s.registered = false
   501  
   502  	// close the subscriber
   503  	if s.subscriber != nil {
   504  		if err := s.subscriber.Unsubscribe(); err != nil {
   505  			logger.Logf(log.ErrorLevel, "Failed to unsubscribe service from service name topic: %v", err)
   506  		}
   507  
   508  		s.subscriber = nil
   509  	}
   510  
   511  	for sb, subs := range s.subscribers {
   512  		for i, sub := range subs {
   513  			logger.Logf(log.InfoLevel, "Unsubscribing %s from topic: %s", node.Id, sub.Topic())
   514  
   515  			if err := sub.Unsubscribe(); err != nil {
   516  				logger.Logf(log.ErrorLevel,
   517  					"Failed to unsubscribe subscriber nr. %d from topic %s: %v",
   518  					i+1,
   519  					sub.Topic(),
   520  					err)
   521  			}
   522  		}
   523  
   524  		s.subscribers[sb] = nil
   525  	}
   526  
   527  	return nil
   528  }
   529  
   530  func (s *rpcServer) Start() error {
   531  	if s.isStarted() {
   532  		return nil
   533  	}
   534  
   535  	config := s.Options()
   536  	logger := config.Logger
   537  
   538  	// start listening on the listener
   539  	listener, err := config.Transport.Listen(config.Address, config.ListenOptions...)
   540  	if err != nil {
   541  		return err
   542  	}
   543  
   544  	logger.Logf(log.InfoLevel, "Transport [%s] Listening on %s", config.Transport.String(), listener.Addr())
   545  
   546  	// swap address
   547  	addr := s.swapAddr(config, listener.Addr())
   548  
   549  	// connect to the broker
   550  	brokerName := config.Broker.String()
   551  	if err = config.Broker.Connect(); err != nil {
   552  		logger.Logf(log.ErrorLevel, "Broker [%s] connect error: %v", brokerName, err)
   553  		return err
   554  	}
   555  
   556  	logger.Logf(log.InfoLevel, "Broker [%s] Connected to %s", brokerName, config.Broker.Address())
   557  
   558  	// Use RegisterCheck func before register
   559  	if err = s.opts.RegisterCheck(s.opts.Context); err != nil {
   560  		logger.Logf(log.ErrorLevel, "Server %s-%s register check error: %s", config.Name, config.Id, err)
   561  	} else if err = s.Register(); err != nil {
   562  		// Perform initial registration
   563  		logger.Logf(log.ErrorLevel, "Server %s-%s register error: %s", config.Name, config.Id, err)
   564  	}
   565  
   566  	exit := make(chan bool)
   567  
   568  	// Listen for connections
   569  	go s.listen(listener, exit)
   570  
   571  	// Keep the service registered to registry
   572  	go s.registrar(listener, addr, config, exit)
   573  
   574  	s.setStarted(true)
   575  
   576  	return nil
   577  }
   578  
   579  func (s *rpcServer) Stop() error {
   580  	if !s.isStarted() {
   581  		return nil
   582  	}
   583  
   584  	ch := make(chan error)
   585  	s.exit <- ch
   586  
   587  	err := <-ch
   588  
   589  	s.setStarted(false)
   590  
   591  	return err
   592  }
   593  
   594  func (s *rpcServer) String() string {
   595  	return "mucp"
   596  }
   597  
   598  // newRegFuc will create a new registry function used to register the service.
   599  func (s *rpcServer) newRegFuc(config Options) func(service *registry.Service) error {
   600  	return func(service *registry.Service) error {
   601  		rOpts := []registry.RegisterOption{registry.RegisterTTL(config.RegisterTTL)}
   602  
   603  		var regErr error
   604  
   605  		// Attempt to register. If registration fails, back off and try again.
   606  		// TODO: see if we can improve the retry mechanism. Maybe retry lib, maybe config values
   607  		for i := 0; i < 3; i++ {
   608  			if regErr = config.Registry.Register(service, rOpts...); regErr != nil {
   609  				time.Sleep(backoff.Do(i + 1))
   610  				continue
   611  			}
   612  			break
   613  		}
   614  
   615  		if regErr != nil {
   616  			return regErr
   617  		}
   618  
   619  		s.Lock()
   620  		defer s.Unlock()
   621  		// Router can exchange messages on broker
   622  		// Subscribe to the topic with its own name
   623  		if err := s.subscribeServer(config); err != nil {
   624  			return errors.Wrap(err, "failed to subscribe to service name topic")
   625  		}
   626  		// Subscribe for all of the subscribers
   627  		s.reSubscribe(config)
   628  
   629  		return nil
   630  	}
   631  }
   632  
   633  // getAddr will take the advertise or service address, and return it.
   634  func (s *rpcServer) getAddr(config Options) (string, bool, error) {
   635  	// Use advertise address if provided, else use service address
   636  	advt := config.Address
   637  	if len(config.Advertise) > 0 {
   638  		advt = config.Advertise
   639  	}
   640  
   641  	// Use explicit host and port if possible
   642  	host, port := advt, ""
   643  
   644  	if cnt := strings.Count(advt, ":"); cnt >= 1 {
   645  		// ipv6 address in format [host]:port or ipv4 host:port
   646  		h, p, err := net.SplitHostPort(advt)
   647  		if err != nil {
   648  			return "", false, err
   649  		}
   650  
   651  		host, port = h, p
   652  	}
   653  
   654  	validHost := net.ParseIP(host) != nil
   655  
   656  	addr, err := addr.Extract(host)
   657  	if err != nil {
   658  		return "", false, err
   659  	}
   660  
   661  	// mq-rpc(eg. nats) doesn't need the port. its addr is queue name.
   662  	if port != "" {
   663  		addr = mnet.HostPort(addr, port)
   664  	}
   665  
   666  	return addr, validHost, nil
   667  }
   668  
   669  // newNodeMetedata creates a new metadata map with default values.
   670  func (s *rpcServer) newNodeMetedata(config Options) metadata.Metadata {
   671  	md := metadata.Copy(config.Metadata)
   672  
   673  	// TODO: revisit this for v5
   674  	md["transport"] = config.Transport.String()
   675  	md["broker"] = config.Broker.String()
   676  	md["server"] = s.String()
   677  	md["registry"] = config.Registry.String()
   678  	md["protocol"] = "mucp"
   679  
   680  	return md
   681  }
   682  
   683  // getEndpoints takes the list of handlers and subscribers and adds them to
   684  // a single endpoints list.
   685  func (s *rpcServer) getEndpoints() []*registry.Endpoint {
   686  	s.RLock()
   687  	defer s.RUnlock()
   688  
   689  	var handlerList []string
   690  
   691  	for n, e := range s.handlers {
   692  		// Only advertise non internal handlers
   693  		if !e.Options().Internal {
   694  			handlerList = append(handlerList, n)
   695  		}
   696  	}
   697  
   698  	// Maps are ordered randomly, sort the keys for consistency
   699  	// TODO: replace with generic version
   700  	sort.Strings(handlerList)
   701  
   702  	var subscriberList []Subscriber
   703  
   704  	for e := range s.subscribers {
   705  		// Only advertise non internal subscribers
   706  		if !e.Options().Internal {
   707  			subscriberList = append(subscriberList, e)
   708  		}
   709  	}
   710  
   711  	sort.Slice(subscriberList, func(i, j int) bool {
   712  		return subscriberList[i].Topic() > subscriberList[j].Topic()
   713  	})
   714  
   715  	endpoints := make([]*registry.Endpoint, 0, len(handlerList)+len(subscriberList))
   716  
   717  	for _, n := range handlerList {
   718  		endpoints = append(endpoints, s.handlers[n].Endpoints()...)
   719  	}
   720  
   721  	for _, e := range subscriberList {
   722  		endpoints = append(endpoints, e.Endpoints()...)
   723  	}
   724  
   725  	return endpoints
   726  }
   727  
   728  func (s *rpcServer) listen(listener transport.Listener, exit chan bool) {
   729  	for {
   730  		// Start listening for connections
   731  		// This will block until either exit signal given or error occurred
   732  		err := listener.Accept(s.ServeConn)
   733  
   734  		// TODO: listen for messages
   735  		// msg := broker.Exchange(service).Consume()
   736  
   737  		select {
   738  		// check if we're supposed to exit
   739  		case <-exit:
   740  			return
   741  		// check the error and backoff
   742  		default:
   743  			if err != nil {
   744  				s.opts.Logger.Logf(log.ErrorLevel, "Accept error: %v", err)
   745  				time.Sleep(time.Second)
   746  
   747  				continue
   748  			}
   749  		}
   750  
   751  		return
   752  	}
   753  }
   754  
   755  // registrar is responsible for keeping the service registered to the registry.
   756  func (s *rpcServer) registrar(listener transport.Listener, addr string, config Options, exit chan bool) {
   757  	logger := config.Logger
   758  
   759  	// Only process if it exists
   760  	ticker := new(time.Ticker)
   761  	if s.opts.RegisterInterval > time.Duration(0) {
   762  		ticker = time.NewTicker(s.opts.RegisterInterval)
   763  	}
   764  
   765  	// Return error chan
   766  	var ch chan error
   767  
   768  Loop:
   769  	for {
   770  		select {
   771  		// Register self on interval
   772  		case <-ticker.C:
   773  			registered := s.isRegistered()
   774  
   775  			rerr := s.opts.RegisterCheck(s.opts.Context)
   776  			if rerr != nil && registered {
   777  				logger.Logf(log.ErrorLevel,
   778  					"Server %s-%s register check error: %s, deregister it",
   779  					config.Name,
   780  					config.Id,
   781  					rerr)
   782  				// deregister self in case of error
   783  				if err := s.Deregister(); err != nil {
   784  					logger.Logf(log.ErrorLevel, "Server %s-%s deregister error: %s", config.Name, config.Id, err)
   785  				}
   786  			} else if rerr != nil && !registered {
   787  				logger.Logf(log.ErrorLevel, "Server %s-%s register check error: %s", config.Name, config.Id, rerr)
   788  				continue
   789  			}
   790  
   791  			if err := s.Register(); err != nil {
   792  				logger.Logf(log.ErrorLevel, "Server %s-%s register error: %s", config.Name, config.Id, err)
   793  			}
   794  
   795  		// Wait for exit signal
   796  		case ch = <-s.exit:
   797  			ticker.Stop()
   798  			close(exit)
   799  
   800  			break Loop
   801  		}
   802  	}
   803  
   804  	// Shutting down, deregister
   805  	if s.isRegistered() {
   806  		if err := s.Deregister(); err != nil {
   807  			logger.Logf(log.ErrorLevel, "Server %s-%s deregister error: %s", config.Name, config.Id, err)
   808  		}
   809  	}
   810  
   811  	// Wait for requests to finish
   812  	if swg := s.getWg(); swg != nil {
   813  		swg.Wait()
   814  	}
   815  
   816  	// Close transport listener
   817  	ch <- listener.Close()
   818  
   819  	brokerName := config.Broker.String()
   820  	logger.Logf(log.InfoLevel, "Broker [%s] Disconnected from %s", brokerName, config.Broker.Address())
   821  
   822  	// Disconnect the broker
   823  	if err := config.Broker.Disconnect(); err != nil {
   824  		logger.Logf(log.ErrorLevel, "Broker [%s] Disconnect error: %v", brokerName, err)
   825  	}
   826  
   827  	// Swap back address
   828  	s.setOptsAddr(addr)
   829  }
   830  
   831  func (s *rpcServer) serveReq(ctx context.Context,
   832  	msg transport.Message,
   833  	req *rpcRequest,
   834  	resp *rpcResponse,
   835  	rcodec codec.Codec) {
   836  	logger := s.opts.Logger
   837  	router := s.getRouter()
   838  
   839  	// serve the actual request using the request router
   840  	if serveRequestError := router.ServeRequest(ctx, req, resp); serveRequestError != nil {
   841  		// write an error response
   842  		writeError := rcodec.Write(&codec.Message{
   843  			Header: msg.Header,
   844  			Error:  serveRequestError.Error(),
   845  			Type:   codec.Error,
   846  		}, nil)
   847  
   848  		// if the server request is an EOS error we let the socket know
   849  		// sometimes the socket is already closed on the other side, so we can ignore that error
   850  		alreadyClosed := errors.Is(serveRequestError, errLastStreamResponse) && errors.Is(writeError, io.EOF)
   851  
   852  		// could not write error response
   853  		if writeError != nil && !alreadyClosed {
   854  			logger.Logf(log.DebugLevel, "rpc: unable to write error response: %v", writeError)
   855  		}
   856  	}
   857  }
   858  
   859  func (s *rpcServer) deferer(pool *socket.Pool, psock *socket.Socket, wg *waitGroup) {
   860  	pool.Release(psock)
   861  	wg.Done()
   862  
   863  	logger := s.opts.Logger
   864  	if r := recover(); r != nil {
   865  		logger.Log(log.ErrorLevel, "panic recovered: ", r)
   866  		logger.Log(log.ErrorLevel, string(debug.Stack()))
   867  	}
   868  }
   869  
   870  func (s *rpcServer) getRouter() Router {
   871  	router := Router(s.router)
   872  
   873  	// if not nil use the router specified
   874  	if s.opts.Router != nil {
   875  		// create a wrapped function
   876  		handler := func(ctx context.Context, req Request, rsp interface{}) error {
   877  			return s.opts.Router.ServeRequest(ctx, req, rsp.(Response))
   878  		}
   879  
   880  		// execute the wrapper for it
   881  		for i := len(s.opts.HdlrWrappers); i > 0; i-- {
   882  			handler = s.opts.HdlrWrappers[i-1](handler)
   883  		}
   884  
   885  		// set the router
   886  		router = rpcRouter{h: handler}
   887  	}
   888  
   889  	return router
   890  }