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 := &registry.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 := &registry.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 := &registry.Node{
   810  		Id:      config.Name + "-" + config.Id,
   811  		Address: mnet.HostPort(addr, port),
   812  	}
   813  
   814  	service := &registry.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  }