dubbo.apache.org/dubbo-go/v3@v3.1.1/protocol/grpc/server.go (about)

     1  /*
     2   * Licensed to the Apache Software Foundation (ASF) under one or more
     3   * contributor license agreements.  See the NOTICE file distributed with
     4   * this work for additional information regarding copyright ownership.
     5   * The ASF licenses this file to You under the Apache License, Version 2.0
     6   * (the "License"); you may not use this file except in compliance with
     7   * the License.  You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  
    18  package grpc
    19  
    20  import (
    21  	"crypto/tls"
    22  	"fmt"
    23  	"net"
    24  	"sync"
    25  	"time"
    26  )
    27  
    28  import (
    29  	"github.com/dubbogo/gost/log/logger"
    30  
    31  	"github.com/dustin/go-humanize"
    32  
    33  	"github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc"
    34  
    35  	"github.com/opentracing/opentracing-go"
    36  
    37  	"google.golang.org/grpc"
    38  	"google.golang.org/grpc/credentials"
    39  	"google.golang.org/grpc/credentials/insecure"
    40  	"google.golang.org/grpc/reflection"
    41  )
    42  
    43  import (
    44  	"dubbo.apache.org/dubbo-go/v3/common"
    45  	"dubbo.apache.org/dubbo-go/v3/common/constant"
    46  	"dubbo.apache.org/dubbo-go/v3/config"
    47  	"dubbo.apache.org/dubbo-go/v3/protocol"
    48  )
    49  
    50  // DubboGrpcService is gRPC service
    51  type DubboGrpcService interface {
    52  	// SetProxyImpl sets proxy.
    53  	SetProxyImpl(impl protocol.Invoker)
    54  	// GetProxyImpl gets proxy.
    55  	GetProxyImpl() protocol.Invoker
    56  	// ServiceDesc gets an RPC service's specification.
    57  	ServiceDesc() *grpc.ServiceDesc
    58  }
    59  
    60  // Server is a gRPC server
    61  type Server struct {
    62  	grpcServer *grpc.Server
    63  	bufferSize int
    64  }
    65  
    66  // NewServer creates a new server
    67  func NewServer() *Server {
    68  	return &Server{}
    69  }
    70  
    71  func (s *Server) SetBufferSize(n int) {
    72  	s.bufferSize = n
    73  }
    74  
    75  // Start gRPC server with @url
    76  func (s *Server) Start(url *common.URL) {
    77  	var (
    78  		addr string
    79  		err  error
    80  	)
    81  	addr = url.Location
    82  	lis, err := net.Listen("tcp", addr)
    83  	if err != nil {
    84  		panic(err)
    85  	}
    86  
    87  	maxServerRecvMsgSize := constant.DefaultMaxServerRecvMsgSize
    88  	if recvMsgSize, convertErr := humanize.ParseBytes(url.GetParam(constant.MaxServerRecvMsgSize, "")); convertErr == nil && recvMsgSize != 0 {
    89  		maxServerRecvMsgSize = int(recvMsgSize)
    90  	}
    91  	maxServerSendMsgSize := constant.DefaultMaxServerSendMsgSize
    92  	if sendMsgSize, convertErr := humanize.ParseBytes(url.GetParam(constant.MaxServerSendMsgSize, "")); err == convertErr && sendMsgSize != 0 {
    93  		maxServerSendMsgSize = int(sendMsgSize)
    94  	}
    95  
    96  	// If global trace instance was set, then server tracer instance
    97  	// can be get. If not, will return NoopTracer.
    98  	tracer := opentracing.GlobalTracer()
    99  	var serverOpts []grpc.ServerOption
   100  	serverOpts = append(serverOpts,
   101  		grpc.UnaryInterceptor(otgrpc.OpenTracingServerInterceptor(tracer)),
   102  		grpc.StreamInterceptor(otgrpc.OpenTracingStreamServerInterceptor(tracer)),
   103  		grpc.MaxRecvMsgSize(maxServerRecvMsgSize),
   104  		grpc.MaxSendMsgSize(maxServerSendMsgSize),
   105  	)
   106  
   107  	tlsConfig := config.GetRootConfig().TLSConfig
   108  	if tlsConfig != nil {
   109  		var cfg *tls.Config
   110  		cfg, err = config.GetServerTlsConfig(&config.TLSConfig{
   111  			CACertFile:    tlsConfig.CACertFile,
   112  			TLSCertFile:   tlsConfig.TLSCertFile,
   113  			TLSKeyFile:    tlsConfig.TLSKeyFile,
   114  			TLSServerName: tlsConfig.TLSServerName,
   115  		})
   116  		if err != nil {
   117  			return
   118  		}
   119  		logger.Infof("Grpc Server initialized the TLSConfig configuration")
   120  		serverOpts = append(serverOpts, grpc.Creds(credentials.NewTLS(cfg)))
   121  	} else {
   122  		serverOpts = append(serverOpts, grpc.Creds(insecure.NewCredentials()))
   123  	}
   124  	server := grpc.NewServer(serverOpts...)
   125  	s.grpcServer = server
   126  
   127  	go func() {
   128  		providerServices := config.GetProviderConfig().Services
   129  
   130  		if len(providerServices) == 0 {
   131  			panic("provider service map is null")
   132  		}
   133  		// wait all exporter ready , then set proxy impl and grpc registerService
   134  		waitGrpcExporter(providerServices)
   135  		registerService(providerServices, server)
   136  		reflection.Register(server)
   137  
   138  		if err = server.Serve(lis); err != nil {
   139  			logger.Errorf("server serve failed with err: %v", err)
   140  		}
   141  	}()
   142  }
   143  
   144  // getSyncMapLen get sync map len
   145  func getSyncMapLen(m *sync.Map) int {
   146  	length := 0
   147  
   148  	m.Range(func(_, _ interface{}) bool {
   149  		length++
   150  		return true
   151  	})
   152  	return length
   153  }
   154  
   155  // waitGrpcExporter wait until len(providerServices) = len(ExporterMap)
   156  func waitGrpcExporter(providerServices map[string]*config.ServiceConfig) {
   157  	t := time.NewTicker(50 * time.Millisecond)
   158  	defer t.Stop()
   159  	pLen := len(providerServices)
   160  	ta := time.NewTimer(10 * time.Second)
   161  	defer ta.Stop()
   162  
   163  	for {
   164  		select {
   165  		case <-t.C:
   166  			mLen := getSyncMapLen(grpcProtocol.ExporterMap())
   167  			if pLen == mLen {
   168  				return
   169  			}
   170  		case <-ta.C:
   171  			panic("wait grpc exporter timeout when start grpc server")
   172  		}
   173  	}
   174  }
   175  
   176  // registerService SetProxyImpl invoker and grpc service
   177  func registerService(providerServices map[string]*config.ServiceConfig, server *grpc.Server) {
   178  	for key, providerService := range providerServices {
   179  		service := config.GetProviderService(key)
   180  		ds, ok := service.(DubboGrpcService)
   181  		if !ok {
   182  			panic("illegal service type registered")
   183  		}
   184  
   185  		serviceKey := common.ServiceKey(providerService.Interface, providerService.Group, providerService.Version)
   186  		exporter, _ := grpcProtocol.ExporterMap().Load(serviceKey)
   187  		if exporter == nil {
   188  			panic(fmt.Sprintf("no exporter found for servicekey: %v", serviceKey))
   189  		}
   190  		invoker := exporter.(protocol.Exporter).GetInvoker()
   191  		if invoker == nil {
   192  			panic(fmt.Sprintf("no invoker found for servicekey: %v", serviceKey))
   193  		}
   194  
   195  		ds.SetProxyImpl(invoker)
   196  		server.RegisterService(ds.ServiceDesc(), service)
   197  	}
   198  }
   199  
   200  // Stop gRPC server
   201  func (s *Server) Stop() {
   202  	s.grpcServer.Stop()
   203  }
   204  
   205  // GracefulStop gRPC server
   206  func (s *Server) GracefulStop() {
   207  	s.grpcServer.GracefulStop()
   208  }