in datasource/etcd/ms.go [1428:1567]
func (ds *MetadataManager) UnregisterService(ctx context.Context, request *pb.DeleteServiceRequest) error {
serviceID := request.ServiceId
force := request.Force
remoteIP := util.GetIPFromContext(ctx)
domainProject := util.ParseDomainProject(ctx)
title := "delete"
if force {
title = "force delete"
}
if serviceID == core.Service.ServiceId {
err := errors.New("not allow to delete service center")
log.Error(fmt.Sprintf("%s micro-service[%s] failed, operator: %s", title, serviceID, remoteIP), err)
return pb.NewError(pb.ErrInvalidParams, err.Error())
}
microservice, err := eutil.GetService(ctx, domainProject, serviceID)
if err != nil {
if errors.Is(err, datasource.ErrNoData) {
log.Debug(fmt.Sprintf("service does not exist, %s micro-service[%s] failed, operator: %s",
title, serviceID, remoteIP))
return pb.NewError(pb.ErrServiceNotExists, "Service does not exist.")
}
log.Error(fmt.Sprintf("%s micro-service[%s] failed, get service file failed, operator: %s",
title, serviceID, remoteIP), err)
return pb.NewError(pb.ErrInternal, err.Error())
}
// 强制删除,则与该服务相关的信息删除,非强制删除: 如果作为该被依赖(作为provider,提供服务,且不是只存在自依赖)或者存在实例,则不能删除
if !force {
services, err := eutil.GetConsumerIds(ctx, domainProject, microservice)
if err != nil {
log.Error(fmt.Sprintf("delete micro-service[%s] failed, get service dependency failed, operator: %s",
serviceID, remoteIP), err)
return pb.NewError(pb.ErrInternal, err.Error())
}
if l := len(services); l > 1 || (l == 1 && services[0] != serviceID) {
log.Error(fmt.Sprintf("delete micro-service[%s] failed, other services[%d] depend on it, operator: %s",
serviceID, l, remoteIP), nil)
return pb.NewError(pb.ErrDependedOnConsumer, "Can not delete this service, other service rely it.")
}
instancesKey := path.GenerateInstanceKey(domainProject, serviceID, "")
rsp, err := sd.Instance().Search(ctx,
etcdadpt.WithStrKey(instancesKey),
etcdadpt.WithPrefix(),
etcdadpt.WithCountOnly())
if err != nil {
log.Error(fmt.Sprintf("delete micro-service[%s] failed, get instances failed, operator: %s",
serviceID, remoteIP), err)
return pb.NewError(pb.ErrUnavailableBackend, err.Error())
}
if rsp.Count > 0 {
log.Error(fmt.Sprintf("delete micro-service[%s] failed, service deployed instances[%d], operator: %s",
serviceID, rsp.Count, remoteIP), nil)
return pb.NewError(pb.ErrDeployedInstance, "Can not delete the service deployed instance(s).")
}
}
serviceIDKey := path.GenerateServiceKey(domainProject, serviceID)
serviceKey := &pb.MicroServiceKey{
Tenant: domainProject,
Environment: microservice.Environment,
AppId: microservice.AppId,
ServiceName: microservice.ServiceName,
Version: microservice.Version,
Alias: microservice.Alias,
}
opts := []etcdadpt.OpOptions{
etcdadpt.OpDel(etcdadpt.WithStrKey(path.GenerateServiceIndexKey(serviceKey))),
etcdadpt.OpDel(etcdadpt.WithStrKey(path.GenerateServiceAliasKey(serviceKey))),
etcdadpt.OpDel(etcdadpt.WithStrKey(serviceIDKey)),
}
syncOpts, err := esync.GenDeleteOpts(ctx, datasource.ResourceService, serviceID,
&pb.DeleteServiceRequest{ServiceId: serviceID, Force: force})
if err != nil {
log.Error("fail to sync opt", err)
return pb.NewError(pb.ErrInternal, err.Error())
}
opts = append(opts, syncOpts...)
//删除依赖规则
optDeleteDep, err := eutil.DeleteDependencyForDeleteService(domainProject, serviceID, serviceKey)
if err != nil {
log.Error(fmt.Sprintf("%s micro-service[%s] failed, delete dependency failed, operator: %s",
title, serviceID, remoteIP), err)
return pb.NewError(pb.ErrInternal, err.Error())
}
opts = append(opts, optDeleteDep)
//删除schemas
opts = append(opts, etcdadpt.OpDel(
etcdadpt.WithStrKey(path.GenerateServiceSchemaKey(domainProject, serviceID, "")),
etcdadpt.WithPrefix()))
opts = append(opts, etcdadpt.OpDel(
etcdadpt.WithStrKey(path.GenerateServiceSchemaSummaryKey(domainProject, serviceID, "")),
etcdadpt.WithPrefix()))
opts = append(opts, etcdadpt.OpDel(
etcdadpt.WithStrKey(path.GenerateServiceSchemaRefKey(domainProject, serviceID, "")),
etcdadpt.WithPrefix()))
//删除tags
opts = append(opts, etcdadpt.OpDel(
etcdadpt.WithStrKey(path.GenerateServiceTagKey(domainProject, serviceID))))
//删除instances
opts = append(opts, etcdadpt.OpDel(
etcdadpt.WithStrKey(path.GenerateInstanceKey(domainProject, serviceID, "")),
etcdadpt.WithPrefix()))
opts = append(opts, etcdadpt.OpDel(
etcdadpt.WithStrKey(path.GenerateInstanceLeaseKey(domainProject, serviceID, "")),
etcdadpt.WithPrefix()))
//删除实例
err = eutil.DeleteServiceAllInstances(ctx, serviceID)
if err != nil {
log.Error(fmt.Sprintf("%s micro-service[%s] failed, revoke all instances failed, operator: %s",
title, serviceID, remoteIP), err)
return pb.NewError(pb.ErrUnavailableBackend, err.Error())
}
resp, err := etcdadpt.TxnWithCmp(ctx, opts, etcdadpt.If(etcdadpt.NotEqualVer(serviceIDKey, 0)), nil)
if err != nil {
log.Error(fmt.Sprintf("%s micro-service[%s] failed, operator: %s", title, serviceID, remoteIP), err)
return pb.NewError(pb.ErrUnavailableBackend, err.Error())
}
if !resp.Succeeded {
log.Error(fmt.Sprintf("%s micro-service[%s] failed, service does not exist, operator: %s",
title, serviceID, remoteIP), err)
return pb.NewError(pb.ErrServiceNotExists, "Service does not exist.")
}
quotasvc.RemandService(ctx)
log.Info(fmt.Sprintf("%s micro-service[%s] successfully, operator: %s", title, serviceID, remoteIP))
return nil
}