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