github.com/volts-dev/volts@v0.0.0-20240120094013-5e9c65924106/server/server.go (about)

     1  package server
     2  
     3  import (
     4  	"net"
     5  	"strings"
     6  	"sync"
     7  	"sync/atomic"
     8  	"time"
     9  
    10  	"github.com/volts-dev/volts/broker"
    11  	_ "github.com/volts-dev/volts/broker/http"
    12  	_ "github.com/volts-dev/volts/broker/memory"
    13  	"github.com/volts-dev/volts/config"
    14  	"github.com/volts-dev/volts/internal/addr"
    15  	"github.com/volts-dev/volts/internal/backoff"
    16  	"github.com/volts-dev/volts/internal/metadata"
    17  	vnet "github.com/volts-dev/volts/internal/net"
    18  	"github.com/volts-dev/volts/logger"
    19  	"github.com/volts-dev/volts/registry"
    20  	_ "github.com/volts-dev/volts/registry/mdns"
    21  	_ "github.com/volts-dev/volts/registry/memory"
    22  	"github.com/volts-dev/volts/router"
    23  )
    24  
    25  var defaultServer *TServer
    26  var log = logger.New("Server")
    27  
    28  type (
    29  	// Server is a simple volts server abstraction
    30  	IServer interface {
    31  		//Init(...Option) error // Initialise options
    32  		Config() *Config // Retrieve the options
    33  
    34  		Name() string
    35  		// Register a handler
    36  		//Handle(Handler) error
    37  		// Create a new handler
    38  		//NewHandler(interface{}, ...HandlerOption) Handler
    39  
    40  		Start() error // Start the server
    41  		Stop() error  // Stop the server
    42  		Started() bool
    43  		String() string // Server implementation
    44  	}
    45  
    46  	TServer struct {
    47  		//*router
    48  		sync.RWMutex
    49  		config      *Config
    50  		httpRspPool sync.Pool
    51  
    52  		// server status
    53  		started     atomic.Value // marks the serve as started
    54  		registered  bool         // used for first registration
    55  		exit        chan chan error
    56  		wg          *sync.WaitGroup // graceful exit
    57  		services    []*registry.Service
    58  		subscribers map[router.ISubscriber][]broker.ISubscriber
    59  	}
    60  )
    61  
    62  // new a server for the service node
    63  func New(opts ...Option) *TServer {
    64  	srv := &TServer{
    65  		config:     newConfig(opts...),
    66  		registered: false,
    67  		exit:       make(chan chan error),
    68  		wg:         &sync.WaitGroup{},
    69  	}
    70  	srv.started.Store(false)
    71  	return srv
    72  }
    73  
    74  // 默认server实例
    75  // NOTE 引入server时defaultServer必须是nil,防止某些场景不需要server实例
    76  func Default(opts ...Option) *TServer {
    77  	if defaultServer == nil {
    78  		defaultServer = New(opts...)
    79  	} else {
    80  		defaultServer.Config().Init(opts...)
    81  	}
    82  
    83  	return defaultServer
    84  }
    85  
    86  func (s *TServer) HandleEvent(e broker.IEvent) error {
    87  	return nil
    88  }
    89  
    90  // 注册到服务发现
    91  func (self *TServer) Register() error {
    92  	regSrv := self.services
    93  	config := self.config
    94  
    95  	regFunc := func(service *registry.Service) error {
    96  		// create registry options
    97  		regOpts := []registry.Option{registry.RegisterTTL(config.RegisterTTL)}
    98  
    99  		var regErr error
   100  
   101  		for i := 0; i < 3; i++ {
   102  			// attempt to register
   103  			if err := config.Registry.Register(service, regOpts...); err != nil {
   104  				// set the error
   105  				regErr = err
   106  				// backoff then retry
   107  				time.Sleep(backoff.Do(i + 1))
   108  				continue
   109  			}
   110  			// success so nil error
   111  			regErr = nil
   112  			break
   113  		}
   114  
   115  		return regErr
   116  	}
   117  
   118  	// have we registered before?
   119  	if len(regSrv) > 0 {
   120  		for _, srv := range regSrv {
   121  			if err := regFunc(srv); err != nil {
   122  				return err
   123  			}
   124  		}
   125  
   126  		return nil
   127  	}
   128  
   129  	var err error
   130  	var advt, host, port string
   131  	var cacheService bool
   132  
   133  	// check the advertise address first
   134  	// if it exists then use it, otherwise
   135  	// use the address
   136  	if len(config.Advertise) > 0 {
   137  		advt = config.Advertise
   138  	} else {
   139  		advt = config.Address
   140  	}
   141  
   142  	if cnt := strings.Count(advt, ":"); cnt >= 1 {
   143  		// ipv6 address in format [host]:port or ipv4 host:port
   144  		host, port, err = net.SplitHostPort(advt)
   145  		if err != nil {
   146  			return err
   147  		}
   148  	} else {
   149  		host = advt
   150  	}
   151  
   152  	if ip := net.ParseIP(host); ip != nil {
   153  		cacheService = true
   154  	}
   155  
   156  	addr, err := addr.Extract(host)
   157  	if err != nil {
   158  		return err
   159  	}
   160  
   161  	// make copy of metadata
   162  	md := metadata.Copy(config.Metadata)
   163  
   164  	// mq-rpc(eg. nats) doesn't need the port. its addr is queue name.
   165  	if port != "" {
   166  		addr = vnet.HostPort(addr, port)
   167  	}
   168  
   169  	// register service node
   170  	node := &registry.Node{
   171  		Id:       config.Name + "-" + config.Uid,
   172  		Address:  addr,
   173  		Metadata: md,
   174  	}
   175  
   176  	node.Metadata["transport"] = config.Transport.String()
   177  	node.Metadata["broker"] = config.Broker.String()
   178  	node.Metadata["server"] = self.String()
   179  	node.Metadata["registry"] = config.Registry.String()
   180  	node.Metadata["protocol"] = config.Transport.Protocol()
   181  	/*
   182  		// 注册订阅列表
   183  		var subscriberList []ISubscriber
   184  
   185  		for e := range self.subscribers {
   186  			// Only advertise non internal subscribers
   187  			if !e.Config().Internal {
   188  				subscriberList = append(subscriberList, e)
   189  			}
   190  		}
   191  		sort.Slice(subscriberList, func(i, j int) bool {
   192  			return subscriberList[i].Topic() > subscriberList[j].Topic()
   193  		})
   194  	*/
   195  	var servics []*registry.Service
   196  	for grp, endpoints := range config.Router.Endpoints() {
   197  		if len(endpoints) == 0 {
   198  			continue
   199  		}
   200  
   201  		name := grp.Name()
   202  		if name == "" {
   203  			name = config.Name // default registry service of this server
   204  		}
   205  		/*
   206  			for _, e := range subscriberList {
   207  				endpoints = append(endpoints, e.Endpoints()...)
   208  			}
   209  		*/
   210  		// default registry service of this server
   211  		service := &registry.Service{
   212  			Name:      name,
   213  			Version:   config.Version,
   214  			Metadata:  grp.Metadata,
   215  			Nodes:     []*registry.Node{node},
   216  			Endpoints: endpoints,
   217  		}
   218  
   219  		// register the service
   220  		if err := regFunc(service); err != nil {
   221  			return err
   222  		}
   223  
   224  		servics = append(servics, service)
   225  	}
   226  
   227  	// get registered value
   228  	registered := self.registered
   229  
   230  	if !registered {
   231  		log.Infof("Registry [%s] Registering node: %s", config.Registry.String(), node.Id)
   232  	}
   233  
   234  	// already registered? don't need to register subscribers
   235  	if registered {
   236  		return nil
   237  	}
   238  
   239  	// set what we're advertising
   240  	self.config.Advertise = addr
   241  
   242  	if cacheService {
   243  		self.services = servics
   244  	}
   245  	self.registered = true
   246  
   247  	// 注册订阅
   248  	// Router can exchange messages on broker
   249  	// Subscribe to the topic with its own name
   250  	if self.config.Router != nil {
   251  		sub, err := self.config.Broker.Subscribe(config.Name, self.HandleEvent)
   252  		if err != nil {
   253  			return err
   254  			//		return errors.Wrap(err, "failed to subscribe to service name topic")
   255  		}
   256  
   257  		// Save the subscriber
   258  		self.config.Subscriber = sub
   259  	}
   260  
   261  	// Subscribe for all of the subscribers
   262  	for sb := range self.subscribers {
   263  		var opts []broker.SubscribeOption
   264  		if queue := sb.Config().Queue; len(queue) > 0 {
   265  			opts = append(opts, broker.Queue(queue))
   266  		}
   267  
   268  		if ctx := sb.Config().Context; ctx != nil {
   269  			opts = append(opts, broker.SubscribeContext(ctx))
   270  		}
   271  
   272  		if !sb.Config().AutoAck {
   273  			opts = append(opts, broker.DisableAutoAck())
   274  		}
   275  
   276  		log.Infof("Subscribing to topic: %s", sb.Topic())
   277  		sub, err := self.config.Broker.Subscribe(sb.Topic(), self.HandleEvent, opts...)
   278  		if err != nil {
   279  			return err
   280  			//		return errors.Wrap(err, "failed to resubscribe")
   281  		}
   282  
   283  		self.subscribers[sb] = []broker.ISubscriber{sub}
   284  	}
   285  
   286  	return nil
   287  }
   288  
   289  func (self *TServer) Deregister() error {
   290  	var err error
   291  	var advt, host, port string
   292  
   293  	//self.RLock()
   294  	config := self.config
   295  	//self.RUnlock()
   296  
   297  	// check the advertise address first
   298  	// if it exists then use it, otherwise
   299  	// use the address
   300  	if len(config.Advertise) > 0 {
   301  		advt = config.Advertise
   302  	} else {
   303  		advt = config.Address
   304  	}
   305  
   306  	if cnt := strings.Count(advt, ":"); cnt >= 1 {
   307  		// ipv6 address in format [host]:port or ipv4 host:port
   308  		host, port, err = net.SplitHostPort(advt)
   309  		if err != nil {
   310  			return err
   311  		}
   312  	} else {
   313  		host = advt
   314  	}
   315  
   316  	addr, err := addr.Extract(host)
   317  	if err != nil {
   318  		return err
   319  	}
   320  
   321  	// mq-rpc(eg. nats) doesn't need the port. its addr is queue name.
   322  	if port != "" {
   323  		addr = vnet.HostPort(addr, port)
   324  	}
   325  
   326  	node := &registry.Node{
   327  		Id:      config.Name + "-" + config.Uid,
   328  		Address: addr,
   329  	}
   330  
   331  	service := &registry.Service{
   332  		Name:    config.Name,
   333  		Version: config.Version,
   334  		Nodes:   []*registry.Node{node},
   335  	}
   336  
   337  	log.Infof("Registry [%s] Deregistering node: %s", config.Registry.String(), node.Id)
   338  	if err := config.Registry.Deregister(service); err != nil {
   339  		return err
   340  	}
   341  
   342  	//self.Lock()
   343  	self.services = nil
   344  
   345  	if !self.registered {
   346  		return nil
   347  	}
   348  
   349  	self.registered = false
   350  
   351  	// 订阅事宜
   352  	// close the subscriber
   353  	if self.config.Subscriber != nil {
   354  		self.config.Subscriber.Unsubscribe()
   355  		self.config.Subscriber = nil
   356  	}
   357  
   358  	for sb, subs := range self.subscribers {
   359  		for _, sub := range subs {
   360  			log.Infof("Unsubscribing %s from topic: %s", node.Id, sub.Topic())
   361  			if err = sub.Unsubscribe(); err != nil {
   362  				log.Err(err)
   363  			}
   364  		}
   365  		self.subscribers[sb] = nil
   366  	}
   367  
   368  	return nil
   369  }
   370  
   371  func (self *TServer) Start() error {
   372  	if self.started.Load().(bool) {
   373  		return nil
   374  	}
   375  
   376  	cfg := self.config
   377  	//config.Register(cfg) // 注册服务器配置
   378  	config.Load() // 加载所有配置
   379  
   380  	// 打印
   381  	cfg.Router.PrintRoutes()
   382  
   383  	self.subscribers = self.config.Router.Config().Router.GetSubscribers()
   384  
   385  	// start listening on the transport
   386  	ts, err := cfg.Transport.Listen(cfg.Address)
   387  	if err != nil {
   388  		return err
   389  	}
   390  
   391  	// swap address
   392  	addr := cfg.Address
   393  	cfg.Address = ts.Addr().String()
   394  	bname := cfg.Broker.String()
   395  
   396  	// connect to the broker
   397  	if err := cfg.Broker.Start(); err != nil {
   398  		log.Errf("Broker [%s] connect error: %v", bname, err)
   399  		return err
   400  	}
   401  
   402  	// use RegisterCheck func before register
   403  	if err = self.config.RegisterCheck(self.config.Context); err != nil {
   404  		log.Errf("Server %s-%s register check error: %s", cfg.Name, cfg.Uid, err)
   405  	} else {
   406  		// announce self to the world
   407  		if err = self.Register(); err != nil {
   408  			log.Errf("Server %s-%s register error: %s", cfg.Name, cfg.Uid, err)
   409  		}
   410  	}
   411  
   412  	exit := make(chan bool)
   413  
   414  	// 监听链接
   415  	go func() {
   416  		for {
   417  			// listen for connections
   418  			err := ts.Serve(self.config.Router)
   419  
   420  			// TODO: listen for messages
   421  			// msg := broker.Exchange(service).Consume()
   422  
   423  			select {
   424  			// check if we're supposed to exit
   425  			case <-exit:
   426  				return
   427  			// check the error and backoff
   428  			default:
   429  				if err != nil {
   430  					log.Errf("Accept error: %v", err)
   431  					time.Sleep(time.Second)
   432  					continue
   433  				}
   434  			}
   435  
   436  			// no error just exit
   437  			return
   438  		}
   439  	}()
   440  	// mark the server as started
   441  	self.started.Store(true)
   442  
   443  	log.Infof("Listening on %s - %s", ts.Addr(), cfg.Transport.String())
   444  
   445  	// 监听退出
   446  	go func() {
   447  		t := new(time.Ticker)
   448  
   449  		// only process if it exists
   450  		if cfg.RegisterInterval > time.Duration(0) {
   451  			// new ticker
   452  			t = time.NewTicker(cfg.RegisterInterval)
   453  		}
   454  
   455  		// return error chan
   456  		var ch chan error
   457  
   458  	Loop:
   459  		for {
   460  			select {
   461  			// register self on interval
   462  			case <-t.C:
   463  				//self.RLock()
   464  				registered := self.registered
   465  				//self.RUnlock()
   466  				rerr := cfg.RegisterCheck(self.config.Context)
   467  				if rerr != nil {
   468  					if !registered {
   469  						log.Errf("Server %s-%s register check error: %s", cfg.Name, cfg.Uid, err)
   470  						continue
   471  					}
   472  
   473  					log.Errf("Server %s-%s register check error: %s, deregister it", cfg.Name, cfg.Uid, err)
   474  
   475  					// deregister self in case of error
   476  					if err := self.Deregister(); err != nil {
   477  						log.Errf("Server %s-%s deregister error: %s", cfg.Name, cfg.Uid, err)
   478  					}
   479  				}
   480  
   481  				if err := self.Register(); err != nil {
   482  					log.Errf("Server %s-%s register error: %s", cfg.Name, cfg.Uid, err)
   483  				}
   484  			// wait for exit
   485  			case ch = <-self.exit: // 监听来自self.Stop()信号
   486  				t.Stop()
   487  				close(exit)
   488  				break Loop
   489  			}
   490  		}
   491  
   492  		//self.RLock()
   493  		registered := self.registered
   494  		//self.RUnlock()
   495  		if registered {
   496  			// deregister self
   497  			if err := self.Deregister(); err != nil {
   498  				log.Errf("Server %s-%s deregister error: %s", cfg.Name, cfg.Uid, err)
   499  			}
   500  		}
   501  
   502  		//self.Lock()
   503  		swg := self.wg
   504  		//self.Unlock()
   505  
   506  		// wait for requests to finish
   507  		if swg != nil {
   508  			swg.Wait()
   509  		}
   510  
   511  		// close transport listener
   512  		ch <- ts.Close()
   513  
   514  		// disconnect the broker
   515  		log.Infof("Broker [%s] Disconnected from %s", bname, cfg.Broker.Address())
   516  		if err := cfg.Broker.Close(); err != nil {
   517  			log.Errf("Broker [%s] Disconnect error: %v", bname, err)
   518  		}
   519  
   520  		// swap back address
   521  		//self.Lock()
   522  		cfg.Address = addr
   523  		//self.Unlock()
   524  	}()
   525  
   526  	return nil
   527  }
   528  
   529  func (self *TServer) Started() bool {
   530  	return self.started.Load().(bool)
   531  }
   532  
   533  func (self *TServer) Stop() error {
   534  	if !self.started.Load().(bool) {
   535  		return nil
   536  	}
   537  
   538  	ch := make(chan error)
   539  	self.exit <- ch
   540  
   541  	err := <-ch
   542  	self.started.Store(false)
   543  	return err
   544  }
   545  
   546  func (self *TServer) Name() string {
   547  	return self.config.Name
   548  }
   549  
   550  func (self *TServer) String() string {
   551  	return self.config.Router.String() + self.config.Transport.String() + "+" + " Server"
   552  }
   553  
   554  func (self *TServer) Config() *Config {
   555  	//self.RLock()
   556  	cfg := self.config
   557  	//self.RUnlock()
   558  	return cfg
   559  }