github.com/micro/go-micro/v2@v2.9.1/server/rpc_server.go (about) 1 package server 2 3 import ( 4 "context" 5 "fmt" 6 "io" 7 "net" 8 "runtime/debug" 9 "sort" 10 "strconv" 11 "strings" 12 "sync" 13 "time" 14 15 "github.com/micro/go-micro/v2/broker" 16 "github.com/micro/go-micro/v2/codec" 17 raw "github.com/micro/go-micro/v2/codec/bytes" 18 "github.com/micro/go-micro/v2/logger" 19 "github.com/micro/go-micro/v2/metadata" 20 "github.com/micro/go-micro/v2/registry" 21 "github.com/micro/go-micro/v2/transport" 22 "github.com/micro/go-micro/v2/util/addr" 23 "github.com/micro/go-micro/v2/util/backoff" 24 mnet "github.com/micro/go-micro/v2/util/net" 25 "github.com/micro/go-micro/v2/util/socket" 26 ) 27 28 type rpcServer struct { 29 router *router 30 exit chan chan error 31 32 sync.RWMutex 33 opts Options 34 handlers map[string]Handler 35 subscribers map[Subscriber][]broker.Subscriber 36 // marks the serve as started 37 started bool 38 // used for first registration 39 registered bool 40 // subscribe to service name 41 subscriber broker.Subscriber 42 // graceful exit 43 wg *sync.WaitGroup 44 45 rsvc *registry.Service 46 } 47 48 func newRpcServer(opts ...Option) Server { 49 options := newOptions(opts...) 50 router := newRpcRouter() 51 router.hdlrWrappers = options.HdlrWrappers 52 router.subWrappers = options.SubWrappers 53 54 return &rpcServer{ 55 opts: options, 56 router: router, 57 handlers: make(map[string]Handler), 58 subscribers: make(map[Subscriber][]broker.Subscriber), 59 exit: make(chan chan error), 60 wg: wait(options.Context), 61 } 62 } 63 64 // HandleEvent handles inbound messages to the service directly 65 // TODO: handle requests from an event. We won't send a response. 66 func (s *rpcServer) HandleEvent(e broker.Event) error { 67 // formatting horrible cruft 68 msg := e.Message() 69 70 if msg.Header == nil { 71 // create empty map in case of headers empty to avoid panic later 72 msg.Header = make(map[string]string) 73 } 74 75 // get codec 76 ct := msg.Header["Content-Type"] 77 78 // default content type 79 if len(ct) == 0 { 80 msg.Header["Content-Type"] = DefaultContentType 81 ct = DefaultContentType 82 } 83 84 // get codec 85 cf, err := s.newCodec(ct) 86 if err != nil { 87 return err 88 } 89 90 // copy headers 91 hdr := make(map[string]string, len(msg.Header)) 92 for k, v := range msg.Header { 93 hdr[k] = v 94 } 95 96 // create context 97 ctx := metadata.NewContext(context.Background(), hdr) 98 99 // TODO: inspect message header 100 // Micro-Service means a request 101 // Micro-Topic means a message 102 103 rpcMsg := &rpcMessage{ 104 topic: msg.Header["Micro-Topic"], 105 contentType: ct, 106 payload: &raw.Frame{Data: msg.Body}, 107 codec: cf, 108 header: msg.Header, 109 body: msg.Body, 110 } 111 112 // existing router 113 r := Router(s.router) 114 115 // if the router is present then execute it 116 if s.opts.Router != nil { 117 // create a wrapped function 118 handler := s.opts.Router.ProcessMessage 119 120 // execute the wrapper for it 121 for i := len(s.opts.SubWrappers); i > 0; i-- { 122 handler = s.opts.SubWrappers[i-1](handler) 123 } 124 125 // set the router 126 r = rpcRouter{m: handler} 127 } 128 129 return r.ProcessMessage(ctx, rpcMsg) 130 } 131 132 // ServeConn serves a single connection 133 func (s *rpcServer) ServeConn(sock transport.Socket) { 134 // global error tracking 135 var gerr error 136 // streams are multiplexed on Micro-Stream or Micro-Id header 137 pool := socket.NewPool() 138 139 // get global waitgroup 140 s.Lock() 141 gg := s.wg 142 s.Unlock() 143 144 // waitgroup to wait for processing to finish 145 wg := &waitGroup{ 146 gg: gg, 147 } 148 149 defer func() { 150 // only wait if there's no error 151 if gerr == nil { 152 // wait till done 153 wg.Wait() 154 } 155 156 // close all the sockets for this connection 157 pool.Close() 158 159 // close underlying socket 160 sock.Close() 161 162 // recover any panics 163 if r := recover(); r != nil { 164 if logger.V(logger.ErrorLevel, log) { 165 log.Error("panic recovered: ", r) 166 log.Error(string(debug.Stack())) 167 } 168 } 169 }() 170 171 for { 172 var msg transport.Message 173 // process inbound messages one at a time 174 if err := sock.Recv(&msg); err != nil { 175 // set a global error and return 176 // we're saying we essentially can't 177 // use the socket anymore 178 gerr = err 179 return 180 } 181 182 // check the message header for 183 // Micro-Service is a request 184 // Micro-Topic is a message 185 if t := msg.Header["Micro-Topic"]; len(t) > 0 { 186 // process the event 187 ev := newEvent(msg) 188 // TODO: handle the error event 189 if err := s.HandleEvent(ev); err != nil { 190 msg.Header["Micro-Error"] = err.Error() 191 } 192 // write back some 200 193 if err := sock.Send(&transport.Message{ 194 Header: msg.Header, 195 }); err != nil { 196 gerr = err 197 break 198 } 199 // we're done 200 continue 201 } 202 203 // business as usual 204 205 // use Micro-Stream as the stream identifier 206 // in the event its blank we'll always process 207 // on the same socket 208 id := msg.Header["Micro-Stream"] 209 210 // if there's no stream id then its a standard request 211 // use the Micro-Id 212 if len(id) == 0 { 213 id = msg.Header["Micro-Id"] 214 } 215 216 // check stream id 217 var stream bool 218 219 if v := getHeader("Micro-Stream", msg.Header); len(v) > 0 { 220 stream = true 221 } 222 223 // check if we have an existing socket 224 psock, ok := pool.Get(id) 225 226 // if we don't have a socket and its a stream 227 if !ok && stream { 228 // check if its a last stream EOS error 229 err := msg.Header["Micro-Error"] 230 if err == lastStreamResponseError.Error() { 231 pool.Release(psock) 232 continue 233 } 234 } 235 236 // got an existing socket already 237 if ok { 238 // we're starting processing 239 wg.Add(1) 240 241 // pass the message to that existing socket 242 if err := psock.Accept(&msg); err != nil { 243 // release the socket if there's an error 244 pool.Release(psock) 245 } 246 247 // done waiting 248 wg.Done() 249 250 // continue to the next message 251 continue 252 } 253 254 // no socket was found so its new 255 // set the local and remote values 256 psock.SetLocal(sock.Local()) 257 psock.SetRemote(sock.Remote()) 258 259 // load the socket with the current message 260 psock.Accept(&msg) 261 262 // now walk the usual path 263 264 // we use this Timeout header to set a server deadline 265 to := msg.Header["Timeout"] 266 // we use this Content-Type header to identify the codec needed 267 ct := msg.Header["Content-Type"] 268 269 // copy the message headers 270 hdr := make(map[string]string, len(msg.Header)) 271 for k, v := range msg.Header { 272 hdr[k] = v 273 } 274 275 // set local/remote ips 276 hdr["Local"] = sock.Local() 277 hdr["Remote"] = sock.Remote() 278 279 // create new context with the metadata 280 ctx := metadata.NewContext(context.Background(), hdr) 281 282 // set the timeout from the header if we have it 283 if len(to) > 0 { 284 if n, err := strconv.ParseUint(to, 10, 64); err == nil { 285 var cancel context.CancelFunc 286 ctx, cancel = context.WithTimeout(ctx, time.Duration(n)) 287 defer cancel() 288 } 289 } 290 291 // if there's no content type default it 292 if len(ct) == 0 { 293 msg.Header["Content-Type"] = DefaultContentType 294 ct = DefaultContentType 295 } 296 297 // setup old protocol 298 cf := setupProtocol(&msg) 299 300 // no legacy codec needed 301 if cf == nil { 302 var err error 303 // try get a new codec 304 if cf, err = s.newCodec(ct); err != nil { 305 // no codec found so send back an error 306 if err := sock.Send(&transport.Message{ 307 Header: map[string]string{ 308 "Content-Type": "text/plain", 309 }, 310 Body: []byte(err.Error()), 311 }); err != nil { 312 gerr = err 313 } 314 315 // release the socket we just created 316 pool.Release(psock) 317 // now continue 318 continue 319 } 320 } 321 322 // create a new rpc codec based on the pseudo socket and codec 323 rcodec := newRpcCodec(&msg, psock, cf) 324 // check the protocol as well 325 protocol := rcodec.String() 326 327 // internal request 328 request := &rpcRequest{ 329 service: getHeader("Micro-Service", msg.Header), 330 method: getHeader("Micro-Method", msg.Header), 331 endpoint: getHeader("Micro-Endpoint", msg.Header), 332 contentType: ct, 333 codec: rcodec, 334 header: msg.Header, 335 body: msg.Body, 336 socket: psock, 337 stream: stream, 338 } 339 340 // internal response 341 response := &rpcResponse{ 342 header: make(map[string]string), 343 socket: psock, 344 codec: rcodec, 345 } 346 347 // set router 348 r := Router(s.router) 349 350 // if not nil use the router specified 351 if s.opts.Router != nil { 352 // create a wrapped function 353 handler := func(ctx context.Context, req Request, rsp interface{}) error { 354 return s.opts.Router.ServeRequest(ctx, req, rsp.(Response)) 355 } 356 357 // execute the wrapper for it 358 for i := len(s.opts.HdlrWrappers); i > 0; i-- { 359 handler = s.opts.HdlrWrappers[i-1](handler) 360 } 361 362 // set the router 363 r = rpcRouter{h: handler} 364 } 365 366 // wait for two coroutines to exit 367 // serve the request and process the outbound messages 368 wg.Add(2) 369 370 // process the outbound messages from the socket 371 go func(id string, psock *socket.Socket) { 372 defer func() { 373 // TODO: don't hack this but if its grpc just break out of the stream 374 // We do this because the underlying connection is h2 and its a stream 375 switch protocol { 376 case "grpc": 377 sock.Close() 378 } 379 // release the socket 380 pool.Release(psock) 381 // signal we're done 382 wg.Done() 383 384 // recover any panics for outbound process 385 if r := recover(); r != nil { 386 if logger.V(logger.ErrorLevel, log) { 387 log.Error("panic recovered: ", r) 388 log.Error(string(debug.Stack())) 389 } 390 } 391 }() 392 393 for { 394 // get the message from our internal handler/stream 395 m := new(transport.Message) 396 if err := psock.Process(m); err != nil { 397 return 398 } 399 400 // send the message back over the socket 401 if err := sock.Send(m); err != nil { 402 return 403 } 404 } 405 }(id, psock) 406 407 // serve the request in a go routine as this may be a stream 408 go func(id string, psock *socket.Socket) { 409 defer func() { 410 // release the socket 411 pool.Release(psock) 412 // signal we're done 413 wg.Done() 414 415 // recover any panics for call handler 416 if r := recover(); r != nil { 417 log.Error("panic recovered: ", r) 418 log.Error(string(debug.Stack())) 419 } 420 }() 421 422 // serve the actual request using the request router 423 if serveRequestError := r.ServeRequest(ctx, request, response); serveRequestError != nil { 424 // write an error response 425 writeError := rcodec.Write(&codec.Message{ 426 Header: msg.Header, 427 Error: serveRequestError.Error(), 428 Type: codec.Error, 429 }, nil) 430 431 // if the server request is an EOS error we let the socket know 432 // sometimes the socket is already closed on the other side, so we can ignore that error 433 alreadyClosed := serveRequestError == lastStreamResponseError && writeError == io.EOF 434 435 // could not write error response 436 if writeError != nil && !alreadyClosed { 437 log.Debugf("rpc: unable to write error response: %v", writeError) 438 } 439 } 440 }(id, psock) 441 } 442 } 443 444 func (s *rpcServer) newCodec(contentType string) (codec.NewCodec, error) { 445 if cf, ok := s.opts.Codecs[contentType]; ok { 446 return cf, nil 447 } 448 if cf, ok := DefaultCodecs[contentType]; ok { 449 return cf, nil 450 } 451 return nil, fmt.Errorf("Unsupported Content-Type: %s", contentType) 452 } 453 454 func (s *rpcServer) Options() Options { 455 s.RLock() 456 opts := s.opts 457 s.RUnlock() 458 return opts 459 } 460 461 func (s *rpcServer) Init(opts ...Option) error { 462 s.Lock() 463 defer s.Unlock() 464 465 for _, opt := range opts { 466 opt(&s.opts) 467 } 468 // update router if its the default 469 if s.opts.Router == nil { 470 r := newRpcRouter() 471 r.hdlrWrappers = s.opts.HdlrWrappers 472 r.serviceMap = s.router.serviceMap 473 r.subWrappers = s.opts.SubWrappers 474 s.router = r 475 } 476 477 s.rsvc = nil 478 479 return nil 480 } 481 482 func (s *rpcServer) NewHandler(h interface{}, opts ...HandlerOption) Handler { 483 return s.router.NewHandler(h, opts...) 484 } 485 486 func (s *rpcServer) Handle(h Handler) error { 487 s.Lock() 488 defer s.Unlock() 489 490 if err := s.router.Handle(h); err != nil { 491 return err 492 } 493 494 s.handlers[h.Name()] = h 495 496 return nil 497 } 498 499 func (s *rpcServer) NewSubscriber(topic string, sb interface{}, opts ...SubscriberOption) Subscriber { 500 return s.router.NewSubscriber(topic, sb, opts...) 501 } 502 503 func (s *rpcServer) Subscribe(sb Subscriber) error { 504 s.Lock() 505 defer s.Unlock() 506 507 if err := s.router.Subscribe(sb); err != nil { 508 return err 509 } 510 511 s.subscribers[sb] = nil 512 return nil 513 } 514 515 func (s *rpcServer) Register() error { 516 s.RLock() 517 rsvc := s.rsvc 518 config := s.Options() 519 s.RUnlock() 520 521 regFunc := func(service *registry.Service) error { 522 // create registry options 523 rOpts := []registry.RegisterOption{registry.RegisterTTL(config.RegisterTTL)} 524 525 var regErr error 526 527 for i := 0; i < 3; i++ { 528 // attempt to register 529 if err := config.Registry.Register(service, rOpts...); err != nil { 530 // set the error 531 regErr = err 532 // backoff then retry 533 time.Sleep(backoff.Do(i + 1)) 534 continue 535 } 536 // success so nil error 537 regErr = nil 538 break 539 } 540 541 return regErr 542 } 543 544 // have we registered before? 545 if rsvc != nil { 546 if err := regFunc(rsvc); err != nil { 547 return err 548 } 549 return nil 550 } 551 552 var err error 553 var advt, host, port string 554 var cacheService bool 555 556 // check the advertise address first 557 // if it exists then use it, otherwise 558 // use the address 559 if len(config.Advertise) > 0 { 560 advt = config.Advertise 561 } else { 562 advt = config.Address 563 } 564 565 if cnt := strings.Count(advt, ":"); cnt >= 1 { 566 // ipv6 address in format [host]:port or ipv4 host:port 567 host, port, err = net.SplitHostPort(advt) 568 if err != nil { 569 return err 570 } 571 } else { 572 host = advt 573 } 574 575 if ip := net.ParseIP(host); ip != nil { 576 cacheService = true 577 } 578 579 addr, err := addr.Extract(host) 580 if err != nil { 581 return err 582 } 583 584 // make copy of metadata 585 md := metadata.Copy(config.Metadata) 586 587 // mq-rpc(eg. nats) doesn't need the port. its addr is queue name. 588 if port != "" { 589 addr = mnet.HostPort(addr, port) 590 } 591 592 // register service 593 node := ®istry.Node{ 594 Id: config.Name + "-" + config.Id, 595 Address: addr, 596 Metadata: md, 597 } 598 599 node.Metadata["transport"] = config.Transport.String() 600 node.Metadata["broker"] = config.Broker.String() 601 node.Metadata["server"] = s.String() 602 node.Metadata["registry"] = config.Registry.String() 603 node.Metadata["protocol"] = "mucp" 604 605 s.RLock() 606 607 // Maps are ordered randomly, sort the keys for consistency 608 var handlerList []string 609 for n, e := range s.handlers { 610 // Only advertise non internal handlers 611 if !e.Options().Internal { 612 handlerList = append(handlerList, n) 613 } 614 } 615 616 sort.Strings(handlerList) 617 618 var subscriberList []Subscriber 619 for e := range s.subscribers { 620 // Only advertise non internal subscribers 621 if !e.Options().Internal { 622 subscriberList = append(subscriberList, e) 623 } 624 } 625 626 sort.Slice(subscriberList, func(i, j int) bool { 627 return subscriberList[i].Topic() > subscriberList[j].Topic() 628 }) 629 630 endpoints := make([]*registry.Endpoint, 0, len(handlerList)+len(subscriberList)) 631 632 for _, n := range handlerList { 633 endpoints = append(endpoints, s.handlers[n].Endpoints()...) 634 } 635 636 for _, e := range subscriberList { 637 endpoints = append(endpoints, e.Endpoints()...) 638 } 639 640 service := ®istry.Service{ 641 Name: config.Name, 642 Version: config.Version, 643 Nodes: []*registry.Node{node}, 644 Endpoints: endpoints, 645 } 646 647 // get registered value 648 registered := s.registered 649 650 s.RUnlock() 651 652 if !registered { 653 if logger.V(logger.InfoLevel, logger.DefaultLogger) { 654 log.Infof("Registry [%s] Registering node: %s", config.Registry.String(), node.Id) 655 } 656 } 657 658 // register the service 659 if err := regFunc(service); err != nil { 660 return err 661 } 662 663 // already registered? don't need to register subscribers 664 if registered { 665 return nil 666 } 667 668 s.Lock() 669 defer s.Unlock() 670 671 // set what we're advertising 672 s.opts.Advertise = addr 673 674 // router can exchange messages 675 if s.opts.Router != nil { 676 // subscribe to the topic with own name 677 sub, err := s.opts.Broker.Subscribe(config.Name, s.HandleEvent) 678 if err != nil { 679 return err 680 } 681 682 // save the subscriber 683 s.subscriber = sub 684 } 685 686 // subscribe for all of the subscribers 687 for sb := range s.subscribers { 688 var opts []broker.SubscribeOption 689 if queue := sb.Options().Queue; len(queue) > 0 { 690 opts = append(opts, broker.Queue(queue)) 691 } 692 693 if cx := sb.Options().Context; cx != nil { 694 opts = append(opts, broker.SubscribeContext(cx)) 695 } 696 697 if !sb.Options().AutoAck { 698 opts = append(opts, broker.DisableAutoAck()) 699 } 700 701 sub, err := config.Broker.Subscribe(sb.Topic(), s.HandleEvent, opts...) 702 if err != nil { 703 return err 704 } 705 if logger.V(logger.InfoLevel, logger.DefaultLogger) { 706 log.Infof("Subscribing to topic: %s", sub.Topic()) 707 } 708 s.subscribers[sb] = []broker.Subscriber{sub} 709 } 710 if cacheService { 711 s.rsvc = service 712 } 713 s.registered = true 714 715 return nil 716 } 717 718 func (s *rpcServer) Deregister() error { 719 var err error 720 var advt, host, port string 721 722 s.RLock() 723 config := s.Options() 724 s.RUnlock() 725 726 // check the advertise address first 727 // if it exists then use it, otherwise 728 // use the address 729 if len(config.Advertise) > 0 { 730 advt = config.Advertise 731 } else { 732 advt = config.Address 733 } 734 735 if cnt := strings.Count(advt, ":"); cnt >= 1 { 736 // ipv6 address in format [host]:port or ipv4 host:port 737 host, port, err = net.SplitHostPort(advt) 738 if err != nil { 739 return err 740 } 741 } else { 742 host = advt 743 } 744 745 addr, err := addr.Extract(host) 746 if err != nil { 747 return err 748 } 749 750 // mq-rpc(eg. nats) doesn't need the port. its addr is queue name. 751 if port != "" { 752 addr = mnet.HostPort(addr, port) 753 } 754 755 node := ®istry.Node{ 756 Id: config.Name + "-" + config.Id, 757 Address: addr, 758 } 759 760 service := ®istry.Service{ 761 Name: config.Name, 762 Version: config.Version, 763 Nodes: []*registry.Node{node}, 764 } 765 766 if logger.V(logger.InfoLevel, logger.DefaultLogger) { 767 log.Infof("Registry [%s] Deregistering node: %s", config.Registry.String(), node.Id) 768 } 769 if err := config.Registry.Deregister(service); err != nil { 770 return err 771 } 772 773 s.Lock() 774 s.rsvc = nil 775 776 if !s.registered { 777 s.Unlock() 778 return nil 779 } 780 781 s.registered = false 782 783 // close the subscriber 784 if s.subscriber != nil { 785 s.subscriber.Unsubscribe() 786 s.subscriber = nil 787 } 788 789 for sb, subs := range s.subscribers { 790 for _, sub := range subs { 791 if logger.V(logger.InfoLevel, logger.DefaultLogger) { 792 log.Infof("Unsubscribing %s from topic: %s", node.Id, sub.Topic()) 793 } 794 sub.Unsubscribe() 795 } 796 s.subscribers[sb] = nil 797 } 798 799 s.Unlock() 800 return nil 801 } 802 803 func (s *rpcServer) Start() error { 804 s.RLock() 805 if s.started { 806 s.RUnlock() 807 return nil 808 } 809 s.RUnlock() 810 811 config := s.Options() 812 813 // start listening on the transport 814 ts, err := config.Transport.Listen(config.Address) 815 if err != nil { 816 return err 817 } 818 819 if logger.V(logger.InfoLevel, logger.DefaultLogger) { 820 log.Infof("Transport [%s] Listening on %s", config.Transport.String(), ts.Addr()) 821 } 822 823 // swap address 824 s.Lock() 825 addr := s.opts.Address 826 s.opts.Address = ts.Addr() 827 s.Unlock() 828 829 bname := config.Broker.String() 830 831 // connect to the broker 832 if err := config.Broker.Connect(); err != nil { 833 if logger.V(logger.ErrorLevel, logger.DefaultLogger) { 834 log.Errorf("Broker [%s] connect error: %v", bname, err) 835 } 836 return err 837 } 838 839 if logger.V(logger.InfoLevel, logger.DefaultLogger) { 840 log.Infof("Broker [%s] Connected to %s", bname, config.Broker.Address()) 841 } 842 843 // use RegisterCheck func before register 844 if err = s.opts.RegisterCheck(s.opts.Context); err != nil { 845 if logger.V(logger.ErrorLevel, logger.DefaultLogger) { 846 log.Errorf("Server %s-%s register check error: %s", config.Name, config.Id, err) 847 } 848 } else { 849 // announce self to the world 850 if err = s.Register(); err != nil { 851 if logger.V(logger.ErrorLevel, logger.DefaultLogger) { 852 log.Errorf("Server %s-%s register error: %s", config.Name, config.Id, err) 853 } 854 } 855 } 856 857 exit := make(chan bool) 858 859 go func() { 860 for { 861 // listen for connections 862 err := ts.Accept(s.ServeConn) 863 864 // TODO: listen for messages 865 // msg := broker.Exchange(service).Consume() 866 867 select { 868 // check if we're supposed to exit 869 case <-exit: 870 return 871 // check the error and backoff 872 default: 873 if err != nil { 874 if logger.V(logger.ErrorLevel, logger.DefaultLogger) { 875 log.Errorf("Accept error: %v", err) 876 } 877 time.Sleep(time.Second) 878 continue 879 } 880 } 881 882 // no error just exit 883 return 884 } 885 }() 886 887 go func() { 888 t := new(time.Ticker) 889 890 // only process if it exists 891 if s.opts.RegisterInterval > time.Duration(0) { 892 // new ticker 893 t = time.NewTicker(s.opts.RegisterInterval) 894 } 895 896 // return error chan 897 var ch chan error 898 899 Loop: 900 for { 901 select { 902 // register self on interval 903 case <-t.C: 904 s.RLock() 905 registered := s.registered 906 s.RUnlock() 907 rerr := s.opts.RegisterCheck(s.opts.Context) 908 if rerr != nil && registered { 909 if logger.V(logger.ErrorLevel, logger.DefaultLogger) { 910 log.Errorf("Server %s-%s register check error: %s, deregister it", config.Name, config.Id, err) 911 } 912 // deregister self in case of error 913 if err := s.Deregister(); err != nil { 914 if logger.V(logger.ErrorLevel, logger.DefaultLogger) { 915 log.Errorf("Server %s-%s deregister error: %s", config.Name, config.Id, err) 916 } 917 } 918 } else if rerr != nil && !registered { 919 if logger.V(logger.ErrorLevel, logger.DefaultLogger) { 920 log.Errorf("Server %s-%s register check error: %s", config.Name, config.Id, err) 921 } 922 continue 923 } 924 if err := s.Register(); err != nil { 925 if logger.V(logger.ErrorLevel, logger.DefaultLogger) { 926 log.Errorf("Server %s-%s register error: %s", config.Name, config.Id, err) 927 } 928 } 929 // wait for exit 930 case ch = <-s.exit: 931 t.Stop() 932 close(exit) 933 break Loop 934 } 935 } 936 937 s.RLock() 938 registered := s.registered 939 s.RUnlock() 940 if registered { 941 // deregister self 942 if err := s.Deregister(); err != nil { 943 if logger.V(logger.ErrorLevel, logger.DefaultLogger) { 944 log.Errorf("Server %s-%s deregister error: %s", config.Name, config.Id, err) 945 } 946 } 947 } 948 949 s.Lock() 950 swg := s.wg 951 s.Unlock() 952 953 // wait for requests to finish 954 if swg != nil { 955 swg.Wait() 956 } 957 958 // close transport listener 959 ch <- ts.Close() 960 961 if logger.V(logger.InfoLevel, logger.DefaultLogger) { 962 log.Infof("Broker [%s] Disconnected from %s", bname, config.Broker.Address()) 963 } 964 // disconnect the broker 965 if err := config.Broker.Disconnect(); err != nil { 966 if logger.V(logger.ErrorLevel, logger.DefaultLogger) { 967 log.Errorf("Broker [%s] Disconnect error: %v", bname, err) 968 } 969 } 970 971 // swap back address 972 s.Lock() 973 s.opts.Address = addr 974 s.Unlock() 975 }() 976 977 // mark the server as started 978 s.Lock() 979 s.started = true 980 s.Unlock() 981 982 return nil 983 } 984 985 func (s *rpcServer) Stop() error { 986 s.RLock() 987 if !s.started { 988 s.RUnlock() 989 return nil 990 } 991 s.RUnlock() 992 993 ch := make(chan error) 994 s.exit <- ch 995 996 err := <-ch 997 s.Lock() 998 s.started = false 999 s.Unlock() 1000 1001 return err 1002 } 1003 1004 func (s *rpcServer) String() string { 1005 return "mucp" 1006 }