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