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  }