github.com/polarismesh/polaris@v1.17.8/service/instance.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  	"errors"
    23  	"fmt"
    24  	"time"
    25  
    26  	"github.com/gogo/protobuf/jsonpb"
    27  	"github.com/golang/protobuf/ptypes/wrappers"
    28  	apimodel "github.com/polarismesh/specification/source/go/api/v1/model"
    29  	apiservice "github.com/polarismesh/specification/source/go/api/v1/service_manage"
    30  	"go.uber.org/zap"
    31  	"google.golang.org/protobuf/types/known/wrapperspb"
    32  
    33  	api "github.com/polarismesh/polaris/common/api/v1"
    34  	"github.com/polarismesh/polaris/common/eventhub"
    35  	"github.com/polarismesh/polaris/common/model"
    36  	commonstore "github.com/polarismesh/polaris/common/store"
    37  	"github.com/polarismesh/polaris/common/utils"
    38  )
    39  
    40  var (
    41  	// InstanceFilterAttributes 查询实例支持的过滤字段
    42  	InstanceFilterAttributes = map[string]bool{
    43  		"id":            true, // 实例ID
    44  		"service":       true, // 服务name
    45  		"namespace":     true, // 服务namespace
    46  		"host":          true,
    47  		"port":          true,
    48  		"keys":          true,
    49  		"values":        true,
    50  		"protocol":      true,
    51  		"version":       true,
    52  		"health_status": true,
    53  		"healthy":       true, // health_status, healthy都有,以healthy为准
    54  		"isolate":       true,
    55  		"weight":        true,
    56  		"logic_set":     true,
    57  		"cmdb_region":   true,
    58  		"cmdb_zone":     true,
    59  		"cmdb_idc":      true,
    60  		"priority":      true,
    61  		"offset":        true,
    62  		"limit":         true,
    63  	}
    64  	// InsFilter2toreAttr 查询字段转为存储层的属性值,映射表
    65  	InsFilter2toreAttr = map[string]string{
    66  		"service": "name",
    67  		"healthy": "health_status",
    68  	}
    69  	// NotInsFilterAttr 不属于 instance 表属性的字段
    70  	NotInsFilterAttr = map[string]bool{
    71  		"keys":   true,
    72  		"values": true,
    73  	}
    74  )
    75  
    76  // CreateInstances 批量创建服务实例
    77  func (s *Server) CreateInstances(ctx context.Context, reqs []*apiservice.Instance) *apiservice.BatchWriteResponse {
    78  	if checkError := checkBatchInstance(reqs); checkError != nil {
    79  		return checkError
    80  	}
    81  
    82  	return batchOperateInstances(ctx, reqs, s.CreateInstance)
    83  }
    84  
    85  // CreateInstance create a single service instance
    86  func (s *Server) CreateInstance(ctx context.Context, req *apiservice.Instance) *apiservice.Response {
    87  	rid := utils.ParseRequestID(ctx)
    88  	pid := utils.ParsePlatformID(ctx)
    89  	start := time.Now()
    90  	instanceID, checkError := checkCreateInstance(req)
    91  	if checkError != nil {
    92  		return checkError
    93  	}
    94  	// Restricted Instance frequently registered
    95  	if ok := s.allowInstanceAccess(instanceID); !ok {
    96  		log.Error("create instance not allowed to access: exceed ratelimit",
    97  			utils.ZapRequestID(rid), utils.ZapPlatformID(pid), utils.ZapInstanceID(instanceID))
    98  		return api.NewInstanceResponse(apimodel.Code_InstanceTooManyRequests, req)
    99  	}
   100  
   101  	// Prevent pollution api.Instance struct, copy and fill token
   102  	ins := *req
   103  	ins.ServiceToken = utils.NewStringValue(parseInstanceReqToken(ctx, req))
   104  	ins.Id = utils.NewStringValue(instanceID)
   105  	data, resp := s.createInstance(ctx, req, &ins)
   106  	if resp != nil {
   107  		return resp
   108  	}
   109  
   110  	msg := fmt.Sprintf("create instance: id=%v, namespace=%v, service=%v, host=%v, port=%v",
   111  		ins.GetId().GetValue(), req.GetNamespace().GetValue(), req.GetService().GetValue(),
   112  		req.GetHost().GetValue(), req.GetPort().GetValue())
   113  	log.Info(msg, utils.ZapRequestID(rid), utils.ZapPlatformID(pid), zap.Duration("cost", time.Since(start)))
   114  	svc := &model.Service{
   115  		Name:      req.GetService().GetValue(),
   116  		Namespace: req.GetNamespace().GetValue(),
   117  	}
   118  	instanceProto := data.Proto
   119  	event := &model.InstanceEvent{
   120  		Id:         instanceID,
   121  		Namespace:  svc.Namespace,
   122  		Service:    svc.Name,
   123  		Instance:   instanceProto,
   124  		EType:      model.EventInstanceOnline,
   125  		CreateTime: time.Time{},
   126  	}
   127  	event.InjectMetadata(ctx)
   128  	s.sendDiscoverEvent(*event)
   129  	s.RecordHistory(ctx, instanceRecordEntry(ctx, req, svc, data, model.OCreate))
   130  	out := &apiservice.Instance{
   131  		Id:        ins.GetId(),
   132  		Service:   &wrappers.StringValue{Value: svc.Name},
   133  		Namespace: &wrappers.StringValue{Value: svc.Namespace},
   134  		VpcId:     instanceProto.GetVpcId(),
   135  		Host:      instanceProto.GetHost(),
   136  		Port:      instanceProto.GetPort(),
   137  	}
   138  	return api.NewInstanceResponse(apimodel.Code_ExecuteSuccess, out)
   139  }
   140  
   141  // createInstance store operate
   142  func (s *Server) createInstance(ctx context.Context, req *apiservice.Instance, ins *apiservice.Instance) (
   143  	*model.Instance, *apiservice.Response) {
   144  	// create service if absent
   145  	svcId, errResp := s.createWrapServiceIfAbsent(ctx, req)
   146  	if errResp != nil {
   147  		log.Errorf("[Instance] create service if absent fail : %+v, req : %+v", errResp.String(), req)
   148  		return nil, errResp
   149  	}
   150  	if len(svcId) == 0 {
   151  		log.Errorf("[Instance] create service if absent return service id is empty : %+v", req)
   152  		return nil, api.NewResponseWithMsg(apimodel.Code_BadRequest, "service id is empty")
   153  	}
   154  
   155  	// fill instance location info
   156  	s.packCmdb(ins)
   157  
   158  	if namingServer.bc == nil || !namingServer.bc.CreateInstanceOpen() {
   159  		return s.serialCreateInstance(ctx, svcId, req, ins) // 单个同步
   160  	}
   161  	return s.asyncCreateInstance(ctx, svcId, req, ins) // 批量异步
   162  }
   163  
   164  // asyncCreateInstance 异步新建实例
   165  // 底层函数会合并create请求,增加并发创建的吞吐
   166  // req 原始请求
   167  // ins 包含了req数据与instanceID,serviceToken
   168  func (s *Server) asyncCreateInstance(
   169  	ctx context.Context, svcId string, req *apiservice.Instance, ins *apiservice.Instance) (
   170  	*model.Instance, *apiservice.Response) {
   171  	allowAsyncRegis, _ := ctx.Value(utils.ContextOpenAsyncRegis).(bool)
   172  	future := s.bc.AsyncCreateInstance(svcId, ins, !allowAsyncRegis)
   173  
   174  	if err := future.Wait(); err != nil {
   175  		if future.Code() == apimodel.Code_ExistedResource {
   176  			req.Id = utils.NewStringValue(ins.GetId().GetValue())
   177  		}
   178  		return nil, api.NewInstanceResponse(future.Code(), req)
   179  	}
   180  
   181  	return model.CreateInstanceModel(svcId, req), nil
   182  }
   183  
   184  // 同步串行创建实例
   185  // req为原始的请求体
   186  // ins包括了req的内容,并且填充了instanceID与serviceToken
   187  func (s *Server) serialCreateInstance(
   188  	ctx context.Context, svcId string, req *apiservice.Instance, ins *apiservice.Instance) (
   189  	*model.Instance, *apiservice.Response) {
   190  	rid := utils.ParseRequestID(ctx)
   191  	pid := utils.ParsePlatformID(ctx)
   192  
   193  	instance, err := s.storage.GetInstance(ins.GetId().GetValue())
   194  	if err != nil {
   195  		log.Error("[Instance] get instance from store",
   196  			utils.ZapRequestID(rid), utils.ZapPlatformID(pid), zap.Error(err))
   197  		return nil, api.NewInstanceResponse(commonstore.StoreCode2APICode(err), req)
   198  	}
   199  	// 如果存在,则替换实例的属性数据,但是需要保留用户设置的隔离状态,以免出现关键状态丢失
   200  	if instance != nil && ins.Isolate == nil {
   201  		ins.Isolate = instance.Proto.Isolate
   202  	}
   203  	// 直接同步创建服务实例
   204  	data := model.CreateInstanceModel(svcId, ins)
   205  	if err := s.storage.AddInstance(data); err != nil {
   206  		log.Error(err.Error(), utils.ZapRequestID(rid), utils.ZapPlatformID(pid))
   207  		return nil, wrapperInstanceStoreResponse(req, err)
   208  	}
   209  
   210  	return data, nil
   211  }
   212  
   213  // DeleteInstances 批量删除服务实例
   214  func (s *Server) DeleteInstances(ctx context.Context, req []*apiservice.Instance) *apiservice.BatchWriteResponse {
   215  	if checkError := checkBatchInstance(req); checkError != nil {
   216  		return checkError
   217  	}
   218  
   219  	return batchOperateInstances(ctx, req, s.DeleteInstance)
   220  }
   221  
   222  // DeleteInstance 删除单个服务实例
   223  func (s *Server) DeleteInstance(ctx context.Context, req *apiservice.Instance) *apiservice.Response {
   224  	rid := utils.ParseRequestID(ctx)
   225  	pid := utils.ParsePlatformID(ctx)
   226  
   227  	// 参数检查
   228  	instanceID, checkError := checkReviseInstance(req)
   229  	if checkError != nil {
   230  		return checkError
   231  	}
   232  	// 限制instance频繁反注册
   233  	if ok := s.allowInstanceAccess(instanceID); !ok {
   234  		log.Error("delete instance is not allow access", utils.ZapRequestID(rid), utils.ZapPlatformID(pid))
   235  		return api.NewInstanceResponse(apimodel.Code_InstanceTooManyRequests, req)
   236  	}
   237  
   238  	ins := *req // 防止污染外部的req
   239  	ins.Id = utils.NewStringValue(instanceID)
   240  	ins.ServiceToken = utils.NewStringValue(parseInstanceReqToken(ctx, req))
   241  	return s.deleteInstance(ctx, req, &ins)
   242  }
   243  
   244  // 删除实例的store操作
   245  // req 原始请求
   246  // ins 填充了instanceID与serviceToken
   247  func (s *Server) deleteInstance(
   248  	ctx context.Context, req *apiservice.Instance, ins *apiservice.Instance) *apiservice.Response {
   249  	if s.bc == nil || !s.bc.DeleteInstanceOpen() {
   250  		return s.serialDeleteInstance(ctx, req, ins)
   251  	}
   252  
   253  	return s.asyncDeleteInstance(ctx, req, ins)
   254  }
   255  
   256  // 串行删除实例
   257  // 返回实例所属的服务和resp
   258  func (s *Server) serialDeleteInstance(
   259  	ctx context.Context, req *apiservice.Instance, ins *apiservice.Instance) *apiservice.Response {
   260  	start := time.Now()
   261  	// 检查服务实例是否存在
   262  	rid := utils.ParseRequestID(ctx)
   263  	pid := utils.ParsePlatformID(ctx)
   264  	instance, err := s.storage.GetInstance(ins.GetId().GetValue())
   265  	if err != nil {
   266  		log.Error(err.Error(), utils.ZapRequestID(rid))
   267  		return api.NewInstanceResponse(commonstore.StoreCode2APICode(err), req)
   268  	}
   269  	if instance == nil {
   270  		// 实例不存在,则返回成功
   271  		return api.NewInstanceResponse(apimodel.Code_ExecuteSuccess, req)
   272  	}
   273  	// 鉴权
   274  	service, resp := s.instanceAuth(ctx, req, instance.ServiceID)
   275  	if resp != nil {
   276  		return resp
   277  	}
   278  
   279  	// 存储层操作
   280  	if err := s.storage.DeleteInstance(instance.ID()); err != nil {
   281  		log.Error(err.Error(), utils.ZapRequestID(rid), utils.ZapPlatformID(pid))
   282  		return wrapperInstanceStoreResponse(req, err)
   283  	}
   284  
   285  	msg := fmt.Sprintf("delete instance: id=%v, namespace=%v, service=%v, host=%v, port=%v",
   286  		instance.ID(), service.Namespace, service.Name, instance.Host(), instance.Port())
   287  	log.Info(msg, utils.ZapRequestID(rid), utils.ZapPlatformID(pid), zap.Duration("cost", time.Since(start)))
   288  	s.RecordHistory(ctx, instanceRecordEntry(ctx, req, service, instance, model.ODelete))
   289  	event := &model.InstanceEvent{
   290  		Id:         instance.ID(),
   291  		Namespace:  service.Namespace,
   292  		Service:    service.Name,
   293  		Instance:   instance.Proto,
   294  		EType:      model.EventInstanceOffline,
   295  		CreateTime: time.Time{},
   296  	}
   297  	event.InjectMetadata(ctx)
   298  	s.sendDiscoverEvent(*event)
   299  
   300  	return api.NewInstanceResponse(apimodel.Code_ExecuteSuccess, req)
   301  }
   302  
   303  // 异步删除实例
   304  // 返回实例所属的服务和resp
   305  func (s *Server) asyncDeleteInstance(
   306  	ctx context.Context, req *apiservice.Instance, ins *apiservice.Instance) *apiservice.Response {
   307  	start := time.Now()
   308  	rid := utils.ParseRequestID(ctx)
   309  	pid := utils.ParsePlatformID(ctx)
   310  	allowAsyncRegis, _ := ctx.Value(utils.ContextOpenAsyncRegis).(bool)
   311  	future := s.bc.AsyncDeleteInstance(ins, !allowAsyncRegis)
   312  	if err := future.Wait(); err != nil {
   313  		// 如果发现不存在资源,意味着实例已经被删除,直接返回成功
   314  		if future.Code() == apimodel.Code_NotFoundResource {
   315  			return api.NewInstanceResponse(apimodel.Code_ExecuteSuccess, req)
   316  		}
   317  		log.Error(err.Error(), utils.ZapRequestID(rid), utils.ZapPlatformID(pid))
   318  		return api.NewInstanceResponse(future.Code(), req)
   319  	}
   320  	instance := future.Instance()
   321  
   322  	// 打印本地日志与操作记录
   323  	msg := fmt.Sprintf("delete instance: id=%v, namespace=%v, service=%v, host=%v, port=%v",
   324  		instance.ID(), instance.Namespace(), instance.Service(), instance.Host(), instance.Port())
   325  	log.Info(msg, utils.ZapRequestID(rid), utils.ZapPlatformID(pid), zap.Duration("cost", time.Since(start)))
   326  	service := &model.Service{Name: instance.Service(), Namespace: instance.Namespace()}
   327  	s.RecordHistory(ctx, instanceRecordEntry(ctx, req, service, instance, model.ODelete))
   328  	event := &model.InstanceEvent{
   329  		Id:         instance.ID(),
   330  		Namespace:  service.Namespace,
   331  		Service:    service.Name,
   332  		Instance:   instance.Proto,
   333  		EType:      model.EventInstanceOffline,
   334  		CreateTime: time.Time{},
   335  	}
   336  	event.InjectMetadata(ctx)
   337  	s.sendDiscoverEvent(*event)
   338  
   339  	return api.NewInstanceResponse(apimodel.Code_ExecuteSuccess, req)
   340  }
   341  
   342  // DeleteInstancesByHost 根据host批量删除服务实例
   343  func (s *Server) DeleteInstancesByHost(
   344  	ctx context.Context, req []*apiservice.Instance) *apiservice.BatchWriteResponse {
   345  	if checkError := checkBatchInstance(req); checkError != nil {
   346  		return checkError
   347  	}
   348  
   349  	return batchOperateInstances(ctx, req, s.DeleteInstanceByHost)
   350  }
   351  
   352  // DeleteInstanceByHost 根据host删除服务实例
   353  func (s *Server) DeleteInstanceByHost(ctx context.Context, req *apiservice.Instance) *apiservice.Response {
   354  	requestID := utils.ParseRequestID(ctx)
   355  	platformID := utils.ParsePlatformID(ctx)
   356  
   357  	// 参数校验
   358  	if err := checkInstanceByHost(req); err != nil {
   359  		return err
   360  	}
   361  
   362  	// 获取实例
   363  	instances, service, err := s.getInstancesMainByService(ctx, req)
   364  	if err != nil {
   365  		return err
   366  	}
   367  
   368  	if instances == nil {
   369  		return api.NewInstanceResponse(apimodel.Code_ExecuteSuccess, req)
   370  	}
   371  
   372  	ids := make([]interface{}, 0, len(instances))
   373  	for _, instance := range instances {
   374  		ids = append(ids, instance.ID())
   375  	}
   376  
   377  	if err := s.storage.BatchDeleteInstances(ids); err != nil {
   378  		log.Error(err.Error(), utils.ZapRequestID(requestID), utils.ZapPlatformID(platformID))
   379  		return wrapperInstanceStoreResponse(req, err)
   380  	}
   381  
   382  	for _, instance := range instances {
   383  		msg := fmt.Sprintf("delete instance: id=%v, namespace=%v, service=%v, host=%v, port=%v",
   384  			instance.ID(), service.Namespace, service.Name, instance.Host(), instance.Port())
   385  		log.Info(msg, utils.ZapRequestID(requestID), utils.ZapPlatformID(platformID))
   386  		s.RecordHistory(ctx, instanceRecordEntry(ctx, req, service, instance, model.ODelete))
   387  		s.sendDiscoverEvent(model.InstanceEvent{
   388  			Id:         instance.ID(),
   389  			Namespace:  service.Namespace,
   390  			Service:    service.Name,
   391  			Instance:   instance.Proto,
   392  			EType:      model.EventInstanceOffline,
   393  			CreateTime: time.Time{},
   394  		})
   395  	}
   396  	return api.NewInstanceResponse(apimodel.Code_ExecuteSuccess, req)
   397  }
   398  
   399  // UpdateInstances 批量修改服务实例
   400  func (s *Server) UpdateInstances(ctx context.Context, req []*apiservice.Instance) *apiservice.BatchWriteResponse {
   401  	if checkError := checkBatchInstance(req); checkError != nil {
   402  		return checkError
   403  	}
   404  
   405  	return batchOperateInstances(ctx, req, s.UpdateInstance)
   406  }
   407  
   408  // UpdateInstance 修改单个服务实例
   409  func (s *Server) UpdateInstance(ctx context.Context, req *apiservice.Instance) *apiservice.Response {
   410  	service, instance, preErr := s.execInstancePreStep(ctx, req)
   411  	if preErr != nil {
   412  		return preErr
   413  	}
   414  	if err := checkMetadata(req.GetMetadata()); err != nil {
   415  		return api.NewInstanceResponse(apimodel.Code_InvalidMetadata, req)
   416  	}
   417  
   418  	// 修改
   419  	requestID := utils.ParseRequestID(ctx)
   420  	platformID := utils.ParsePlatformID(ctx)
   421  	log.Info(fmt.Sprintf("old instance: %+v", instance), utils.ZapRequestID(requestID), utils.ZapPlatformID(platformID))
   422  
   423  	var eventTypes map[model.InstanceEventType]bool
   424  	var needUpdate bool
   425  	// 存储层操作
   426  	if needUpdate, eventTypes = s.updateInstanceAttribute(req, instance); !needUpdate {
   427  		log.Info("update instance no data change, no need update",
   428  			utils.ZapRequestID(requestID), utils.ZapPlatformID(platformID), zap.String("instance", req.String()))
   429  		return api.NewInstanceResponse(apimodel.Code_NoNeedUpdate, req)
   430  	}
   431  	if err := s.storage.UpdateInstance(instance); err != nil {
   432  		log.Error(err.Error(), utils.ZapRequestID(requestID), utils.ZapPlatformID(platformID))
   433  		return wrapperInstanceStoreResponse(req, err)
   434  	}
   435  
   436  	msg := fmt.Sprintf("update instance: id=%v, namespace=%v, service=%v, host=%v, port=%v, healthy = %v",
   437  		instance.ID(), service.Namespace, service.Name, instance.Host(),
   438  		instance.Port(), instance.Healthy())
   439  	log.Info(msg, utils.ZapRequestID(requestID), utils.ZapPlatformID(platformID))
   440  	s.RecordHistory(ctx, instanceRecordEntry(ctx, req, service, instance, model.OUpdate))
   441  
   442  	for eventType := range eventTypes {
   443  		event := &model.InstanceEvent{
   444  			Id:         instance.ID(),
   445  			Namespace:  service.Namespace,
   446  			Service:    service.Name,
   447  			Instance:   instance.Proto,
   448  			EType:      eventType,
   449  			CreateTime: time.Time{},
   450  		}
   451  		event.InjectMetadata(ctx)
   452  		s.sendDiscoverEvent(*event)
   453  	}
   454  
   455  	for i := range s.instanceChains {
   456  		s.instanceChains[i].AfterUpdate(ctx, instance)
   457  	}
   458  
   459  	return api.NewInstanceResponse(apimodel.Code_ExecuteSuccess, req)
   460  }
   461  
   462  // UpdateInstancesIsolate 批量修改服务实例隔离状态
   463  // @note 必填参数为service+namespace+host
   464  func (s *Server) UpdateInstancesIsolate(
   465  	ctx context.Context, req []*apiservice.Instance) *apiservice.BatchWriteResponse {
   466  	if checkError := checkBatchInstance(req); checkError != nil {
   467  		return checkError
   468  	}
   469  
   470  	return batchOperateInstances(ctx, req, s.UpdateInstanceIsolate)
   471  }
   472  
   473  // UpdateInstanceIsolate 修改服务实例隔离状态
   474  // @note 必填参数为service+namespace+ip
   475  func (s *Server) UpdateInstanceIsolate(ctx context.Context, req *apiservice.Instance) *apiservice.Response {
   476  	requestID := utils.ParseRequestID(ctx)
   477  	platformID := utils.ParsePlatformID(ctx)
   478  
   479  	// 参数校验
   480  	if err := checkInstanceByHost(req); err != nil {
   481  		return err
   482  	}
   483  	if req.GetIsolate() == nil {
   484  		return api.NewInstanceResponse(apimodel.Code_InvalidInstanceIsolate, req)
   485  	}
   486  
   487  	// 获取实例
   488  	instances, service, err := s.getInstancesMainByService(ctx, req)
   489  	if err != nil {
   490  		return err
   491  	}
   492  	if instances == nil {
   493  		return api.NewInstanceResponse(apimodel.Code_NotFoundInstance, req)
   494  	}
   495  
   496  	// 判断是否需要更新
   497  	needUpdate := false
   498  	for _, instance := range instances {
   499  		if req.Isolate != nil && instance.Isolate() != req.GetIsolate().GetValue() {
   500  			needUpdate = true
   501  			break
   502  		}
   503  	}
   504  	if !needUpdate {
   505  		return api.NewInstanceResponse(apimodel.Code_NoNeedUpdate, req)
   506  	}
   507  
   508  	isolate := 0
   509  	if req.GetIsolate().GetValue() {
   510  		isolate = 1
   511  	}
   512  
   513  	ids := make([]interface{}, 0, len(instances))
   514  	for _, instance := range instances {
   515  		// 方便后续打印操作记录
   516  		instance.Proto.Isolate = req.GetIsolate()
   517  		ids = append(ids, instance.ID())
   518  	}
   519  
   520  	if err := s.storage.BatchSetInstanceIsolate(ids, isolate, utils.NewUUID()); err != nil {
   521  		log.Error(err.Error(), utils.ZapRequestID(requestID), utils.ZapPlatformID(platformID))
   522  		return wrapperInstanceStoreResponse(req, err)
   523  	}
   524  
   525  	for _, instance := range instances {
   526  		msg := fmt.Sprintf("update instance: id=%v, namespace=%v, service=%v, host=%v, port=%v, isolate=%v",
   527  			instance.ID(), service.Namespace, service.Name, instance.Host(), instance.Port(), instance.Isolate())
   528  		log.Info(msg, utils.ZapRequestID(requestID), utils.ZapPlatformID(platformID))
   529  		s.RecordHistory(ctx, instanceRecordEntry(ctx, req, service, instance, model.OUpdateIsolate))
   530  
   531  		// 比对下更新前后的 isolate 状态
   532  		if req.Isolate != nil && instance.Isolate() != req.Isolate.GetValue() {
   533  			eventType := model.EventInstanceCloseIsolate
   534  			if req.Isolate.GetValue() {
   535  				eventType = model.EventInstanceOpenIsolate
   536  			}
   537  			s.sendDiscoverEvent(model.InstanceEvent{
   538  				Id:         instance.ID(),
   539  				Namespace:  req.Namespace.GetValue(),
   540  				Service:    req.Service.GetValue(),
   541  				Instance:   instance.Proto,
   542  				EType:      eventType,
   543  				CreateTime: time.Time{},
   544  			})
   545  		}
   546  		instance.Proto.Isolate = utils.NewBoolValue(req.GetIsolate().GetValue())
   547  	}
   548  
   549  	for i := range s.instanceChains {
   550  		s.instanceChains[i].AfterUpdate(ctx, instances...)
   551  	}
   552  
   553  	return api.NewInstanceResponse(apimodel.Code_ExecuteSuccess, req)
   554  }
   555  
   556  /**
   557   * @brief 根据ip隔离和删除服务实例的参数检查
   558   */
   559  func checkInstanceByHost(req *apiservice.Instance) *apiservice.Response {
   560  	if req == nil {
   561  		return api.NewInstanceResponse(apimodel.Code_EmptyRequest, req)
   562  	}
   563  	if err := checkResourceName(req.GetService()); err != nil {
   564  		return api.NewInstanceResponse(apimodel.Code_InvalidServiceName, req)
   565  	}
   566  	if err := checkResourceName(req.GetNamespace()); err != nil {
   567  		return api.NewInstanceResponse(apimodel.Code_InvalidNamespaceName, req)
   568  	}
   569  	if err := checkInstanceHost(req.GetHost()); err != nil {
   570  		return api.NewInstanceResponse(apimodel.Code_InvalidInstanceHost, req)
   571  	}
   572  	return nil
   573  }
   574  
   575  /**
   576   * @brief 根据服务和host获取服务实例
   577   */
   578  func (s *Server) getInstancesMainByService(ctx context.Context, req *apiservice.Instance) (
   579  	[]*model.Instance, *model.Service, *apiservice.Response) {
   580  	requestID := utils.ParseRequestID(ctx)
   581  	platformID := utils.ParsePlatformID(ctx)
   582  
   583  	// 检查服务
   584  	// 这里获取的是源服务的token。如果是别名,service=nil
   585  	service, err := s.storage.GetSourceServiceToken(req.GetService().GetValue(), req.GetNamespace().GetValue())
   586  	if err != nil {
   587  		log.Error(err.Error(), utils.ZapRequestID(requestID), utils.ZapPlatformID(platformID))
   588  		return nil, nil, api.NewInstanceResponse(commonstore.StoreCode2APICode(err), req)
   589  	}
   590  	if service == nil {
   591  		return nil, nil, api.NewInstanceResponse(apimodel.Code_NotFoundService, req)
   592  	}
   593  
   594  	// 获取服务实例
   595  	instances, err := s.storage.GetInstancesMainByService(service.ID, req.GetHost().GetValue())
   596  	if err != nil {
   597  		log.Error(err.Error(), utils.ZapRequestID(requestID), utils.ZapPlatformID(platformID))
   598  		return nil, nil, api.NewInstanceResponse(commonstore.StoreCode2APICode(err), req)
   599  	}
   600  	return instances, service, nil
   601  }
   602  
   603  /**
   604   * @brief 修改服务属性
   605   */
   606  func (s *Server) updateInstanceAttribute(
   607  	req *apiservice.Instance, instance *model.Instance) (bool, map[model.InstanceEventType]bool) {
   608  	// #lizard forgives
   609  	instance.MallocProto()
   610  	needUpdate := false
   611  	insProto := instance.Proto
   612  	var updateEvents = make(map[model.InstanceEventType]bool)
   613  	if ok := utils.IsNotEqualMap(req.GetMetadata(), instance.Metadata()); ok {
   614  		insProto.Metadata = req.GetMetadata()
   615  		needUpdate = true
   616  		updateEvents[model.EventInstanceUpdate] = true
   617  	}
   618  
   619  	if ok := instanceLocationNeedUpdate(req.GetLocation(), instance.Proto.GetLocation()); ok {
   620  		insProto.Location = req.Location
   621  		needUpdate = true
   622  		updateEvents[model.EventInstanceUpdate] = true
   623  	}
   624  
   625  	if req.GetProtocol() != nil && req.GetProtocol().GetValue() != instance.Protocol() {
   626  		insProto.Protocol = req.GetProtocol()
   627  		needUpdate = true
   628  		updateEvents[model.EventInstanceUpdate] = true
   629  	}
   630  
   631  	if req.GetVersion() != nil && req.GetVersion().GetValue() != instance.Version() {
   632  		insProto.Version = req.GetVersion()
   633  		needUpdate = true
   634  		updateEvents[model.EventInstanceUpdate] = true
   635  	}
   636  
   637  	if req.GetPriority() != nil && req.GetPriority().GetValue() != instance.Priority() {
   638  		insProto.Priority = req.GetPriority()
   639  		needUpdate = true
   640  		updateEvents[model.EventInstanceUpdate] = true
   641  	}
   642  
   643  	if req.GetWeight() != nil && req.GetWeight().GetValue() != instance.Weight() {
   644  		insProto.Weight = req.GetWeight()
   645  		needUpdate = true
   646  		updateEvents[model.EventInstanceUpdate] = true
   647  	}
   648  
   649  	if req.GetHealthy() != nil && req.GetHealthy().GetValue() != instance.Healthy() {
   650  		insProto.Healthy = req.GetHealthy()
   651  		needUpdate = true
   652  		if req.Healthy.GetValue() {
   653  			updateEvents[model.EventInstanceTurnHealth] = true
   654  		} else {
   655  			updateEvents[model.EventInstanceTurnUnHealth] = true
   656  		}
   657  	}
   658  
   659  	if req.GetIsolate() != nil && req.GetIsolate().GetValue() != instance.Isolate() {
   660  		insProto.Isolate = req.GetIsolate()
   661  		needUpdate = true
   662  		if req.Isolate.GetValue() {
   663  			updateEvents[model.EventInstanceOpenIsolate] = true
   664  		} else {
   665  			updateEvents[model.EventInstanceCloseIsolate] = true
   666  		}
   667  	}
   668  
   669  	if req.GetLogicSet() != nil && req.GetLogicSet().GetValue() != instance.LogicSet() {
   670  		insProto.LogicSet = req.GetLogicSet()
   671  		needUpdate = true
   672  		updateEvents[model.EventInstanceUpdate] = true
   673  	}
   674  
   675  	if ok := updateHealthCheck(req, instance); ok {
   676  		needUpdate = true
   677  		updateEvents[model.EventInstanceUpdate] = true
   678  	}
   679  
   680  	// 每次更改,都要生成一个新的uuid
   681  	if needUpdate {
   682  		insProto.Revision = utils.NewStringValue(utils.NewUUID())
   683  	}
   684  
   685  	return needUpdate, updateEvents
   686  }
   687  
   688  func instanceLocationNeedUpdate(req *apimodel.Location, old *apimodel.Location) bool {
   689  	if req.GetRegion().GetValue() != old.GetRegion().GetValue() {
   690  		return true
   691  	}
   692  	if req.GetZone().GetValue() != old.GetZone().GetValue() {
   693  		return true
   694  	}
   695  	if req.GetCampus().GetValue() != old.GetCampus().GetValue() {
   696  		return true
   697  	}
   698  
   699  	return false
   700  }
   701  
   702  // 健康检查的更新
   703  func updateHealthCheck(req *apiservice.Instance, instance *model.Instance) bool {
   704  	needUpdate := false
   705  	insProto := instance.Proto
   706  	// health Check,healthCheck不能为空,且没有把enable_health_check置为false
   707  	if req.GetHealthCheck().GetHeartbeat() != nil &&
   708  		(req.GetEnableHealthCheck() == nil || req.GetEnableHealthCheck().GetValue()) {
   709  		// 如果数据库中实例原有是不打开健康检查,
   710  		// 那么一旦打开,status需置为false,等待一次心跳成功才能变成true
   711  		if !instance.EnableHealthCheck() {
   712  			// 需要重置healthy,则认为有变更
   713  			insProto.Healthy = utils.NewBoolValue(false)
   714  			insProto.EnableHealthCheck = utils.NewBoolValue(true)
   715  			needUpdate = true
   716  		}
   717  
   718  		ttl := req.GetHealthCheck().GetHeartbeat().GetTtl().GetValue()
   719  		if ttl == 0 || ttl > 60 {
   720  			ttl = DefaultTLL
   721  		}
   722  		if ttl != instance.HealthCheck().GetHeartbeat().GetTtl().GetValue() {
   723  			// ttl有变更
   724  			needUpdate = true
   725  		}
   726  		if apiservice.HealthCheck_HEARTBEAT != instance.HealthCheck().GetType() {
   727  			// health check type有变更
   728  			needUpdate = true
   729  		}
   730  		insProto.HealthCheck = req.GetHealthCheck()
   731  		insProto.HealthCheck.Type = apiservice.HealthCheck_HEARTBEAT
   732  		if insProto.HealthCheck.Heartbeat.Ttl == nil {
   733  			insProto.HealthCheck.Heartbeat.Ttl = utils.NewUInt32Value(0)
   734  		}
   735  		insProto.HealthCheck.Heartbeat.Ttl.Value = ttl
   736  	}
   737  
   738  	// update的时候,修改了enableHealthCheck的值
   739  	if req.GetEnableHealthCheck() != nil && !req.GetEnableHealthCheck().GetValue() {
   740  		if req.GetEnableHealthCheck().GetValue() != instance.EnableHealthCheck() {
   741  			needUpdate = true
   742  		}
   743  		if insProto.GetHealthCheck() != nil {
   744  			needUpdate = true
   745  		}
   746  
   747  		insProto.EnableHealthCheck = utils.NewBoolValue(false)
   748  		insProto.HealthCheck = nil
   749  	}
   750  
   751  	return needUpdate
   752  }
   753  
   754  // GetInstances 查询服务实例
   755  func (s *Server) GetInstances(ctx context.Context, query map[string]string) *apiservice.BatchQueryResponse {
   756  	// 对数据先进行提前处理一下
   757  	filters, metaFilter, batchErr := preGetInstances(query)
   758  	if batchErr != nil {
   759  		return batchErr
   760  	}
   761  	// 分页数据
   762  	offset, limit, err := utils.ParseOffsetAndLimit(filters)
   763  	if err != nil {
   764  		return api.NewBatchQueryResponse(apimodel.Code_InvalidParameter)
   765  	}
   766  
   767  	total, instances, err := s.Cache().Instance().QueryInstances(filters, metaFilter, offset, limit)
   768  	if err != nil {
   769  		log.Errorf("[Server][Instances][Query] instances store err: %s", err.Error())
   770  		return api.NewBatchQueryResponse(commonstore.StoreCode2APICode(err))
   771  	}
   772  
   773  	out := api.NewBatchQueryResponse(apimodel.Code_ExecuteSuccess)
   774  	out.Amount = utils.NewUInt32Value(total)
   775  	out.Size = utils.NewUInt32Value(uint32(len(instances)))
   776  
   777  	apiInstances := make([]*apiservice.Instance, 0, len(instances))
   778  	for _, instance := range instances {
   779  		svc, _ := s.loadServiceByID(instance.ServiceID)
   780  		if svc == nil {
   781  			continue
   782  		}
   783  		protoIns := copyOSSInstance(instance.Proto)
   784  		protoIns.Service = wrapperspb.String(svc.Name)
   785  		protoIns.Namespace = wrapperspb.String(svc.Namespace)
   786  		protoIns.ServiceToken = wrapperspb.String(svc.Token)
   787  		s.packCmdb(protoIns)
   788  		apiInstances = append(apiInstances, protoIns)
   789  	}
   790  	out.Instances = apiInstances
   791  
   792  	return out
   793  }
   794  
   795  var (
   796  	ignoreReturnOSSInstanceMetadata = map[string]struct{}{
   797  		"version":  {},
   798  		"protocol": {},
   799  		"region":   {},
   800  		"zone":     {},
   801  		"campus":   {},
   802  	}
   803  )
   804  
   805  func copyOSSInstance(instance *apiservice.Instance) *apiservice.Instance {
   806  	copyIns := &apiservice.Instance{
   807  		Id:                instance.Id,
   808  		Service:           instance.Service,
   809  		Namespace:         instance.Namespace,
   810  		VpcId:             instance.VpcId,
   811  		Host:              instance.Host,
   812  		Port:              instance.Port,
   813  		Protocol:          instance.Protocol,
   814  		Version:           instance.Version,
   815  		Priority:          instance.Priority,
   816  		Weight:            instance.Weight,
   817  		EnableHealthCheck: instance.EnableHealthCheck,
   818  		HealthCheck:       instance.HealthCheck,
   819  		Healthy:           instance.Healthy,
   820  		Isolate:           instance.Isolate,
   821  		Location:          instance.Location,
   822  		LogicSet:          instance.LogicSet,
   823  		Ctime:             instance.Ctime,
   824  		Mtime:             instance.Mtime,
   825  		Revision:          instance.Revision,
   826  		ServiceToken:      instance.ServiceToken,
   827  	}
   828  
   829  	copym := map[string]string{}
   830  	for k, v := range instance.Metadata {
   831  		if _, ok := ignoreReturnOSSInstanceMetadata[k]; ok {
   832  			continue
   833  		}
   834  		copym[k] = v
   835  	}
   836  
   837  	copyIns.Metadata = copym
   838  	return copyIns
   839  }
   840  
   841  // GetInstanceLabels 获取实例标签列表
   842  func (s *Server) GetInstanceLabels(ctx context.Context, query map[string]string) *apiservice.Response {
   843  	var (
   844  		serviceId string
   845  		namespace = DefaultNamespace
   846  	)
   847  
   848  	if val, ok := query["namespace"]; ok {
   849  		namespace = val
   850  	}
   851  
   852  	if service, ok := query["service"]; ok {
   853  		svc := s.Cache().Service().GetServiceByName(service, namespace)
   854  		if svc != nil {
   855  			serviceId = svc.ID
   856  		}
   857  	}
   858  
   859  	if id, ok := query["service_id"]; ok {
   860  		serviceId = id
   861  	}
   862  
   863  	if serviceId == "" {
   864  		resp := api.NewResponse(apimodel.Code_ExecuteSuccess)
   865  		resp.InstanceLabels = &apiservice.InstanceLabels{}
   866  		return resp
   867  	}
   868  
   869  	ret := s.Cache().Instance().GetInstanceLabels(serviceId)
   870  	resp := api.NewResponse(apimodel.Code_ExecuteSuccess)
   871  	resp.InstanceLabels = ret
   872  	return resp
   873  }
   874  
   875  // GetInstancesCount 查询总的服务实例,不带过滤条件的
   876  func (s *Server) GetInstancesCount(ctx context.Context) *apiservice.BatchQueryResponse {
   877  	count, err := s.storage.GetInstancesCount()
   878  	if err != nil {
   879  		log.Errorf("[Server][Instance][Count] storage get err: %s", err.Error())
   880  		return api.NewBatchQueryResponse(commonstore.StoreCode2APICode(err))
   881  	}
   882  
   883  	out := api.NewBatchQueryResponse(apimodel.Code_ExecuteSuccess)
   884  	out.Amount = utils.NewUInt32Value(count)
   885  	out.Instances = make([]*apiservice.Instance, 0)
   886  	return out
   887  }
   888  
   889  // update/delete instance前置条件
   890  func (s *Server) execInstancePreStep(ctx context.Context, req *apiservice.Instance) (
   891  	*model.Service, *model.Instance, *apiservice.Response) {
   892  	rid := utils.ParseRequestID(ctx)
   893  
   894  	// 参数检查
   895  	instanceID, checkError := checkReviseInstance(req)
   896  	if checkError != nil {
   897  		return nil, nil, checkError
   898  	}
   899  
   900  	// 检查服务实例是否存在
   901  	instance, err := s.storage.GetInstance(instanceID)
   902  	if err != nil {
   903  		log.Error("[Instance] get instance from store", utils.ZapRequestID(rid), utils.ZapInstanceID(instanceID),
   904  			zap.Error(err))
   905  		return nil, nil, api.NewInstanceResponse(commonstore.StoreCode2APICode(err), req)
   906  	}
   907  	if instance == nil {
   908  		return nil, nil, api.NewInstanceResponse(apimodel.Code_NotFoundInstance, req)
   909  	}
   910  
   911  	service, resp := s.instanceAuth(ctx, req, instance.ServiceID)
   912  	if resp != nil {
   913  		return nil, nil, resp
   914  	}
   915  
   916  	return service, instance, nil
   917  }
   918  
   919  // 实例鉴权
   920  func (s *Server) instanceAuth(ctx context.Context, req *apiservice.Instance, serviceID string) (
   921  	*model.Service, *apiservice.Response) {
   922  	service, err := s.storage.GetServiceByID(serviceID)
   923  	if err != nil {
   924  		log.Error(err.Error(), utils.ZapRequestID(utils.ParseRequestID(ctx)))
   925  		return nil, api.NewInstanceResponse(commonstore.StoreCode2APICode(err), req)
   926  	}
   927  	if service == nil {
   928  		return nil, api.NewInstanceResponse(apimodel.Code_NotFoundResource, req)
   929  	}
   930  
   931  	return service, nil
   932  }
   933  
   934  // 获取api.instance
   935  func (s *Server) getInstance(service *apiservice.Service, instance *apiservice.Instance) *apiservice.Instance {
   936  	out := &apiservice.Instance{
   937  		Id:                instance.GetId(),
   938  		Service:           service.GetName(),
   939  		Namespace:         service.GetNamespace(),
   940  		VpcId:             instance.GetVpcId(),
   941  		Host:              instance.GetHost(),
   942  		Port:              instance.GetPort(),
   943  		Protocol:          instance.GetProtocol(),
   944  		Version:           instance.GetVersion(),
   945  		Priority:          instance.GetPriority(),
   946  		Weight:            instance.GetWeight(),
   947  		EnableHealthCheck: instance.GetEnableHealthCheck(),
   948  		HealthCheck:       instance.GetHealthCheck(),
   949  		Healthy:           instance.GetHealthy(),
   950  		Isolate:           instance.GetIsolate(),
   951  		Location:          instance.GetLocation(),
   952  		Metadata:          instance.GetMetadata(),
   953  		LogicSet:          instance.GetLogicSet(),
   954  		Ctime:             instance.GetCtime(),
   955  		Mtime:             instance.GetMtime(),
   956  		Revision:          instance.GetRevision(),
   957  	}
   958  
   959  	s.packCmdb(out)
   960  	return out
   961  }
   962  
   963  // 获取cmdb
   964  func (s *Server) packCmdb(instance *apiservice.Instance) {
   965  	if s.cmdb == nil {
   966  		return
   967  	}
   968  	if instance == nil || !isEmptyLocation(instance.GetLocation()) {
   969  		return
   970  	}
   971  
   972  	location, err := s.cmdb.GetLocation(instance.GetHost().GetValue())
   973  	if err != nil {
   974  		log.Error("[Instance] pack cmdb info fail",
   975  			zap.String("namespace", instance.GetNamespace().GetValue()),
   976  			zap.String("service", instance.GetService().GetValue()),
   977  			zap.String("host", instance.GetHost().GetValue()),
   978  			zap.Uint32("port", instance.GetPort().GetValue()))
   979  		return
   980  	}
   981  	if location != nil {
   982  		instance.Location = location.Proto
   983  	}
   984  }
   985  
   986  func isEmptyLocation(loc *apimodel.Location) bool {
   987  	return loc == nil || (loc.GetRegion().GetValue() == "" &&
   988  		loc.GetZone().GetValue() == "" &&
   989  		loc.GetCampus().GetValue() == "")
   990  }
   991  
   992  func (s *Server) sendDiscoverEvent(event model.InstanceEvent) {
   993  	if event.Instance != nil {
   994  		// In order not to cause `panic` in cause multi-corporate data op, do deep copy
   995  		// event.Instance = proto.Clone(event.Instance).(*apiservice.Instance)
   996  	}
   997  	_ = eventhub.Publish(eventhub.InstanceEventTopic, event)
   998  }
   999  
  1000  type wrapSvcName interface {
  1001  	// GetService 获取服务名
  1002  	GetService() *wrappers.StringValue
  1003  	// GetNamespace 获取命名空间
  1004  	GetNamespace() *wrappers.StringValue
  1005  }
  1006  
  1007  type rawSvcName interface {
  1008  	// GetService 获取服务名
  1009  	GetService() string
  1010  	// GetNamespace 获取命名空间
  1011  	GetNamespace() string
  1012  }
  1013  
  1014  // createWrapServiceIfAbsent 如果服务不存在,则进行创建,并返回服务的ID信息
  1015  func (s *Server) createWrapServiceIfAbsent(ctx context.Context, instance wrapSvcName) (string, *apiservice.Response) {
  1016  	return s.createServiceIfAbsent(ctx, instance.GetNamespace().GetValue(), instance.GetService().GetValue())
  1017  }
  1018  
  1019  func (s *Server) createServiceIfAbsent(
  1020  	ctx context.Context, namespace string, svcName string) (string, *apiservice.Response) {
  1021  	svc, errResp := s.loadService(namespace, svcName)
  1022  	if errResp != nil {
  1023  		return "", errResp
  1024  	}
  1025  	if svc != nil {
  1026  		return svc.ID, nil
  1027  	}
  1028  	simpleService := &apiservice.Service{
  1029  		Name:      utils.NewStringValue(svcName),
  1030  		Namespace: utils.NewStringValue(namespace),
  1031  		Owners: func() *wrapperspb.StringValue {
  1032  			owner := utils.ParseOwnerID(ctx)
  1033  			if owner == "" {
  1034  				return utils.NewStringValue("Polaris")
  1035  			}
  1036  			return utils.NewStringValue(owner)
  1037  		}(),
  1038  	}
  1039  	key := fmt.Sprintf("%s:%s", simpleService.Namespace, simpleService.Name)
  1040  	ret, err, _ := s.createServiceSingle.Do(key, func() (interface{}, error) {
  1041  		resp := s.CreateService(ctx, simpleService)
  1042  		return resp, nil
  1043  	})
  1044  	if err != nil {
  1045  		return "", api.NewResponseWithMsg(apimodel.Code_ExecuteException, err.Error())
  1046  	}
  1047  	resp := ret.(*apiservice.Response)
  1048  	retCode := apimodel.Code(resp.GetCode().GetValue())
  1049  	if retCode != apimodel.Code_ExecuteSuccess && retCode != apimodel.Code_ExistedResource {
  1050  		return "", resp
  1051  	}
  1052  	svcId := resp.GetService().GetId().GetValue()
  1053  	return svcId, nil
  1054  }
  1055  
  1056  func (s *Server) loadService(namespace string, svcName string) (*model.Service, *apiservice.Response) {
  1057  	svc := s.caches.Service().GetServiceByName(svcName, namespace)
  1058  	if svc != nil {
  1059  		if svc.IsAlias() {
  1060  			return nil, api.NewResponseWithMsg(apimodel.Code_BadRequest, "service is alias")
  1061  		}
  1062  		return svc, nil
  1063  	}
  1064  	// 再走数据库查询一遍
  1065  	svc, err := s.storage.GetService(svcName, namespace)
  1066  	if err != nil {
  1067  		return nil, api.NewResponseWithMsg(commonstore.StoreCode2APICode(err), err.Error())
  1068  	}
  1069  	if svc != nil && svc.IsAlias() {
  1070  		return nil, api.NewResponseWithMsg(apimodel.Code_BadRequest, "service is alias")
  1071  	}
  1072  	return svc, nil
  1073  }
  1074  
  1075  func (s *Server) loadServiceByID(svcID string) (*model.Service, error) {
  1076  	svc := s.caches.Service().GetServiceByID(svcID)
  1077  	if svc != nil {
  1078  		if svc.IsAlias() {
  1079  			return nil, errors.New("service is alias")
  1080  		}
  1081  		return svc, nil
  1082  	}
  1083  
  1084  	// 再走数据库查询一遍
  1085  	svc, err := s.storage.GetServiceByID(svcID)
  1086  	if err != nil {
  1087  		return nil, err
  1088  	}
  1089  
  1090  	if svc != nil && svc.IsAlias() {
  1091  		return nil, errors.New("service is alias")
  1092  	}
  1093  
  1094  	return svc, nil
  1095  }
  1096  
  1097  /*
  1098   * @brief 检查批量请求
  1099   */
  1100  func checkBatchInstance(req []*apiservice.Instance) *apiservice.BatchWriteResponse {
  1101  	if len(req) == 0 {
  1102  		return api.NewBatchWriteResponse(apimodel.Code_EmptyRequest)
  1103  	}
  1104  
  1105  	if len(req) > MaxBatchSize {
  1106  		return api.NewBatchWriteResponse(apimodel.Code_BatchSizeOverLimit)
  1107  	}
  1108  
  1109  	return nil
  1110  }
  1111  
  1112  /*
  1113   * @brief 检查创建服务实例请求参数
  1114   */
  1115  func checkCreateInstance(req *apiservice.Instance) (string, *apiservice.Response) {
  1116  	if req == nil {
  1117  		return "", api.NewInstanceResponse(apimodel.Code_EmptyRequest, req)
  1118  	}
  1119  
  1120  	if err := checkMetadata(req.GetMetadata()); err != nil {
  1121  		return "", api.NewInstanceResponse(apimodel.Code_InvalidMetadata, req)
  1122  	}
  1123  
  1124  	// 检查字段长度是否大于DB中对应字段长
  1125  	err, notOk := CheckDbInstanceFieldLen(req)
  1126  	if notOk {
  1127  		return "", err
  1128  	}
  1129  
  1130  	return utils.CheckInstanceTetrad(req)
  1131  }
  1132  
  1133  /*
  1134   * @brief 检查删除/修改服务实例请求参数
  1135   */
  1136  func checkReviseInstance(req *apiservice.Instance) (string, *apiservice.Response) {
  1137  	if req == nil {
  1138  		return "", api.NewInstanceResponse(apimodel.Code_EmptyRequest, req)
  1139  	}
  1140  
  1141  	if req.GetId() != nil {
  1142  		if req.GetId().GetValue() == "" {
  1143  			return "", api.NewInstanceResponse(apimodel.Code_InvalidInstanceID, req)
  1144  		}
  1145  		return req.GetId().GetValue(), nil
  1146  	}
  1147  
  1148  	// 检查字段长度是否大于DB中对应字段长
  1149  	err, notOk := CheckDbInstanceFieldLen(req)
  1150  	if notOk {
  1151  		return "", err
  1152  	}
  1153  
  1154  	return utils.CheckInstanceTetrad(req)
  1155  }
  1156  
  1157  /*
  1158   * @brief 检查心跳实例请求参数
  1159   * 检查是否存在token,以及 id或者四元组
  1160   * 注意:心跳上报只允许从client上报,因此token只会存在req中
  1161   */
  1162  func checkHeartbeatInstance(req *apiservice.Instance) (string, *apiservice.Response) {
  1163  	if req == nil {
  1164  		return "", api.NewInstanceResponse(apimodel.Code_EmptyRequest, req)
  1165  	}
  1166  	if req.GetId() != nil {
  1167  		if req.GetId().GetValue() == "" {
  1168  			return "", api.NewInstanceResponse(apimodel.Code_InvalidInstanceID, req)
  1169  		}
  1170  		return req.GetId().GetValue(), nil
  1171  	}
  1172  	return utils.CheckInstanceTetrad(req)
  1173  }
  1174  
  1175  // 获取instance请求的token信息
  1176  func parseInstanceReqToken(ctx context.Context, req *apiservice.Instance) string {
  1177  	if reqToken := req.GetServiceToken().GetValue(); reqToken != "" {
  1178  		return reqToken
  1179  	}
  1180  
  1181  	return utils.ParseToken(ctx)
  1182  }
  1183  
  1184  // 实例查询前置处理
  1185  func preGetInstances(query map[string]string) (map[string]string, map[string]string, *apiservice.BatchQueryResponse) {
  1186  	// 不允许全量查询服务实例
  1187  	if len(query) == 0 {
  1188  		return nil, nil, api.NewBatchQueryResponse(apimodel.Code_EmptyQueryParameter)
  1189  	}
  1190  
  1191  	var metaFilter map[string]string
  1192  	metaKey, metaKeyAvail := query["keys"]
  1193  	metaValue, metaValueAvail := query["values"]
  1194  	if metaKeyAvail != metaValueAvail {
  1195  		return nil, nil, api.NewBatchQueryResponseWithMsg(
  1196  			apimodel.Code_InvalidQueryInsParameter, "instance metadata key and value must be both provided")
  1197  	}
  1198  	if metaKeyAvail {
  1199  		metaFilter = map[string]string{metaKey: metaValue}
  1200  	}
  1201  
  1202  	// 以healthy为准
  1203  	_, lhs := query["health_status"]
  1204  	_, rhs := query["healthy"]
  1205  	if lhs && rhs {
  1206  		delete(query, "health_status")
  1207  	}
  1208  
  1209  	filters := make(map[string]string)
  1210  	for key, value := range query {
  1211  		if _, ok := InstanceFilterAttributes[key]; !ok {
  1212  			log.Errorf("[Server][Instance][Query] attribute(%s) is not allowed", key)
  1213  			return nil, metaFilter, api.NewBatchQueryResponseWithMsg(
  1214  				apimodel.Code_InvalidParameter, key+" is not allowed")
  1215  		}
  1216  
  1217  		if value == "" {
  1218  			log.Errorf("[Server][Instance][Query] attribute(%s: %s) is not allowed empty", key, value)
  1219  			return nil, metaFilter, api.NewBatchQueryResponseWithMsg(
  1220  				apimodel.Code_InvalidParameter, "the value for "+key+" is empty")
  1221  		}
  1222  		if attr, ok := InsFilter2toreAttr[key]; ok {
  1223  			key = attr
  1224  		}
  1225  		if !NotInsFilterAttr[key] {
  1226  			filters[key] = value
  1227  		}
  1228  	}
  1229  
  1230  	return filters, metaFilter, nil
  1231  }
  1232  
  1233  // 批量操作实例
  1234  func batchOperateInstances(ctx context.Context, reqs []*apiservice.Instance,
  1235  	handler func(ctx context.Context, req *apiservice.Instance) *apiservice.Response) *apiservice.BatchWriteResponse {
  1236  	responses := api.NewBatchWriteResponse(apimodel.Code_ExecuteSuccess)
  1237  
  1238  	chs := make([]chan *apiservice.Response, 0, len(reqs))
  1239  	for i, instance := range reqs {
  1240  		chs = append(chs, make(chan *apiservice.Response))
  1241  		go func(index int, ins *apiservice.Instance) {
  1242  			chs[index] <- handler(ctx, ins)
  1243  		}(i, instance)
  1244  	}
  1245  
  1246  	for _, ch := range chs {
  1247  		resp := <-ch
  1248  		api.Collect(responses, resp)
  1249  	}
  1250  
  1251  	return api.FormatBatchWriteResponse(responses)
  1252  }
  1253  
  1254  // wrapper instance store response
  1255  func wrapperInstanceStoreResponse(instance *apiservice.Instance, err error) *apiservice.Response {
  1256  	resp := storeError2Response(err)
  1257  	if resp == nil {
  1258  		return nil
  1259  	}
  1260  
  1261  	resp.Instance = instance
  1262  	return resp
  1263  }
  1264  
  1265  // 生成instance的记录entry
  1266  func instanceRecordEntry(ctx context.Context, req *apiservice.Instance, service *model.Service, ins *model.Instance,
  1267  	opt model.OperationType) *model.RecordEntry {
  1268  	if service == nil || ins == nil {
  1269  		return nil
  1270  	}
  1271  	marshaler := jsonpb.Marshaler{}
  1272  	datail, _ := marshaler.MarshalToString(req)
  1273  	entry := &model.RecordEntry{
  1274  		ResourceType:  model.RInstance,
  1275  		ResourceName:  fmt.Sprintf("%s(%s:%d)", service.Name, ins.Host(), ins.Port()),
  1276  		Namespace:     service.Namespace,
  1277  		OperationType: opt,
  1278  		Operator:      utils.ParseOperator(ctx),
  1279  		Detail:        datail,
  1280  		HappenTime:    time.Now(),
  1281  	}
  1282  	return entry
  1283  }
  1284  
  1285  // CheckDbInstanceFieldLen 检查DB中service表对应的入参字段合法性
  1286  func CheckDbInstanceFieldLen(req *apiservice.Instance) (*apiservice.Response, bool) {
  1287  	if err := utils.CheckDbStrFieldLen(req.GetService(), MaxDbServiceNameLength); err != nil {
  1288  		return api.NewInstanceResponse(apimodel.Code_InvalidServiceName, req), true
  1289  	}
  1290  	if err := utils.CheckDbStrFieldLen(req.GetNamespace(), MaxDbServiceNamespaceLength); err != nil {
  1291  		return api.NewInstanceResponse(apimodel.Code_InvalidNamespaceName, req), true
  1292  	}
  1293  	if err := utils.CheckDbStrFieldLen(req.GetHost(), MaxDbInsHostLength); err != nil {
  1294  		return api.NewInstanceResponse(apimodel.Code_InvalidInstanceHost, req), true
  1295  	}
  1296  	if err := utils.CheckDbStrFieldLen(req.GetProtocol(), MaxDbInsProtocolLength); err != nil {
  1297  		return api.NewInstanceResponse(apimodel.Code_InvalidInstanceProtocol, req), true
  1298  	}
  1299  	if err := utils.CheckDbStrFieldLen(req.GetVersion(), MaxDbInsVersionLength); err != nil {
  1300  		return api.NewInstanceResponse(apimodel.Code_InvalidInstanceVersion, req), true
  1301  	}
  1302  	if err := utils.CheckDbStrFieldLen(req.GetLogicSet(), MaxDbInsLogicSetLength); err != nil {
  1303  		return api.NewInstanceResponse(apimodel.Code_InvalidInstanceLogicSet, req), true
  1304  	}
  1305  	if err := utils.CheckDbMetaDataFieldLen(req.GetMetadata()); err != nil {
  1306  		return api.NewInstanceResponse(apimodel.Code_InvalidMetadata, req), true
  1307  	}
  1308  	if req.GetPort().GetValue() > 65535 {
  1309  		return api.NewInstanceResponse(apimodel.Code_InvalidInstancePort, req), true
  1310  	}
  1311  
  1312  	if req.GetWeight().GetValue() > 65535 {
  1313  		return api.NewInstanceResponse(apimodel.Code_InvalidParameter, req), true
  1314  	}
  1315  	return nil, false
  1316  }