dubbo.apache.org/dubbo-go/v3@v3.1.1/remoting/xds/mapping/handler.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 mapping 19 20 import ( 21 "encoding/json" 22 "fmt" 23 "io" 24 "net/http" 25 "os" 26 "sync" 27 "time" 28 29 "github.com/dubbogo/gost/log/logger" 30 31 structpb "github.com/golang/protobuf/ptypes/struct" 32 33 "dubbo.apache.org/dubbo-go/v3/remoting/xds/common" 34 "dubbo.apache.org/dubbo-go/v3/xds/client" 35 perrors "github.com/pkg/errors" 36 ) 37 38 const ( 39 authorizationHeader = "Authorization" 40 istiodTokenPrefix = "Bearer " 41 ) 42 43 type InterfaceMapHandlerImpl struct { 44 hostAddr common.HostAddr 45 46 istioDebugAddr common.HostAddr 47 48 xdsClient client.XDSClient 49 50 istioTokenPath string 51 52 /* 53 interfaceAppNameMap store map of serviceUniqueKey -> hostAddr 54 */ 55 interfaceAppNameMap map[string]string 56 interfaceAppNameMapLock sync.RWMutex 57 58 /* 59 interfaceNameHostAddrMap cache the dubbo interface unique key -> hostName 60 the data is read from istiod:8080/debug/adsz, connection metadata["LABELS"]["DUBBO_GO"] 61 */ 62 interfaceNameHostAddrMap map[string]string 63 interfaceNameHostAddrMapLock sync.RWMutex 64 localDebugMode bool 65 } 66 67 func (i *InterfaceMapHandlerImpl) UnRegister(serviceUniqueKey string) error { 68 i.interfaceAppNameMapLock.Lock() 69 delete(i.interfaceAppNameMap, serviceUniqueKey) 70 i.interfaceAppNameMapLock.Unlock() 71 return i.xdsClient.SetMetadata(i.interfaceAppNameMap2DubboGoMetadata()) 72 } 73 74 func (i *InterfaceMapHandlerImpl) Register(serviceUniqueKey string) error { 75 i.interfaceAppNameMapLock.Lock() 76 i.interfaceAppNameMap[serviceUniqueKey] = i.hostAddr.String() 77 i.interfaceAppNameMapLock.Unlock() 78 return i.xdsClient.SetMetadata(i.interfaceAppNameMap2DubboGoMetadata()) 79 } 80 81 func (i *InterfaceMapHandlerImpl) GetDubboGoMetadata() (map[string]string, error) { 82 return i.getServiceUniqueKeyHostAddrMapFromPilot() 83 } 84 85 func (i *InterfaceMapHandlerImpl) GetHostAddrMap(serviceUniqueKey string) (string, error) { 86 i.interfaceNameHostAddrMapLock.RLock() 87 if hostAddr, ok := i.interfaceNameHostAddrMap[serviceUniqueKey]; ok { 88 i.interfaceNameHostAddrMapLock.RUnlock() 89 return hostAddr, nil 90 } 91 i.interfaceNameHostAddrMapLock.RUnlock() 92 93 retryCount := 0 94 maxRetries := 30 95 for { 96 if interfaceHostAddrMap, err := i.getServiceUniqueKeyHostAddrMapFromPilot(); err != nil { 97 return "", err 98 } else { 99 i.interfaceNameHostAddrMapLock.Lock() 100 i.interfaceNameHostAddrMap = interfaceHostAddrMap 101 i.interfaceNameHostAddrMapLock.Unlock() 102 hostName, ok := interfaceHostAddrMap[serviceUniqueKey] 103 if !ok { 104 logger.Infof("[XDS Wrapped Client] Try getting interface %s 's host from istio %s:8080\n", serviceUniqueKey, i.istioDebugAddr) 105 time.Sleep(time.Millisecond * 100) 106 retryCount++ 107 if retryCount > maxRetries { 108 err := perrors.Errorf("[XDS Wrapped Client] Try getting interface %s 's host from istio %s:8080 failed. Please check if provider's service resource is deployed correctly.\n", serviceUniqueKey, i.istioDebugAddr) 109 logger.Error(err) 110 return "", err 111 } 112 continue 113 } 114 return hostName, nil 115 } 116 } 117 } 118 119 // getServiceUniqueKeyHostAddrMapFromPilot get map of service key like 'provider::api.Greeter' to host addr like 120 // 'dubbo-go-app.default.svc.cluster.local:20000' 121 func (i *InterfaceMapHandlerImpl) getServiceUniqueKeyHostAddrMapFromPilot() (map[string]string, error) { 122 req, _ := http.NewRequest(http.MethodGet, fmt.Sprintf("http://%s/debug/adsz", i.istioDebugAddr.String()), nil) 123 if !i.localDebugMode { 124 token, err := os.ReadFile(i.istioTokenPath) 125 if err != nil { 126 return nil, err 127 } 128 req.Header.Add(authorizationHeader, istiodTokenPrefix+string(token)) 129 } 130 rsp, err := http.DefaultClient.Do(req) 131 if err != nil { 132 logger.Infof("[XDS Wrapped Client] Try getting interface host map from istio IP %s with error %s\n", 133 i.istioDebugAddr, err) 134 return nil, err 135 } 136 137 data, err := io.ReadAll(rsp.Body) 138 if err != nil { 139 return nil, err 140 } 141 adszRsp := &ADSZResponse{} 142 if err := json.Unmarshal(data, adszRsp); err != nil { 143 return nil, err 144 } 145 return adszRsp.GetMap(), nil 146 } 147 148 func (i *InterfaceMapHandlerImpl) interfaceAppNameMap2DubboGoMetadata() *structpb.Struct { 149 i.interfaceAppNameMapLock.RLock() 150 defer i.interfaceAppNameMapLock.RUnlock() 151 data, _ := json.Marshal(i.interfaceAppNameMap) 152 return GetDubboGoMetadata(string(data)) 153 } 154 155 func NewInterfaceMapHandlerImpl(xdsClient client.XDSClient, istioTokenPath string, istioDebugAddr, hostAddr common.HostAddr, localDebugMode bool) InterfaceMapHandler { 156 return &InterfaceMapHandlerImpl{ 157 xdsClient: xdsClient, 158 interfaceAppNameMap: map[string]string{}, 159 interfaceNameHostAddrMap: map[string]string{}, 160 istioDebugAddr: istioDebugAddr, 161 hostAddr: hostAddr, 162 istioTokenPath: istioTokenPath, 163 localDebugMode: localDebugMode, 164 } 165 } 166 167 type InterfaceMapHandler interface { 168 Register(string) error 169 UnRegister(string) error 170 GetHostAddrMap(string) (string, error) 171 GetDubboGoMetadata() (map[string]string, error) 172 }