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 }