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