github.com/polarismesh/polaris@v1.17.8/service/client_info.go (about) 1 /** 2 * Tencent is pleased to support the open source community by making Polaris available. 3 * 4 * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. 5 * 6 * Licensed under the BSD 3-Clause License (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * https://opensource.org/licenses/BSD-3-Clause 11 * 12 * Unless required by applicable law or agreed to in writing, software distributed 13 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 14 * CONDITIONS OF ANY KIND, either express or implied. See the License for the 15 * specific language governing permissions and limitations under the License. 16 */ 17 18 package service 19 20 import ( 21 "context" 22 23 apimodel "github.com/polarismesh/specification/source/go/api/v1/model" 24 apiservice "github.com/polarismesh/specification/source/go/api/v1/service_manage" 25 "go.uber.org/zap" 26 27 api "github.com/polarismesh/polaris/common/api/v1" 28 "github.com/polarismesh/polaris/common/model" 29 commonstore "github.com/polarismesh/polaris/common/store" 30 "github.com/polarismesh/polaris/common/utils" 31 ) 32 33 var ( 34 clientFilterAttributes = map[string]struct{}{ 35 "type": {}, 36 "host": {}, 37 "limit": {}, 38 "offset": {}, 39 "version": {}, 40 } 41 ) 42 43 func (s *Server) checkAndStoreClient(ctx context.Context, req *apiservice.Client) *apiservice.Response { 44 clientId := req.GetId().GetValue() 45 var needStore bool 46 client := s.caches.Client().GetClient(clientId) 47 var resp *apiservice.Response 48 if nil == client { 49 needStore = true 50 } else { 51 needStore = !clientEquals(client.Proto(), req) 52 } 53 if needStore { 54 client, resp = s.createClient(ctx, req) 55 } 56 57 if resp != nil { 58 if resp.GetCode().GetValue() != api.ExistedResource { 59 return resp 60 } 61 } 62 63 resp = s.HealthServer().ReportByClient(context.Background(), req) 64 respCode := apimodel.Code(resp.GetCode().GetValue()) 65 if respCode == apimodel.Code_HealthCheckNotOpen || respCode == apimodel.Code_HeartbeatTypeNotFound { 66 return api.NewResponse(apimodel.Code_ExecuteSuccess) 67 } 68 return resp 69 } 70 71 func (s *Server) createClient(ctx context.Context, req *apiservice.Client) (*model.Client, *apiservice.Response) { 72 if namingServer.bc == nil || !namingServer.bc.ClientRegisterOpen() { 73 return nil, nil 74 } 75 return s.asyncCreateClient(ctx, req) // 批量异步 76 } 77 78 // 异步新建客户端 79 // 底层函数会合并create请求,增加并发创建的吞吐 80 // req 原始请求 81 // ins 包含了req数据与instanceID,serviceToken 82 func (s *Server) asyncCreateClient(ctx context.Context, req *apiservice.Client) (*model.Client, *apiservice.Response) { 83 rid := utils.ParseRequestID(ctx) 84 pid := utils.ParsePlatformID(ctx) 85 future := s.bc.AsyncRegisterClient(req) 86 if err := future.Wait(); err != nil { 87 log.Error("[Server][ReportClient] async create client", zap.Error(err), utils.ZapRequestID(rid), 88 utils.ZapPlatformID(pid)) 89 if future.Code() == apimodel.Code_ExistedResource { 90 req.Id = utils.NewStringValue(req.GetId().GetValue()) 91 } 92 return nil, api.NewClientResponse(apimodel.Code(future.Code()), req) 93 } 94 95 return future.Client(), nil 96 } 97 98 // GetReportClients create one instance 99 func (s *Server) GetReportClients(ctx context.Context, query map[string]string) *apiservice.BatchQueryResponse { 100 searchFilters := make(map[string]string) 101 var ( 102 offset, limit uint32 103 err error 104 ) 105 106 for key, value := range query { 107 if _, ok := clientFilterAttributes[key]; !ok { 108 log.Errorf("[Server][Client] attribute(%s) it not allowed", key) 109 return api.NewBatchQueryResponseWithMsg(apimodel.Code_InvalidParameter, key+" is not allowed") 110 } 111 searchFilters[key] = value 112 } 113 114 var ( 115 total uint32 116 clients []*model.Client 117 ) 118 119 offset, limit, err = utils.ParseOffsetAndLimit(searchFilters) 120 if err != nil { 121 return api.NewBatchQueryResponse(apimodel.Code_InvalidParameter) 122 } 123 124 total, services, err := s.caches.Client().GetClientsByFilter(searchFilters, offset, limit) 125 if err != nil { 126 log.Errorf("[Server][Client][Query] req(%+v) store err: %s", query, err.Error()) 127 return api.NewBatchQueryResponse(commonstore.StoreCode2APICode(err)) 128 } 129 130 resp := api.NewBatchQueryResponse(apimodel.Code_ExecuteSuccess) 131 resp.Amount = utils.NewUInt32Value(total) 132 resp.Size = utils.NewUInt32Value(uint32(len(services))) 133 resp.Clients = enhancedClients2Api(clients, client2Api) 134 return resp 135 } 136 137 type Client2Api func(client *model.Client) *apiservice.Client 138 139 // client 数组转为[]*api.Client 140 func enhancedClients2Api(clients []*model.Client, handler Client2Api) []*apiservice.Client { 141 out := make([]*apiservice.Client, 0, len(clients)) 142 for _, entry := range clients { 143 outUser := handler(entry) 144 out = append(out, outUser) 145 } 146 return out 147 } 148 149 // model.Client 转为 api.Client 150 func client2Api(client *model.Client) *apiservice.Client { 151 if client == nil { 152 return nil 153 } 154 out := client.Proto() 155 return out 156 } 157 158 func clientEquals(client1 *apiservice.Client, client2 *apiservice.Client) bool { 159 if client1.GetId().GetValue() != client2.GetId().GetValue() { 160 return false 161 } 162 if client1.GetHost().GetValue() != client2.GetHost().GetValue() { 163 return false 164 } 165 if client1.GetVersion().GetValue() != client2.GetVersion().GetValue() { 166 return false 167 } 168 if client1.GetType() != client2.GetType() { 169 return false 170 } 171 if client1.GetLocation().GetRegion().GetValue() != client2.GetLocation().GetRegion().GetValue() { 172 return false 173 } 174 if client1.GetLocation().GetZone().GetValue() != client2.GetLocation().GetZone().GetValue() { 175 return false 176 } 177 if client1.GetLocation().GetCampus().GetValue() != client2.GetLocation().GetCampus().GetValue() { 178 return false 179 } 180 if len(client1.Stat) != len(client2.Stat) { 181 return false 182 } 183 for i := 0; i < len(client1.Stat); i++ { 184 if client1.Stat[i].GetTarget().GetValue() != client2.Stat[i].GetTarget().GetValue() { 185 return false 186 } 187 if client1.Stat[i].GetPort().GetValue() != client2.Stat[i].GetPort().GetValue() { 188 return false 189 } 190 if client1.Stat[i].GetPath().GetValue() != client2.Stat[i].GetPath().GetValue() { 191 return false 192 } 193 if client1.Stat[i].GetProtocol().GetValue() != client2.Stat[i].GetProtocol().GetValue() { 194 return false 195 } 196 } 197 return true 198 }