gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/grpc/xds/googledirectpath/googlec2p.go (about) 1 /* 2 * 3 * Copyright 2021 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * 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 19 // Package googledirectpath implements a resolver that configures xds to make 20 // cloud to prod directpath connection. 21 // 22 // It's a combo of DNS and xDS resolvers. It delegates to DNS if 23 // - not on GCE, or 24 // - xDS bootstrap env var is set (so this client needs to do normal xDS, not 25 // direct path, and clients with this scheme is not part of the xDS mesh). 26 package googledirectpath 27 28 import ( 29 "fmt" 30 "time" 31 32 grpc "gitee.com/ks-custle/core-gm/grpc" 33 "gitee.com/ks-custle/core-gm/grpc/credentials/google" 34 "gitee.com/ks-custle/core-gm/grpc/grpclog" 35 "gitee.com/ks-custle/core-gm/grpc/internal/envconfig" 36 "gitee.com/ks-custle/core-gm/grpc/internal/googlecloud" 37 internalgrpclog "gitee.com/ks-custle/core-gm/grpc/internal/grpclog" 38 "gitee.com/ks-custle/core-gm/grpc/internal/grpcrand" 39 "gitee.com/ks-custle/core-gm/grpc/resolver" 40 _ "gitee.com/ks-custle/core-gm/grpc/xds" // To register xds resolvers and balancers. 41 "gitee.com/ks-custle/core-gm/grpc/xds/internal/xdsclient" 42 "gitee.com/ks-custle/core-gm/grpc/xds/internal/xdsclient/bootstrap" 43 "gitee.com/ks-custle/core-gm/grpc/xds/internal/xdsclient/xdsresource/version" 44 "google.golang.org/protobuf/types/known/structpb" 45 46 v3corepb "gitee.com/ks-custle/core-gm/go-control-plane/envoy/config/core/v3" 47 ) 48 49 const ( 50 c2pScheme = "google-c2p-experimental" 51 52 tdURL = "dns:///directpath-pa.googleapis.com" 53 httpReqTimeout = 10 * time.Second 54 zoneURL = "http://metadata.google.internal/computeMetadata/v1/instance/zone" 55 ipv6URL = "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/ipv6s" 56 57 gRPCUserAgentName = "gRPC Go" 58 clientFeatureNoOverprovisioning = "envoy.lb.does_not_support_overprovisioning" 59 ipv6CapableMetadataName = "TRAFFICDIRECTOR_DIRECTPATH_C2P_IPV6_CAPABLE" 60 61 logPrefix = "[google-c2p-resolver]" 62 63 dnsName, xdsName = "dns", "xds" 64 ) 65 66 // For overriding in unittests. 67 var ( 68 onGCE = googlecloud.OnGCE 69 70 newClientWithConfig = func(config *bootstrap.Config) (xdsclient.XDSClient, error) { 71 return xdsclient.NewWithConfig(config) 72 } 73 74 logger = internalgrpclog.NewPrefixLogger(grpclog.Component("directpath"), logPrefix) 75 ) 76 77 func init() { 78 resolver.Register(c2pResolverBuilder{}) 79 } 80 81 type c2pResolverBuilder struct{} 82 83 func (c2pResolverBuilder) Build(t resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) { 84 if !runDirectPath() { 85 // If not xDS, fallback to DNS. 86 // t.Scheme is deprecated, use URL.Scheme instead. 87 //t.Scheme = dnsName 88 t.URL.Scheme = dnsName 89 return resolver.Get(dnsName).Build(t, cc, opts) 90 } 91 92 // Note that the following calls to getZone() and getIPv6Capable() does I/O, 93 // and has 10 seconds timeout each. 94 // 95 // This should be fine in most of the cases. In certain error cases, this 96 // could block Dial() for up to 10 seconds (each blocking call has its own 97 // goroutine). 98 zoneCh, ipv6CapableCh := make(chan string), make(chan bool) 99 go func() { zoneCh <- getZone(httpReqTimeout) }() 100 go func() { ipv6CapableCh <- getIPv6Capable(httpReqTimeout) }() 101 102 balancerName := envconfig.C2PResolverTestOnlyTrafficDirectorURI 103 if balancerName == "" { 104 balancerName = tdURL 105 } 106 config := &bootstrap.Config{ 107 XDSServer: &bootstrap.ServerConfig{ 108 ServerURI: balancerName, 109 Creds: grpc.WithCredentialsBundle(google.NewDefaultCredentials()), 110 TransportAPI: version.TransportV3, 111 NodeProto: newNode(<-zoneCh, <-ipv6CapableCh), 112 }, 113 ClientDefaultListenerResourceNameTemplate: "%s", 114 } 115 116 // Create singleton xds client with this config. The xds client will be 117 // used by the xds resolver later. 118 xdsC, err := newClientWithConfig(config) 119 if err != nil { 120 return nil, fmt.Errorf("failed to start xDS client: %v", err) 121 } 122 123 // Create and return an xDS resolver. 124 // t.Scheme is deprecated, use URL.Scheme instead. 125 //t.Scheme = xdsName 126 t.URL.Scheme = xdsName 127 xdsR, err := resolver.Get(xdsName).Build(t, cc, opts) 128 if err != nil { 129 xdsC.Close() 130 return nil, err 131 } 132 return &c2pResolver{ 133 Resolver: xdsR, 134 client: xdsC, 135 }, nil 136 } 137 138 func (c2pResolverBuilder) Scheme() string { 139 return c2pScheme 140 } 141 142 type c2pResolver struct { 143 resolver.Resolver 144 client xdsclient.XDSClient 145 } 146 147 func (r *c2pResolver) Close() { 148 r.Resolver.Close() 149 r.client.Close() 150 } 151 152 var ipv6EnabledMetadata = &structpb.Struct{ 153 Fields: map[string]*structpb.Value{ 154 ipv6CapableMetadataName: structpb.NewBoolValue(true), 155 }, 156 } 157 158 var id = fmt.Sprintf("C2P-%d", grpcrand.Int()) 159 160 // newNode makes a copy of defaultNode, and populate it's Metadata and 161 // Locality fields. 162 func newNode(zone string, ipv6Capable bool) *v3corepb.Node { 163 ret := &v3corepb.Node{ 164 // Not all required fields are set in defaultNote. Metadata will be set 165 // if ipv6 is enabled. Locality will be set to the value from metadata. 166 Id: id, 167 UserAgentName: gRPCUserAgentName, 168 UserAgentVersionType: &v3corepb.Node_UserAgentVersion{UserAgentVersion: grpc.Version}, 169 ClientFeatures: []string{clientFeatureNoOverprovisioning}, 170 } 171 ret.Locality = &v3corepb.Locality{Zone: zone} 172 if ipv6Capable { 173 ret.Metadata = ipv6EnabledMetadata 174 } 175 return ret 176 } 177 178 // runDirectPath returns whether this resolver should use direct path. 179 // 180 // direct path is enabled if this client is running on GCE, and the normal xDS 181 // is not used (bootstrap env vars are not set). 182 func runDirectPath() bool { 183 return envconfig.XDSBootstrapFileName == "" && envconfig.XDSBootstrapFileContent == "" && onGCE() 184 }