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