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 := ®istry.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 := ®istry.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 := ®istry.Node{ 327 Id: config.Name + "-" + config.Uid, 328 Address: addr, 329 } 330 331 service := ®istry.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 }