dubbo.apache.org/dubbo-go/v3@v3.1.1/protocol/grpc/client.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 "reflect" 22 "sync" 23 "time" 24 ) 25 26 import ( 27 "github.com/dubbogo/gost/log/logger" 28 29 "github.com/dustin/go-humanize" 30 31 "github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc" 32 33 "github.com/opentracing/opentracing-go" 34 35 "google.golang.org/grpc" 36 "google.golang.org/grpc/credentials" 37 "google.golang.org/grpc/credentials/insecure" 38 39 "gopkg.in/yaml.v2" 40 ) 41 42 import ( 43 "dubbo.apache.org/dubbo-go/v3/common" 44 "dubbo.apache.org/dubbo-go/v3/common/constant" 45 "dubbo.apache.org/dubbo-go/v3/config" 46 ) 47 48 var clientConf *ClientConfig 49 var clientConfInitOnce sync.Once 50 51 // Client is gRPC client include client connection and invoker 52 type Client struct { 53 *grpc.ClientConn 54 invoker reflect.Value 55 } 56 57 // NewClient creates a new gRPC client. 58 func NewClient(url *common.URL) (*Client, error) { 59 clientConfInitOnce.Do(clientInit) 60 61 // If global trace instance was set, it means trace function enabled. 62 // If not, will return NoopTracer. 63 tracer := opentracing.GlobalTracer() 64 dialOpts := make([]grpc.DialOption, 0, 4) 65 66 // set max send and recv msg size 67 maxCallRecvMsgSize := constant.DefaultMaxCallRecvMsgSize 68 if recvMsgSize, err := humanize.ParseBytes(url.GetParam(constant.MaxCallRecvMsgSize, "")); err == nil && recvMsgSize > 0 { 69 maxCallRecvMsgSize = int(recvMsgSize) 70 } 71 maxCallSendMsgSize := constant.DefaultMaxCallSendMsgSize 72 if sendMsgSize, err := humanize.ParseBytes(url.GetParam(constant.MaxCallSendMsgSize, "")); err == nil && sendMsgSize > 0 { 73 maxCallSendMsgSize = int(sendMsgSize) 74 } 75 76 // consumer config client connectTimeout 77 //connectTimeout := config.GetConsumerConfig().ConnectTimeout 78 79 dialOpts = append(dialOpts, 80 grpc.WithBlock(), 81 // todo config network timeout 82 grpc.WithTimeout(time.Second*3), 83 grpc.WithUnaryInterceptor(otgrpc.OpenTracingClientInterceptor(tracer, otgrpc.LogPayloads())), 84 grpc.WithStreamInterceptor(otgrpc.OpenTracingStreamClientInterceptor(tracer, otgrpc.LogPayloads())), 85 grpc.WithDefaultCallOptions( 86 grpc.CallContentSubtype(clientConf.ContentSubType), 87 grpc.MaxCallRecvMsgSize(maxCallRecvMsgSize), 88 grpc.MaxCallSendMsgSize(maxCallSendMsgSize), 89 ), 90 ) 91 tlsConfig := config.GetRootConfig().TLSConfig 92 93 if tlsConfig != nil { 94 cfg, err := config.GetClientTlsConfig(&config.TLSConfig{ 95 CACertFile: tlsConfig.CACertFile, 96 TLSCertFile: tlsConfig.TLSCertFile, 97 TLSKeyFile: tlsConfig.TLSKeyFile, 98 TLSServerName: tlsConfig.TLSServerName, 99 }) 100 logger.Infof("Grpc Client initialized the TLSConfig configuration") 101 if err != nil { 102 return nil, err 103 } 104 dialOpts = append(dialOpts, grpc.WithTransportCredentials(credentials.NewTLS(cfg))) 105 } else { 106 dialOpts = append(dialOpts, grpc.WithTransportCredentials(insecure.NewCredentials())) 107 } 108 109 conn, err := grpc.Dial(url.Location, dialOpts...) 110 if err != nil { 111 logger.Errorf("grpc dial error: %v", err) 112 return nil, err 113 } 114 115 key := url.GetParam(constant.InterfaceKey, "") 116 impl := config.GetConsumerServiceByInterfaceName(key) 117 invoker := getInvoker(impl, conn) 118 119 return &Client{ 120 ClientConn: conn, 121 invoker: reflect.ValueOf(invoker), 122 }, nil 123 } 124 125 func clientInit() { 126 // load rootConfig from runtime 127 rootConfig := config.GetRootConfig() 128 129 clientConfig := GetClientConfig() 130 clientConf = &clientConfig 131 132 // check client config and decide whether to use the default config 133 defer func() { 134 if clientConf == nil || len(clientConf.ContentSubType) == 0 { 135 defaultClientConfig := GetDefaultClientConfig() 136 clientConf = &defaultClientConfig 137 } 138 if err := clientConf.Validate(); err != nil { 139 panic(err) 140 } 141 }() 142 143 if rootConfig.Application == nil { 144 return 145 } 146 protocolConf := config.GetRootConfig().Protocols 147 148 if protocolConf == nil { 149 logger.Info("protocol_conf default use dubbo config") 150 } else { 151 grpcConf := protocolConf[GRPC] 152 if grpcConf == nil { 153 logger.Warnf("grpcConf is nil") 154 return 155 } 156 grpcConfByte, err := yaml.Marshal(grpcConf) 157 if err != nil { 158 panic(err) 159 } 160 err = yaml.Unmarshal(grpcConfByte, clientConf) 161 if err != nil { 162 panic(err) 163 } 164 } 165 } 166 167 func getInvoker(impl interface{}, conn *grpc.ClientConn) interface{} { 168 var in []reflect.Value 169 in = append(in, reflect.ValueOf(conn)) 170 method := reflect.ValueOf(impl).MethodByName("GetDubboStub") 171 res := method.Call(in) 172 return res[0].Interface() 173 }