go-micro.dev/v5@v5.12.0/server/grpc/grpc.go (about) 1 // Package grpc provides a grpc server 2 package grpc 3 4 import ( 5 "context" 6 "crypto/tls" 7 "fmt" 8 "net" 9 "reflect" 10 "runtime/debug" 11 "sort" 12 "strconv" 13 "strings" 14 "sync" 15 "time" 16 17 "github.com/golang/protobuf/proto" 18 "go-micro.dev/v5/broker" 19 "go-micro.dev/v5/cmd" 20 "go-micro.dev/v5/errors" 21 "go-micro.dev/v5/logger" 22 meta "go-micro.dev/v5/metadata" 23 "go-micro.dev/v5/registry" 24 "go-micro.dev/v5/server" 25 "go-micro.dev/v5/util/addr" 26 "go-micro.dev/v5/util/backoff" 27 mgrpc "go-micro.dev/v5/util/grpc" 28 mnet "go-micro.dev/v5/util/net" 29 "golang.org/x/net/netutil" 30 31 "google.golang.org/grpc" 32 "google.golang.org/grpc/codes" 33 "google.golang.org/grpc/credentials" 34 "google.golang.org/grpc/encoding" 35 "google.golang.org/grpc/metadata" 36 "google.golang.org/grpc/peer" 37 "google.golang.org/grpc/status" 38 ) 39 40 func init() { 41 cmd.DefaultServers["grpc"] = NewServer 42 } 43 44 var ( 45 // DefaultMaxMsgSize define maximum message size that server can send 46 // or receive. Default value is 4MB. 47 DefaultMaxMsgSize = 1024 * 1024 * 4 48 ) 49 50 const ( 51 defaultContentType = "application/grpc" 52 ) 53 54 type grpcServer struct { 55 rpc *rServer 56 srv *grpc.Server 57 exit chan chan error 58 wg *sync.WaitGroup 59 60 sync.RWMutex 61 opts server.Options 62 handlers map[string]server.Handler 63 subscribers map[*subscriber][]broker.Subscriber 64 // marks the serve as started 65 started bool 66 // used for first registration 67 registered bool 68 69 // registry service instance 70 rsvc *registry.Service 71 } 72 73 func init() { 74 encoding.RegisterCodec(wrapCodec{jsonCodec{}}) 75 encoding.RegisterCodec(wrapCodec{protoCodec{}}) 76 encoding.RegisterCodec(wrapCodec{bytesCodec{}}) 77 } 78 79 func newGRPCServer(opts ...server.Option) server.Server { 80 options := newOptions(opts...) 81 82 // create a grpc server 83 srv := &grpcServer{ 84 opts: options, 85 rpc: &rServer{ 86 serviceMap: make(map[string]*service), 87 logger: options.Logger, 88 }, 89 handlers: make(map[string]server.Handler), 90 subscribers: make(map[*subscriber][]broker.Subscriber), 91 exit: make(chan chan error), 92 wg: wait(options.Context), 93 } 94 95 // configure the grpc server 96 srv.configure() 97 98 return srv 99 } 100 101 type grpcRouter struct { 102 h func(context.Context, server.Request, interface{}) error 103 m func(context.Context, server.Message) error 104 } 105 106 func (r grpcRouter) ProcessMessage(ctx context.Context, msg server.Message) error { 107 return r.m(ctx, msg) 108 } 109 110 func (r grpcRouter) ServeRequest(ctx context.Context, req server.Request, rsp server.Response) error { 111 return r.h(ctx, req, rsp) 112 } 113 114 func (g *grpcServer) configure(opts ...server.Option) { 115 g.Lock() 116 defer g.Unlock() 117 118 // Don't reprocess where there's no config 119 if len(opts) == 0 && g.srv != nil { 120 return 121 } 122 123 // Optionally use injected grpc.Server if there's a one 124 var srv *grpc.Server 125 if srv = g.getGrpcServer(); srv != nil { 126 g.srv = srv 127 } 128 129 for _, o := range opts { 130 o(&g.opts) 131 } 132 133 g.rsvc = nil 134 135 // NOTE: injected grpc.Server doesn't have g.handler registered 136 if srv != nil { 137 return 138 } 139 140 maxMsgSize := g.getMaxMsgSize() 141 142 gopts := []grpc.ServerOption{ 143 grpc.MaxRecvMsgSize(maxMsgSize), 144 grpc.MaxSendMsgSize(maxMsgSize), 145 grpc.UnknownServiceHandler(g.handler), 146 } 147 148 if creds := g.getCredentials(); creds != nil { 149 gopts = append(gopts, grpc.Creds(creds)) 150 } 151 152 if opts := g.getGrpcOptions(); opts != nil { 153 gopts = append(gopts, opts...) 154 } 155 156 g.srv = grpc.NewServer(gopts...) 157 } 158 159 func (g *grpcServer) getMaxMsgSize() int { 160 if g.opts.Context == nil { 161 return DefaultMaxMsgSize 162 } 163 s, ok := g.opts.Context.Value(maxMsgSizeKey{}).(int) 164 if !ok { 165 return DefaultMaxMsgSize 166 } 167 return s 168 } 169 170 func (g *grpcServer) getCredentials() credentials.TransportCredentials { 171 if g.opts.Context != nil { 172 if v, ok := g.opts.Context.Value(tlsAuth{}).(*tls.Config); ok && v != nil { 173 return credentials.NewTLS(v) 174 } 175 } 176 return nil 177 } 178 179 func (g *grpcServer) getGrpcOptions() []grpc.ServerOption { 180 if g.opts.Context == nil { 181 return nil 182 } 183 184 opts, ok := g.opts.Context.Value(grpcOptions{}).([]grpc.ServerOption) 185 if !ok || opts == nil { 186 return nil 187 } 188 189 return opts 190 } 191 192 func (g *grpcServer) getListener() net.Listener { 193 if g.opts.Context == nil { 194 return nil 195 } 196 197 if l, ok := g.opts.Context.Value(netListener{}).(net.Listener); ok && l != nil { 198 return l 199 } 200 201 return nil 202 } 203 204 func (g *grpcServer) getGrpcServer() *grpc.Server { 205 if g.opts.Context == nil { 206 return nil 207 } 208 209 if srv, ok := g.opts.Context.Value(grpcServerKey{}).(*grpc.Server); ok && srv != nil { 210 return srv 211 } 212 213 return nil 214 } 215 216 func (g *grpcServer) handler(srv interface{}, stream grpc.ServerStream) error { 217 if g.wg != nil { 218 g.wg.Add(1) 219 defer g.wg.Done() 220 } 221 222 fullMethod, ok := grpc.MethodFromServerStream(stream) 223 if !ok { 224 return status.Errorf(codes.Internal, "method does not exist in context") 225 } 226 227 serviceName, methodName, err := mgrpc.ServiceMethod(fullMethod) 228 if err != nil { 229 return status.New(codes.InvalidArgument, err.Error()).Err() 230 } 231 232 // get grpc metadata 233 gmd, ok := metadata.FromIncomingContext(stream.Context()) 234 if !ok { 235 gmd = metadata.MD{} 236 } 237 238 // copy the metadata to go-micro.metadata 239 md := meta.Metadata{} 240 for k, v := range gmd { 241 md[k] = strings.Join(v, ", ") 242 } 243 244 // timeout for server deadline 245 to := md["timeout"] 246 247 // get content type 248 ct := defaultContentType 249 250 if ctype, ok := md["x-content-type"]; ok { 251 ct = ctype 252 } 253 if ctype, ok := md["content-type"]; ok { 254 ct = ctype 255 } 256 257 delete(md, "x-content-type") 258 delete(md, "timeout") 259 260 // create new context 261 ctx := meta.NewContext(stream.Context(), md) 262 263 // get peer from context 264 if p, ok := peer.FromContext(stream.Context()); ok { 265 md["Remote"] = p.Addr.String() 266 ctx = peer.NewContext(ctx, p) 267 } 268 269 // set the timeout if we have it 270 if len(to) > 0 { 271 if n, err := strconv.ParseUint(to, 10, 64); err == nil { 272 var cancel context.CancelFunc 273 ctx, cancel = context.WithTimeout(ctx, time.Duration(n)) 274 defer cancel() 275 } 276 } 277 278 // process via router 279 if g.opts.Router != nil { 280 cc, err := g.newGRPCCodec(ct) 281 if err != nil { 282 return errors.InternalServerError("go.micro.server", err.Error()) 283 } 284 codec := &grpcCodec{ 285 method: fmt.Sprintf("%s.%s", serviceName, methodName), 286 endpoint: fmt.Sprintf("%s.%s", serviceName, methodName), 287 target: g.opts.Name, 288 s: stream, 289 c: cc, 290 } 291 292 // create a client.Request 293 request := &rpcRequest{ 294 service: mgrpc.ServiceFromMethod(fullMethod), 295 contentType: ct, 296 method: fmt.Sprintf("%s.%s", serviceName, methodName), 297 codec: codec, 298 stream: true, 299 } 300 301 response := &rpcResponse{ 302 header: make(map[string]string), 303 codec: codec, 304 } 305 306 // create a wrapped function 307 handler := func(ctx context.Context, req server.Request, rsp interface{}) error { 308 return g.opts.Router.ServeRequest(ctx, req, rsp.(server.Response)) 309 } 310 311 // execute the wrapper for it 312 for i := len(g.opts.HdlrWrappers); i > 0; i-- { 313 handler = g.opts.HdlrWrappers[i-1](handler) 314 } 315 316 r := grpcRouter{h: handler} 317 318 // serve the actual request using the request router 319 if err := r.ServeRequest(ctx, request, response); err != nil { 320 if _, ok := status.FromError(err); ok { 321 return err 322 } 323 return status.Errorf(codes.Internal, "%v", err.Error()) 324 } 325 326 return nil 327 } 328 329 // process the standard request flow 330 g.rpc.mu.Lock() 331 service := g.rpc.serviceMap[serviceName] 332 g.rpc.mu.Unlock() 333 334 if service == nil { 335 return status.New(codes.Unimplemented, fmt.Sprintf("unknown service %s", serviceName)).Err() 336 } 337 338 mtype := service.method[methodName] 339 if mtype == nil { 340 return status.New(codes.Unimplemented, fmt.Sprintf("unknown service %s.%s", serviceName, methodName)).Err() 341 } 342 343 // process unary 344 if !mtype.stream { 345 return g.processRequest(stream, service, mtype, ct, ctx) 346 } 347 348 // process stream 349 return g.processStream(stream, service, mtype, ct, ctx) 350 } 351 352 func (g *grpcServer) processRequest(stream grpc.ServerStream, service *service, mtype *methodType, ct string, ctx context.Context) error { 353 for { 354 var argv, replyv reflect.Value 355 356 // Decode the argument value. 357 argIsValue := false // if true, need to indirect before calling. 358 if mtype.ArgType.Kind() == reflect.Ptr { 359 argv = reflect.New(mtype.ArgType.Elem()) 360 } else { 361 argv = reflect.New(mtype.ArgType) 362 argIsValue = true 363 } 364 365 // Unmarshal request 366 if err := stream.RecvMsg(argv.Interface()); err != nil { 367 return err 368 } 369 370 if argIsValue { 371 argv = argv.Elem() 372 } 373 374 // reply value 375 replyv = reflect.New(mtype.ReplyType.Elem()) 376 377 function := mtype.method.Func 378 var returnValues []reflect.Value 379 380 cc, err := g.newGRPCCodec(ct) 381 if err != nil { 382 return errors.InternalServerError("go.micro.server", err.Error()) 383 } 384 b, err := cc.Marshal(argv.Interface()) 385 if err != nil { 386 return err 387 } 388 389 // create a client.Request 390 r := &rpcRequest{ 391 service: g.opts.Name, 392 contentType: ct, 393 method: fmt.Sprintf("%s.%s", service.name, mtype.method.Name), 394 body: b, 395 payload: argv.Interface(), 396 } 397 398 // define the handler func 399 fn := func(ctx context.Context, req server.Request, rsp interface{}) (err error) { 400 defer func() { 401 if r := recover(); r != nil { 402 logger.Extract(ctx).Errorf("panic recovered: %v, stack: %s", r, string(debug.Stack())) 403 err = errors.InternalServerError("go.micro.server", "panic recovered: %v", r) 404 } 405 }() 406 returnValues = function.Call([]reflect.Value{service.rcvr, mtype.prepareContext(ctx), reflect.ValueOf(argv.Interface()), reflect.ValueOf(rsp)}) 407 408 // The return value for the method is an error. 409 if rerr := returnValues[0].Interface(); rerr != nil { 410 err = rerr.(error) 411 } 412 413 return err 414 } 415 416 // wrap the handler func 417 for i := len(g.opts.HdlrWrappers); i > 0; i-- { 418 fn = g.opts.HdlrWrappers[i-1](fn) 419 } 420 statusCode := codes.OK 421 statusDesc := "" 422 // execute the handler 423 if appErr := fn(ctx, r, replyv.Interface()); appErr != nil { 424 var errStatus *status.Status 425 switch verr := appErr.(type) { 426 case *errors.Error: 427 // micro.Error now proto based and we can attach it to grpc status 428 statusCode = microError(verr) 429 statusDesc = verr.Error() 430 verr.Detail = strings.ToValidUTF8(verr.Detail, "") 431 errStatus, err = status.New(statusCode, statusDesc).WithDetails(verr) 432 if err != nil { 433 return err 434 } 435 case proto.Message: 436 // user defined error that proto based we can attach it to grpc status 437 statusCode = convertCode(appErr) 438 statusDesc = appErr.Error() 439 errStatus, err = status.New(statusCode, statusDesc).WithDetails(verr) 440 if err != nil { 441 return err 442 } 443 default: 444 // default case user pass own error type that not proto based 445 statusCode = convertCode(verr) 446 statusDesc = verr.Error() 447 errStatus = status.New(statusCode, statusDesc) 448 } 449 450 return errStatus.Err() 451 } 452 453 if err := stream.SendMsg(replyv.Interface()); err != nil { 454 return err 455 } 456 return status.New(statusCode, statusDesc).Err() 457 } 458 } 459 460 func (g *grpcServer) processStream(stream grpc.ServerStream, service *service, mtype *methodType, ct string, ctx context.Context) error { 461 opts := g.opts 462 463 r := &rpcRequest{ 464 service: opts.Name, 465 contentType: ct, 466 method: fmt.Sprintf("%s.%s", service.name, mtype.method.Name), 467 stream: true, 468 } 469 470 ss := &rpcStream{ 471 request: r, 472 s: stream, 473 } 474 475 function := mtype.method.Func 476 var returnValues []reflect.Value 477 478 // Invoke the method, providing a new value for the reply. 479 fn := func(ctx context.Context, req server.Request, stream interface{}) error { 480 returnValues = function.Call([]reflect.Value{service.rcvr, mtype.prepareContext(ctx), reflect.ValueOf(stream)}) 481 if err := returnValues[0].Interface(); err != nil { 482 return err.(error) 483 } 484 485 return nil 486 } 487 488 for i := len(opts.HdlrWrappers); i > 0; i-- { 489 fn = opts.HdlrWrappers[i-1](fn) 490 } 491 492 statusCode := codes.OK 493 statusDesc := "" 494 495 if appErr := fn(ctx, r, ss); appErr != nil { 496 var err error 497 var errStatus *status.Status 498 switch verr := appErr.(type) { 499 case *errors.Error: 500 // micro.Error now proto based and we can attach it to grpc status 501 statusCode = microError(verr) 502 statusDesc = verr.Error() 503 verr.Detail = strings.ToValidUTF8(verr.Detail, "") 504 errStatus, err = status.New(statusCode, statusDesc).WithDetails(verr) 505 if err != nil { 506 return err 507 } 508 case proto.Message: 509 // user defined error that proto based we can attach it to grpc status 510 statusCode = convertCode(appErr) 511 statusDesc = appErr.Error() 512 errStatus, err = status.New(statusCode, statusDesc).WithDetails(verr) 513 if err != nil { 514 return err 515 } 516 default: 517 // default case user pass own error type that not proto based 518 statusCode = convertCode(verr) 519 statusDesc = verr.Error() 520 errStatus = status.New(statusCode, statusDesc) 521 } 522 return errStatus.Err() 523 } 524 525 return status.New(statusCode, statusDesc).Err() 526 } 527 528 func (g *grpcServer) newGRPCCodec(contentType string) (encoding.Codec, error) { 529 codecs := make(map[string]encoding.Codec) 530 if g.opts.Context != nil { 531 if v, ok := g.opts.Context.Value(codecsKey{}).(map[string]encoding.Codec); ok && v != nil { 532 codecs = v 533 } 534 } 535 if c, ok := codecs[contentType]; ok { 536 return c, nil 537 } 538 if c, ok := defaultGRPCCodecs[contentType]; ok { 539 return c, nil 540 } 541 return nil, fmt.Errorf("Unsupported Content-Type: %s", contentType) 542 } 543 544 func (g *grpcServer) Options() server.Options { 545 g.RLock() 546 opts := g.opts 547 g.RUnlock() 548 549 return opts 550 } 551 552 func (g *grpcServer) Init(opts ...server.Option) error { 553 g.configure(opts...) 554 return nil 555 } 556 557 func (g *grpcServer) NewHandler(h interface{}, opts ...server.HandlerOption) server.Handler { 558 return newRpcHandler(h, opts...) 559 } 560 561 func (g *grpcServer) Handle(h server.Handler) error { 562 if err := g.rpc.register(h.Handler()); err != nil { 563 return err 564 } 565 566 g.handlers[h.Name()] = h 567 return nil 568 } 569 570 func (g *grpcServer) NewSubscriber(topic string, sb interface{}, opts ...server.SubscriberOption) server.Subscriber { 571 return newSubscriber(topic, sb, opts...) 572 } 573 574 func (g *grpcServer) Subscribe(sb server.Subscriber) error { 575 sub, ok := sb.(*subscriber) 576 if !ok { 577 return fmt.Errorf("invalid subscriber: expected *subscriber") 578 } 579 if len(sub.handlers) == 0 { 580 return fmt.Errorf("invalid subscriber: no handler functions") 581 } 582 583 if err := validateSubscriber(sb); err != nil { 584 return err 585 } 586 587 g.Lock() 588 if _, ok = g.subscribers[sub]; ok { 589 g.Unlock() 590 return fmt.Errorf("subscriber %v already exists", sub) 591 } 592 593 g.subscribers[sub] = nil 594 g.Unlock() 595 return nil 596 } 597 598 func (g *grpcServer) Register() error { 599 g.RLock() 600 rsvc := g.rsvc 601 config := g.opts 602 g.RUnlock() 603 604 log := g.opts.Logger 605 606 regFunc := func(service *registry.Service) error { 607 var regErr error 608 609 for i := 0; i < 3; i++ { 610 // set the ttl 611 rOpts := []registry.RegisterOption{registry.RegisterTTL(config.RegisterTTL)} 612 // attempt to register 613 if err := config.Registry.Register(service, rOpts...); err != nil { 614 // set the error 615 regErr = err 616 // backoff then retry 617 time.Sleep(backoff.Do(i + 1)) 618 continue 619 } 620 // success so nil error 621 regErr = nil 622 break 623 } 624 625 return regErr 626 } 627 628 // if service already filled, reuse it and return early 629 if rsvc != nil { 630 if err := regFunc(rsvc); err != nil { 631 return err 632 } 633 return nil 634 } 635 636 var err error 637 var advt, host, port string 638 var cacheService bool 639 640 // check the advertise address first 641 // if it exists then use it, otherwise 642 // use the address 643 if len(config.Advertise) > 0 { 644 advt = config.Advertise 645 } else { 646 advt = config.Address 647 } 648 649 if cnt := strings.Count(advt, ":"); cnt >= 1 { 650 // ipv6 address in format [host]:port or ipv4 host:port 651 host, port, err = net.SplitHostPort(advt) 652 if err != nil { 653 return err 654 } 655 } else { 656 host = advt 657 } 658 659 if ip := net.ParseIP(host); ip != nil { 660 cacheService = true 661 } 662 663 addr, err := addr.Extract(host) 664 if err != nil { 665 return err 666 } 667 668 // make copy of metadata 669 md := meta.Copy(config.Metadata) 670 671 // register service 672 node := ®istry.Node{ 673 Id: config.Name + "-" + config.Id, 674 Address: mnet.HostPort(addr, port), 675 Metadata: md, 676 } 677 678 node.Metadata["broker"] = config.Broker.String() 679 node.Metadata["registry"] = config.Registry.String() 680 node.Metadata["server"] = g.String() 681 node.Metadata["transport"] = g.String() 682 node.Metadata["protocol"] = "grpc" 683 684 g.RLock() 685 // Maps are ordered randomly, sort the keys for consistency 686 var handlerList []string 687 for n, e := range g.handlers { 688 // Only advertise non internal handlers 689 if !e.Options().Internal { 690 handlerList = append(handlerList, n) 691 } 692 } 693 sort.Strings(handlerList) 694 695 var subscriberList []*subscriber 696 for e := range g.subscribers { 697 // Only advertise non internal subscribers 698 if !e.Options().Internal { 699 subscriberList = append(subscriberList, e) 700 } 701 } 702 sort.Slice(subscriberList, func(i, j int) bool { 703 return subscriberList[i].topic > subscriberList[j].topic 704 }) 705 706 endpoints := make([]*registry.Endpoint, 0, len(handlerList)+len(subscriberList)) 707 for _, n := range handlerList { 708 endpoints = append(endpoints, g.handlers[n].Endpoints()...) 709 } 710 for _, e := range subscriberList { 711 endpoints = append(endpoints, e.Endpoints()...) 712 } 713 g.RUnlock() 714 715 service := ®istry.Service{ 716 Name: config.Name, 717 Version: config.Version, 718 Nodes: []*registry.Node{node}, 719 Endpoints: endpoints, 720 } 721 722 g.RLock() 723 registered := g.registered 724 g.RUnlock() 725 726 if !registered { 727 log.Logf(logger.InfoLevel, "Registry [%s] Registering node: %s", config.Registry.String(), node.Id) 728 } 729 730 // register the service 731 if err := regFunc(service); err != nil { 732 return err 733 } 734 735 // already registered? don't need to register subscribers 736 if registered { 737 return nil 738 } 739 740 g.Lock() 741 defer g.Unlock() 742 743 for sb := range g.subscribers { 744 handler := g.createSubHandler(sb, g.opts) 745 var opts []broker.SubscribeOption 746 if queue := sb.Options().Queue; len(queue) > 0 { 747 opts = append(opts, broker.Queue(queue)) 748 } 749 750 if cx := sb.Options().Context; cx != nil { 751 opts = append(opts, broker.SubscribeContext(cx)) 752 } 753 754 if !sb.Options().AutoAck { 755 opts = append(opts, broker.DisableAutoAck()) 756 } 757 758 log.Logf(logger.InfoLevel, "Subscribing to topic: %s", sb.Topic()) 759 760 sub, err := config.Broker.Subscribe(sb.Topic(), handler, opts...) 761 if err != nil { 762 return err 763 } 764 g.subscribers[sb] = []broker.Subscriber{sub} 765 } 766 767 g.registered = true 768 if cacheService { 769 g.rsvc = service 770 } 771 772 return nil 773 } 774 775 func (g *grpcServer) Deregister() error { 776 var err error 777 var advt, host, port string 778 779 g.RLock() 780 config := g.opts 781 g.RUnlock() 782 783 log := g.opts.Logger 784 785 // check the advertise address first 786 // if it exists then use it, otherwise 787 // use the address 788 if len(config.Advertise) > 0 { 789 advt = config.Advertise 790 } else { 791 advt = config.Address 792 } 793 794 if cnt := strings.Count(advt, ":"); cnt >= 1 { 795 // ipv6 address in format [host]:port or ipv4 host:port 796 host, port, err = net.SplitHostPort(advt) 797 if err != nil { 798 return err 799 } 800 } else { 801 host = advt 802 } 803 804 addr, err := addr.Extract(host) 805 if err != nil { 806 return err 807 } 808 809 node := ®istry.Node{ 810 Id: config.Name + "-" + config.Id, 811 Address: mnet.HostPort(addr, port), 812 } 813 814 service := ®istry.Service{ 815 Name: config.Name, 816 Version: config.Version, 817 Nodes: []*registry.Node{node}, 818 } 819 820 log.Logf(logger.InfoLevel, "Deregistering node: %s", node.Id) 821 822 if err := config.Registry.Deregister(service); err != nil { 823 return err 824 } 825 826 g.Lock() 827 g.rsvc = nil 828 829 if !g.registered { 830 g.Unlock() 831 return nil 832 } 833 834 g.registered = false 835 836 wg := sync.WaitGroup{} 837 for sb, subs := range g.subscribers { 838 for _, sub := range subs { 839 wg.Add(1) 840 go func(s broker.Subscriber) { 841 defer wg.Done() 842 log.Logf(logger.InfoLevel, "Unsubscribing from topic: %s", s.Topic()) 843 s.Unsubscribe() 844 }(sub) 845 } 846 g.subscribers[sb] = nil 847 } 848 wg.Wait() 849 850 g.Unlock() 851 return nil 852 } 853 854 func (g *grpcServer) Start() error { 855 g.RLock() 856 if g.started { 857 g.RUnlock() 858 return nil 859 } 860 g.RUnlock() 861 862 config := g.Options() 863 log := config.Logger 864 865 // micro: config.Transport.Listen(config.Address) 866 var ( 867 ts net.Listener 868 err error 869 ) 870 871 if l := g.getListener(); l != nil { 872 ts = l 873 } else { 874 // check the tls config for secure connect 875 if tc := config.TLSConfig; tc != nil { 876 ts, err = tls.Listen("tcp", config.Address, tc) 877 // otherwise just plain tcp listener 878 } else { 879 ts, err = net.Listen("tcp", config.Address) 880 } 881 if err != nil { 882 return err 883 } 884 } 885 886 if g.opts.Context != nil { 887 if c, ok := g.opts.Context.Value(maxConnKey{}).(int); ok && c > 0 { 888 ts = netutil.LimitListener(ts, c) 889 } 890 } 891 892 log.Logf(logger.InfoLevel, "Server [grpc] Listening on %s", ts.Addr().String()) 893 g.Lock() 894 g.opts.Address = ts.Addr().String() 895 g.Unlock() 896 897 // only connect if we're subscribed 898 if len(g.subscribers) > 0 { 899 // connect to the broker 900 if err := config.Broker.Connect(); err != nil { 901 log.Logf(logger.ErrorLevel, "Broker [%s] connect error: %v", config.Broker.String(), err) 902 return err 903 } 904 905 log.Logf(logger.InfoLevel, "Broker [%s] Connected to %s", config.Broker.String(), config.Broker.Address()) 906 } 907 908 // use RegisterCheck func before register 909 if err = g.opts.RegisterCheck(g.opts.Context); err != nil { 910 log.Logf(logger.ErrorLevel, "Server %s-%s register check error: %s", config.Name, config.Id, err) 911 } else { 912 // announce self to the world 913 if err := g.Register(); err != nil { 914 log.Logf(logger.ErrorLevel, "Server register error: %v", err) 915 } 916 } 917 918 // micro: go ts.Accept(s.accept) 919 go func() { 920 if err := g.srv.Serve(ts); err != nil { 921 log.Logf(logger.ErrorLevel, "gRPC Server start error: %v", err) 922 } 923 }() 924 925 go func() { 926 t := new(time.Ticker) 927 928 // only process if it exists 929 if g.opts.RegisterInterval > time.Duration(0) { 930 // new ticker 931 t = time.NewTicker(g.opts.RegisterInterval) 932 } 933 934 // return error chan 935 var ( 936 err error 937 ch chan error 938 ) 939 940 Loop: 941 for { 942 select { 943 // register self on interval 944 case <-t.C: 945 g.RLock() 946 registered := g.registered 947 g.RUnlock() 948 rerr := g.opts.RegisterCheck(g.opts.Context) 949 if rerr != nil && registered { 950 log.Logf(logger.ErrorLevel, "Server %s-%s register check error: %s, deregister it", config.Name, config.Id, rerr) 951 // deregister self in case of error 952 if err := g.Deregister(); err != nil { 953 log.Logf(logger.ErrorLevel, "Server %s-%s deregister error: %s", config.Name, config.Id, err) 954 } 955 } else if rerr != nil && !registered { 956 log.Logf(logger.ErrorLevel, "Server %s-%s register check error: %s", config.Name, config.Id, rerr) 957 continue 958 } 959 if err := g.Register(); err != nil { 960 log.Log(logger.ErrorLevel, "Server register error: ", err) 961 } 962 // wait for exit 963 case ch = <-g.exit: 964 break Loop 965 } 966 } 967 968 // deregister self 969 if err := g.Deregister(); err != nil { 970 log.Log(logger.ErrorLevel, "Server deregister error: ", err) 971 } 972 973 // wait for waitgroup 974 if g.wg != nil { 975 g.wg.Wait() 976 } 977 978 // stop the grpc server 979 exit := make(chan bool) 980 981 go func() { 982 g.srv.GracefulStop() 983 close(exit) 984 }() 985 986 select { 987 case <-exit: 988 case <-time.After(time.Second): 989 g.srv.Stop() 990 } 991 992 log.Logf(logger.InfoLevel, "Broker [%s] Disconnected from %s", config.Broker.String(), config.Broker.Address()) 993 // disconnect broker 994 if err = config.Broker.Disconnect(); err != nil { 995 log.Logf(logger.ErrorLevel, "Broker [%s] disconnect error: %v", config.Broker.String(), err) 996 } 997 998 // close transport 999 ch <- err 1000 }() 1001 1002 // mark the server as started 1003 g.Lock() 1004 g.started = true 1005 g.Unlock() 1006 1007 return nil 1008 } 1009 1010 func (g *grpcServer) Stop() error { 1011 g.RLock() 1012 if !g.started { 1013 g.RUnlock() 1014 return nil 1015 } 1016 g.RUnlock() 1017 1018 ch := make(chan error) 1019 g.exit <- ch 1020 1021 var err error 1022 select { 1023 case err = <-ch: 1024 g.Lock() 1025 g.rsvc = nil 1026 g.started = false 1027 g.Unlock() 1028 } 1029 1030 return err 1031 } 1032 1033 func (g *grpcServer) String() string { 1034 return "grpc" 1035 } 1036 1037 func NewServer(opts ...server.Option) server.Server { 1038 return newGRPCServer(opts...) 1039 }