You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by ti...@apache.org on 2020/12/15 02:01:21 UTC

[servicecomb-service-center] branch master updated: [SCB-2094] add dep UT, implement dep query interface (#776)

This is an automated email from the ASF dual-hosted git repository.

tianxiaoliang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-service-center.git


The following commit(s) were added to refs/heads/master by this push:
     new a0a2104  [SCB-2094] add dep UT, implement dep query interface (#776)
a0a2104 is described below

commit a0a2104115578c3e1baa28e1970e8fdfedfc4c06
Author: xzccfzy <50...@users.noreply.github.com>
AuthorDate: Tue Dec 15 10:01:12 2020 +0800

    [SCB-2094] add dep UT, implement dep query interface (#776)
---
 datasource/mongo/database.go         |   3 +
 datasource/mongo/dep.go              | 203 +--------------
 datasource/mongo/dep_test.go         | 484 ++++++++++++++++++++++++++---------
 datasource/mongo/dependency_query.go | 474 ++++++++++++++++++++++++++++++++++
 datasource/mongo/ms.go               |  58 +++--
 5 files changed, 877 insertions(+), 345 deletions(-)

diff --git a/datasource/mongo/database.go b/datasource/mongo/database.go
index 3bfdf25..9cbcfb5 100644
--- a/datasource/mongo/database.go
+++ b/datasource/mongo/database.go
@@ -76,6 +76,9 @@ const (
 	ColumnRuleInfo       = "ruleinfo"
 	ColumnInstanceInfo   = "instanceinfo"
 	ColumnInstanceID     = "instanceid"
+	ColumnConsumerID     = "consumerid"
+	ColumnMongoID        = "_id"
+	ColumnTenant         = "tenant"
 )
 
 type Service struct {
diff --git a/datasource/mongo/dep.go b/datasource/mongo/dep.go
index 6a1eef2..0566c5b 100644
--- a/datasource/mongo/dep.go
+++ b/datasource/mongo/dep.go
@@ -19,13 +19,11 @@ package mongo
 
 import (
 	"context"
+	"fmt"
 
 	pb "github.com/go-chassis/cari/discovery"
 	"go.mongodb.org/mongo-driver/bson"
 
-	"fmt"
-	"strings"
-
 	"github.com/apache/servicecomb-service-center/datasource"
 	"github.com/apache/servicecomb-service-center/datasource/mongo/client"
 	"github.com/apache/servicecomb-service-center/pkg/log"
@@ -33,6 +31,7 @@ import (
 )
 
 func (ds *DataSource) SearchProviderDependency(ctx context.Context, request *pb.GetDependenciesRequest) (*pb.GetProDependenciesResponse, error) {
+	domainProject := util.ParseDomainProject(ctx)
 	providerServiceID := request.ServiceId
 	filter := GeneratorServiceFilter(ctx, providerServiceID)
 	provider, err := GetService(ctx, filter)
@@ -47,7 +46,8 @@ func (ds *DataSource) SearchProviderDependency(ctx context.Context, request *pb.
 		}, nil
 	}
 
-	services, err := GetDependencyProviders(ctx, provider.ServiceInfo, request)
+	dr := NewProviderDependencyRelation(ctx, domainProject, provider.ServiceInfo)
+	services, err := dr.GetDependencyConsumers(ToDependencyFilterOptions(request)...)
 	if err != nil {
 		log.Error(fmt.Sprintf("GetProviderDependencies failed, provider is %s/%s/%s/%s",
 			provider.ServiceInfo.Environment, provider.ServiceInfo.AppId, provider.ServiceInfo.ServiceName, provider.ServiceInfo.Version), err)
@@ -63,6 +63,7 @@ func (ds *DataSource) SearchProviderDependency(ctx context.Context, request *pb.
 }
 
 func (ds *DataSource) SearchConsumerDependency(ctx context.Context, request *pb.GetDependenciesRequest) (*pb.GetConDependenciesResponse, error) {
+	domainProject := util.ParseDomainProject(ctx)
 	consumerID := request.ServiceId
 
 	filter := GeneratorServiceFilter(ctx, consumerID)
@@ -78,7 +79,8 @@ func (ds *DataSource) SearchConsumerDependency(ctx context.Context, request *pb.
 		}, nil
 	}
 
-	services, err := GetDependencyProviders(ctx, consumer.ServiceInfo, request)
+	dr := NewConsumerDependencyRelation(ctx, domainProject, consumer.ServiceInfo)
+	services, err := dr.GetDependencyProviders(ToDependencyFilterOptions(request)...)
 	if err != nil {
 		log.Error(fmt.Sprintf("GetConsumerDependencies failed, consumer is %s/%s/%s/%s",
 			consumer.ServiceInfo.Environment, consumer.ServiceInfo.AppId, consumer.ServiceInfo.ServiceName, consumer.ServiceInfo.Version), err)
@@ -152,197 +154,6 @@ func (ds *DataSource) DeleteDependency() {
 	panic("implement me")
 }
 
-func GetDependencyProviders(ctx context.Context, consumer *pb.MicroService, request *pb.GetDependenciesRequest) ([]*pb.MicroService, error) {
-	keys, err := GetProviderKeys(ctx, consumer)
-	if err != nil {
-		return nil, err
-	}
-
-	services := make([]*pb.MicroService, 0, len(keys))
-
-	for _, key := range keys {
-		domainProject := util.ParseDomainProject(ctx)
-		if request.SameDomain && key.Tenant != domainProject {
-			continue
-		}
-
-		providerIDs, err := ParseDependencyRule(ctx, key)
-		if err != nil {
-			return nil, err
-		}
-
-		if key.ServiceName == "*" {
-			services = services[:0]
-		}
-
-		for _, providerID := range providerIDs {
-			filter := GeneratorServiceFilter(ctx, providerID)
-			provider, err := GetService(ctx, filter)
-			if err != nil {
-				log.Warn(fmt.Sprintf("get provider[%s/%s/%s/%s] failed",
-					key.Environment, key.AppId, key.ServiceName, key.Version))
-				continue
-			}
-			if provider == nil {
-				log.Warn(fmt.Sprintf("provider[%s/%s/%s/%s] does not exist",
-					key.Environment, key.AppId, key.ServiceName, key.Version))
-				continue
-			}
-			if request.NoSelf && providerID == consumer.ServiceId {
-				continue
-			}
-			services = append(services, provider.ServiceInfo)
-		}
-
-		if key.ServiceName == "*" {
-			break
-		}
-	}
-
-	return services, nil
-}
-
-func GetProviderKeys(ctx context.Context, consumer *pb.MicroService) ([]*pb.MicroServiceKey, error) {
-	if consumer == nil {
-		return nil, ErrInvalidConsumer
-	}
-	domainProject := util.ParseDomainProject(ctx)
-	consumerMicroServiceKey := &pb.MicroServiceKey{
-		Tenant:      domainProject,
-		Environment: consumer.Environment,
-		AppId:       consumer.AppId,
-		ServiceName: consumer.ServiceName,
-		Alias:       consumer.Alias,
-		Version:     consumer.Version,
-	}
-
-	filter := GenerateConsumerDependencyRuleKey(ctx, consumerMicroServiceKey)
-
-	findRes, err := client.GetMongoClient().Find(ctx, CollectionDep, filter)
-	if err != nil {
-		return nil, err
-	}
-	var services []*pb.MicroServiceKey
-	for findRes.Next(ctx) {
-		var tempMongoDep Dependency
-		err := findRes.Decode(&tempMongoDep)
-		if err != nil {
-			return nil, err
-		}
-		providers := tempMongoDep.DependencyInfo.Providers
-		services = append(services, providers...)
-	}
-	return services, nil
-}
-
-func GenerateConsumerDependencyRuleKey(ctx context.Context, in *pb.MicroServiceKey) bson.M {
-
-	domain := util.ParseDomain(ctx)
-	project := util.ParseProject(ctx)
-	if in == nil {
-		return bson.M{
-			ColumnDomain:  domain,
-			ColumnProject: project,
-		}
-	}
-	if in.ServiceName == "*" {
-		return bson.M{
-			ColumnDomain:  domain,
-			ColumnProject: project,
-			StringBuilder([]string{ColumnDependencyInfo, ColumnConsumer, ColumnEnv}): in.Environment,
-		}
-	}
-	return bson.M{
-		ColumnDomain:  domain,
-		ColumnProject: project,
-		StringBuilder([]string{ColumnDependencyInfo, ColumnConsumer, ColumnEnv}):     in.Environment,
-		StringBuilder([]string{ColumnDependencyInfo, ColumnConsumer, ColumnAppID}):   in.AppId,
-		StringBuilder([]string{ColumnDependencyInfo, ColumnConsumer, ColumnVersion}): in.Version,
-	}
-}
-
-func ParseDependencyRule(ctx context.Context, dependencyRule *pb.MicroServiceKey) (serviceIDs []string, err error) {
-	switch {
-	case dependencyRule.ServiceName == "*":
-		splited := strings.Split(dependencyRule.Tenant, "/")
-		filter := bson.M{
-			ColumnDomain:  splited[0],
-			ColumnProject: splited[1],
-			StringBuilder([]string{ColumnServiceInfo, ColumnEnv}): dependencyRule.Environment}
-		findRes, err := client.GetMongoClient().Find(ctx, CollectionService, filter)
-		if err != nil {
-			return nil, err
-		}
-		for findRes.Next(ctx) {
-			var service Service
-			err = findRes.Decode(&service)
-			if err != nil {
-				return nil, err
-			}
-			serviceIDs = append(serviceIDs, service.ServiceInfo.ServiceId)
-		}
-	default:
-		serviceIDs, err = FindServiceIds(ctx, dependencyRule)
-	}
-	return
-}
-
-func FindServiceIds(ctx context.Context, key *pb.MicroServiceKey) ([]string, error) {
-	versionRule := key.Version
-	splited := strings.Split(key.Tenant, "/")
-	if len(versionRule) == 0 {
-		return nil, nil
-	}
-	rangeIdx := strings.Index(versionRule, "-")
-	switch {
-	case versionRule == "latest":
-		filter := bson.M{
-			ColumnDomain:  splited[0],
-			ColumnProject: splited[1]}
-		return GetFilterVersionService(ctx, filter)
-	case versionRule[len(versionRule)-1:] == "+":
-		start := versionRule[:len(versionRule)-1]
-		filter := bson.M{
-			ColumnDomain:  splited[0],
-			ColumnProject: splited[1],
-			StringBuilder([]string{ColumnServiceInfo, ColumnVersion}): bson.M{"$gte": start}}
-		return GetFilterVersionService(ctx, filter)
-	case rangeIdx > 0:
-		start := versionRule[:rangeIdx]
-		end := versionRule[rangeIdx+1:]
-		filter := bson.M{
-			ColumnDomain:  splited[0],
-			ColumnProject: splited[1],
-			StringBuilder([]string{ColumnServiceInfo, ColumnVersion}): bson.M{"$gts": start, "$lt": end}}
-		return GetFilterVersionService(ctx, filter)
-	default:
-		filter := bson.M{
-			ColumnDomain:  splited[0],
-			ColumnProject: splited[1],
-			StringBuilder([]string{ColumnServiceInfo, ColumnEnv}):         key.Environment,
-			StringBuilder([]string{ColumnServiceInfo, ColumnAppID}):       key.AppId,
-			StringBuilder([]string{ColumnServiceInfo, ColumnServiceName}): key.ServiceName,
-			StringBuilder([]string{ColumnServiceInfo, ColumnVersion}):     key.Version}
-		return GetFilterVersionService(ctx, filter)
-	}
-}
-
-func GetFilterVersionService(ctx context.Context, m bson.M) (serviceIDs []string, err error) {
-	findRes, err := client.GetMongoClient().Find(ctx, CollectionService, m)
-	if err != nil {
-		return nil, err
-	}
-	for findRes.Next(ctx) {
-		var service Service
-		err = findRes.Decode(&service)
-		if err != nil {
-			return nil, err
-		}
-		serviceIDs = append(serviceIDs, service.ServiceInfo.ServiceId)
-	}
-	return
-}
-
 func GetServiceID(ctx context.Context, key *pb.MicroServiceKey) (serviceID string, err error) {
 	domain := util.ParseDomain(ctx)
 	project := util.ParseProject(ctx)
diff --git a/datasource/mongo/dep_test.go b/datasource/mongo/dep_test.go
index 77bdc06..2b0f4fb 100644
--- a/datasource/mongo/dep_test.go
+++ b/datasource/mongo/dep_test.go
@@ -25,182 +25,237 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func TestDep_Creat(t *testing.T) {
-
+func Test_Creat(t *testing.T) {
 	var (
 		consumerId1 string
+		consumerId2 string
 		consumerId3 string
 	)
 
-	t.Run("creat service, when request is valid, should not pass", func(t *testing.T) {
-		respCreateService, err := datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+	t.Run("create service, should be passed", func(t *testing.T) {
+		resp, err := datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
 			Service: &pb.MicroService{
-				ServiceId:   "dep1",
-				AppId:       "create_dep_group",
-				ServiceName: "create_dep_consumer",
+				AppId:       "dep_create_dep_group",
+				ServiceName: "dep_create_dep_consumer",
 				Version:     "1.0.0",
 				Level:       "FRONT",
 				Status:      pb.MS_UP,
 			},
 		})
+		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, pb.ResponseSuccess, respCreateService.Response.GetCode())
-		consumerId1 = respCreateService.ServiceId
+		assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+		consumerId1 = resp.ServiceId
 
-		respCreateService, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+		resp, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
 			Service: &pb.MicroService{
-				ServiceId:   "dep2",
-				AppId:       "create_dep_group",
-				ServiceName: "create_dep_consumer_all",
+				AppId:       "dep_create_dep_group",
+				ServiceName: "dep_create_dep_consumer_all",
 				Version:     "1.0.0",
 				Level:       "FRONT",
 				Status:      pb.MS_UP,
 			},
 		})
+		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, pb.ResponseSuccess, respCreateService.Response.GetCode())
-		consumerId3 = respCreateService.ServiceId
+		assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+		consumerId3 = resp.ServiceId
 
-		respCreateService, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+		resp, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
 			Service: &pb.MicroService{
-				ServiceId:   "dep3",
 				Environment: pb.ENV_PROD,
-				AppId:       "create_dep_group",
-				ServiceName: "create_dep_consumer",
+				AppId:       "dep_create_dep_group",
+				ServiceName: "dep_create_dep_consumer",
 				Version:     "1.0.0",
 				Level:       "FRONT",
 				Status:      pb.MS_UP,
 			},
 		})
+		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, pb.ResponseSuccess, respCreateService.Response.GetCode())
+		assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+		consumerId2 = resp.ServiceId
 
-		respCreateService, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+		resp, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
 			Service: &pb.MicroService{
-				ServiceId:   "dep4",
-				AppId:       "create_dep_group",
-				ServiceName: "create_dep_provider",
+				AppId:       "dep_create_dep_group",
+				ServiceName: "dep_create_dep_provider",
 				Version:     "1.0.0",
 				Level:       "FRONT",
 				Status:      pb.MS_UP,
 			},
 		})
+		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, pb.ResponseSuccess, respCreateService.Response.GetCode())
+		assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
 
-		respCreateService, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+		resp, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
 			Service: &pb.MicroService{
-				ServiceId:   "dep5",
-				AppId:       "create_dep_group",
-				ServiceName: "create_dep_provider",
+				AppId:       "dep_create_dep_group",
+				ServiceName: "dep_create_dep_provider",
 				Version:     "1.0.1",
 				Level:       "FRONT",
 				Status:      pb.MS_UP,
 			},
 		})
+		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, pb.ResponseSuccess, respCreateService.Response.GetCode())
+		assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
 
-		respCreateService, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+		resp, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
 			Service: &pb.MicroService{
-				ServiceId:   "dep6",
 				Environment: pb.ENV_PROD,
-				AppId:       "create_dep_group",
-				ServiceName: "create_dep_provider",
+				AppId:       "dep_create_dep_group",
+				ServiceName: "dep_create_dep_provider",
 				Version:     "1.0.0",
 				Level:       "FRONT",
 				Status:      pb.MS_UP,
 			},
 		})
+		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, pb.ResponseSuccess, respCreateService.Response.GetCode())
+		assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
 	})
 
-	t.Run("create dep, when request is valid, should be passed", func(t *testing.T) {
+	t.Run("add dep and search, when request is invalid, should be failed", func(t *testing.T) {
+		consumer := &pb.MicroServiceKey{
+			AppId:       "dep_create_dep_group",
+			ServiceName: "dep_create_dep_consumer",
+			Version:     "1.0.0",
+		}
+		providers := []*pb.MicroServiceKey{
+			{
+				AppId:       "dep_create_dep_group",
+				ServiceName: "dep_create_dep_provider",
+				Version:     "1.0.0",
+			},
+		}
 
-		respCreateDependency, err := datasource.Instance().AddOrUpdateDependencies(getContext(), []*pb.ConsumerDependency{
+		// consumer does not exist
+		resp, err := datasource.Instance().AddOrUpdateDependencies(getContext(), []*pb.ConsumerDependency{
 			{
 				Consumer: &pb.MicroServiceKey{
-					ServiceName: "create_dep_consumer",
-					AppId:       "create_dep_group",
+					AppId:       "noexistapp",
+					ServiceName: "noexistservice",
 					Version:     "1.0.0",
 				},
+				Providers: providers,
+			},
+		}, false)
+		assert.NotNil(t, resp)
+		assert.NoError(t, err)
+		assert.Equal(t, pb.ErrServiceNotExists, resp.GetCode())
+
+		// provider in diff env
+		resp, err = datasource.Instance().AddOrUpdateDependencies(getContext(), []*pb.ConsumerDependency{
+			{
+				Consumer: consumer,
 				Providers: []*pb.MicroServiceKey{
 					{
-						AppId:       "create_dep_group",
-						ServiceName: "create_dep_provider",
+						Environment: pb.ENV_PROD,
+						AppId:       "dep_service_group_provider",
+						ServiceName: "dep_service_name_provider",
 						Version:     "latest",
 					},
 				},
 			},
 		}, false)
+		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, pb.ResponseSuccess, respCreateDependency.GetCode())
+		assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
 
-		respPro, err := datasource.Instance().SearchConsumerDependency(getContext(), &pb.GetDependenciesRequest{
+		// consumer in diff env
+		consumer.Environment = pb.ENV_PROD
+		resp, err = datasource.Instance().AddOrUpdateDependencies(getContext(), []*pb.ConsumerDependency{
+			{
+				Consumer: consumer,
+				Providers: []*pb.MicroServiceKey{
+					{
+						AppId:       "dep_service_group_provider",
+						ServiceName: "dep_service_name_provider",
+						Version:     "latest",
+					},
+				},
+			},
+		}, false)
+		assert.NotNil(t, resp)
+		assert.NoError(t, err)
+		assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
+
+		respCon, err := datasource.Instance().SearchConsumerDependency(getContext(), &pb.GetDependenciesRequest{
 			ServiceId: consumerId1,
 		})
+		assert.NotNil(t, respCon)
+		assert.NoError(t, err)
+
+		respCon, err = datasource.Instance().SearchConsumerDependency(getContext(), &pb.GetDependenciesRequest{
+			ServiceId: consumerId2,
+		})
+		assert.NotNil(t, respCon)
 		assert.NoError(t, err)
-		assert.Equal(t, pb.ResponseSuccess, respPro.Response.GetCode())
-		assert.NotEqual(t, "1.0.1", respPro.Providers[0].Version)
+	})
+
+	t.Run("add dep and search, when request is valid, should be passed", func(t *testing.T) {
+		consumer := &pb.MicroServiceKey{
+			ServiceName: "dep_create_dep_consumer",
+			AppId:       "dep_create_dep_group",
+			Version:     "1.0.0",
+		}
 
-		respCreateDependency, err = datasource.Instance().AddOrUpdateDependencies(getContext(), []*pb.ConsumerDependency{
+		// add latest
+		resp, err := datasource.Instance().AddOrUpdateDependencies(getContext(), []*pb.ConsumerDependency{
 			{
-				Consumer: &pb.MicroServiceKey{
-					ServiceName: "create_dep_consumer",
-					AppId:       "create_dep_group",
-					Version:     "1.0.0",
-				},
+				Consumer: consumer,
 				Providers: []*pb.MicroServiceKey{
 					{
-						AppId:       "create_dep_group",
-						ServiceName: "create_dep_provider",
-						Version:     "1.0.0+",
+						AppId:       "dep_create_dep_group",
+						ServiceName: "dep_create_dep_provider",
+						Version:     "latest",
 					},
 				},
 			},
 		}, false)
+		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, pb.ResponseSuccess, respCreateDependency.GetCode())
+		assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
 
-		respPro, err = datasource.Instance().SearchConsumerDependency(getContext(), &pb.GetDependenciesRequest{
+		respPro, err := datasource.Instance().SearchConsumerDependency(getContext(), &pb.GetDependenciesRequest{
 			ServiceId: consumerId1,
 		})
+		assert.NotNil(t, respPro)
 		assert.NoError(t, err)
-		assert.Equal(t, pb.ResponseSuccess, respPro.Response.GetCode())
-		assert.NotEqual(t, "1.0.1", respPro.Providers[0].Version)
+		assert.NotEqual(t, 0, len(respPro.Providers))
+		assert.Equal(t, "1.0.1", respPro.Providers[0].Version)
 
-		respCreateDependency, err = datasource.Instance().AddOrUpdateDependencies(getContext(), []*pb.ConsumerDependency{
+		// add 1.0.0+
+		resp, err = datasource.Instance().AddOrUpdateDependencies(getContext(), []*pb.ConsumerDependency{
 			{
-				Consumer: &pb.MicroServiceKey{
-					ServiceName: "create_dep_consumer",
-					AppId:       "create_dep_group",
-					Version:     "1.0.0",
-				},
+				Consumer: consumer,
 				Providers: []*pb.MicroServiceKey{
 					{
-						AppId:       "create_dep_group",
-						ServiceName: "create_dep_provider",
+						AppId:       "dep_create_dep_group",
+						ServiceName: "dep_create_dep_provider",
 						Version:     "1.0.0+",
 					},
 				},
 			},
 		}, false)
+		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, pb.ResponseSuccess, respCreateDependency.GetCode())
+		assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
 
 		respPro, err = datasource.Instance().SearchConsumerDependency(getContext(), &pb.GetDependenciesRequest{
 			ServiceId: consumerId1,
 		})
+		assert.NotNil(t, respPro)
 		assert.NoError(t, err)
-		assert.Equal(t, pb.ResponseSuccess, respPro.Response.GetCode())
-		assert.NotEqual(t, 2, len(respPro.Providers))
 
-		respCreateDependency, err = datasource.Instance().AddOrUpdateDependencies(getContext(), []*pb.ConsumerDependency{
+		// add *
+		resp, err = datasource.Instance().AddOrUpdateDependencies(getContext(), []*pb.ConsumerDependency{
 			{
 				Consumer: &pb.MicroServiceKey{
-					ServiceName: "create_dep_consumer_all",
-					AppId:       "create_dep_group",
+					ServiceName: "dep_create_dep_consumer_all",
+					AppId:       "dep_create_dep_group",
 					Version:     "1.0.0",
 				},
 				Providers: []*pb.MicroServiceKey{
@@ -210,40 +265,40 @@ func TestDep_Creat(t *testing.T) {
 				},
 			},
 		}, false)
+		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, pb.ResponseSuccess, respCreateDependency.GetCode())
+		assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
 
 		respPro, err = datasource.Instance().SearchConsumerDependency(getContext(), &pb.GetDependenciesRequest{
 			ServiceId: consumerId3,
 		})
+		assert.NotNil(t, respPro)
 		assert.NoError(t, err)
-		assert.Equal(t, pb.ResponseSuccess, respPro.Response.GetCode())
-		assert.NotEqual(t, 0, len(respPro.Providers))
+		assert.Equal(t, 0, len(respPro.Providers))
 
-		respCreateDependency, err = datasource.Instance().AddOrUpdateDependencies(getContext(), []*pb.ConsumerDependency{
+		// clean all
+		resp, err = datasource.Instance().AddOrUpdateDependencies(getContext(), []*pb.ConsumerDependency{
 			{
 				Consumer: &pb.MicroServiceKey{
-					ServiceName: "create_dep_consumer_all",
-					AppId:       "create_dep_group",
+					ServiceName: "dep_create_dep_consumer_all",
+					AppId:       "dep_create_dep_group",
 					Version:     "1.0.0",
 				},
 				Providers: nil,
 			},
 		}, false)
+		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, pb.ResponseSuccess, respCreateDependency.GetCode())
+		assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
 
-		respCreateDependency, err = datasource.Instance().AddOrUpdateDependencies(getContext(), []*pb.ConsumerDependency{
+		// add multiple providers
+		resp, err = datasource.Instance().AddOrUpdateDependencies(getContext(), []*pb.ConsumerDependency{
 			{
-				Consumer: &pb.MicroServiceKey{
-					ServiceName: "create_dep_consumer",
-					AppId:       "create_dep_group",
-					Version:     "1.0.0",
-				},
+				Consumer: consumer,
 				Providers: []*pb.MicroServiceKey{
 					{
-						AppId:       "create_dep_group",
-						ServiceName: "create_dep_provider",
+						AppId:       "dep_create_dep_group",
+						ServiceName: "dep_create_dep_provider",
 						Version:     "1.0.0",
 					},
 					{
@@ -252,100 +307,281 @@ func TestDep_Creat(t *testing.T) {
 				},
 			},
 		}, false)
+		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, pb.ResponseSuccess, respCreateDependency.GetCode())
+		assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
 
-		respCreateDependency, err = datasource.Instance().AddOrUpdateDependencies(getContext(), []*pb.ConsumerDependency{
+		// add 1.0.0-2.0.0 to override *
+		resp, err = datasource.Instance().AddOrUpdateDependencies(getContext(), []*pb.ConsumerDependency{
 			{
-				Consumer: &pb.MicroServiceKey{
-					ServiceName: "create_dep_consumer",
-					AppId:       "create_dep_group",
-					Version:     "1.0.0",
-				},
+				Consumer: consumer,
 				Providers: []*pb.MicroServiceKey{
 					{
-						AppId:       "create_dep_group",
-						ServiceName: "create_dep_provider",
+						AppId:       "dep_create_dep_group",
+						ServiceName: "dep_create_dep_provider",
 						Version:     "1.0.0-1.0.1",
 					},
 				},
 			},
 		}, false)
+		assert.NotNil(t, resp)
+		assert.NoError(t, err)
+		assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
+
+		respPro, err = datasource.Instance().SearchConsumerDependency(getContext(), &pb.GetDependenciesRequest{
+			ServiceId: consumerId1,
+		})
+		assert.NotNil(t, respPro)
+		assert.NoError(t, err)
+		assert.Equal(t, "1.0.1", respPro.Providers[0].Version)
+
+		// add not override
+		respAdd, err := datasource.Instance().AddOrUpdateDependencies(getContext(), []*pb.ConsumerDependency{
+			{
+				Consumer: consumer,
+				Providers: []*pb.MicroServiceKey{
+					{
+						AppId:       "dep_create_dep_group",
+						ServiceName: "dep_create_dep_provider",
+						Version:     "1.0.0-3.0.0",
+					},
+				},
+			},
+		}, false)
+		assert.NotNil(t, respAdd)
+		assert.NoError(t, err)
+		assert.Equal(t, pb.ResponseSuccess, respAdd.GetCode())
+
+		respPro, err = datasource.Instance().SearchConsumerDependency(getContext(), &pb.GetDependenciesRequest{
+			ServiceId: consumerId1,
+		})
+		assert.NotNil(t, respPro)
+		assert.NoError(t, err)
+
+		// add provider is empty
+		resp, err = datasource.Instance().AddOrUpdateDependencies(getContext(), []*pb.ConsumerDependency{
+			{
+				Consumer:  consumer,
+				Providers: []*pb.MicroServiceKey{},
+			},
+		}, false)
+		assert.NotNil(t, resp)
+		assert.NoError(t, err)
+		assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
+
+		resp, err = datasource.Instance().AddOrUpdateDependencies(getContext(), []*pb.ConsumerDependency{
+			{
+				Consumer: consumer,
+			},
+		}, false)
+		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, pb.ResponseSuccess, respCreateDependency.GetCode())
+		assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
 
 		respPro, err = datasource.Instance().SearchConsumerDependency(getContext(), &pb.GetDependenciesRequest{
 			ServiceId: consumerId1,
 		})
+		assert.NotNil(t, respPro)
 		assert.NoError(t, err)
-		assert.Equal(t, pb.ResponseSuccess, respPro.Response.GetCode())
-		assert.Equal(t, "1.0.0", respPro.Providers[0].Version)
 	})
 }
 
-func TestDep_Get(t *testing.T) {
-
+func Test_Get(t *testing.T) {
 	var (
 		consumerId1 string
 		providerId1 string
+		providerId2 string
 	)
 
-	t.Run("create service, when request is valid, should be passed", func(t *testing.T) {
-		respCreateService, err := datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+	t.Run("create service, should be passed", func(t *testing.T) {
+		resp, err := datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
 			Service: &pb.MicroService{
-				ServiceId:   "dep7",
-				AppId:       "get_dep_group",
-				ServiceName: "get_dep_consumer",
+				AppId:       "dep_get_dep_group",
+				ServiceName: "dep_get_dep_consumer",
 				Version:     "1.0.0",
 				Level:       "FRONT",
 				Status:      pb.MS_UP,
 			},
 		})
+		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, pb.ResponseSuccess, respCreateService.Response.GetCode())
-		consumerId1 = respCreateService.ServiceId
+		assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+		consumerId1 = resp.ServiceId
 
-		respCreateService, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+		resp, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
 			Service: &pb.MicroService{
-				ServiceId:   "dep8",
-				AppId:       "get_dep_group",
-				ServiceName: "get_dep_provider",
+				AppId:       "dep_get_dep_group",
+				ServiceName: "dep_get_dep_provider",
 				Version:     "1.0.0",
 				Level:       "FRONT",
 				Status:      pb.MS_UP,
 			},
 		})
+		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, pb.ResponseSuccess, respCreateService.Response.GetCode())
-		providerId1 = respCreateService.ServiceId
+		assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+		providerId1 = resp.ServiceId
 
-		respCreateService, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+		resp, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
 			Service: &pb.MicroService{
-				ServiceId:   "dep9",
-				AppId:       "get_dep_group",
-				ServiceName: "get_dep_provider",
+				AppId:       "dep_get_dep_group",
+				ServiceName: "dep_get_dep_provider",
 				Version:     "2.0.0",
 				Level:       "FRONT",
 				Status:      pb.MS_UP,
 			},
 		})
+		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, pb.ResponseSuccess, respCreateService.Response.GetCode())
+		assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+		providerId2 = resp.ServiceId
 	})
 
-	t.Run("execute 'search dep' operation, when request is valid,should be passed", func(t *testing.T) {
-		respPro, err := datasource.Instance().SearchProviderDependency(getContext(), &pb.GetDependenciesRequest{
+	t.Run("search dep, when request is valid, should be passed", func(t *testing.T) {
+		//get provider
+		resp, err := datasource.Instance().SearchProviderDependency(getContext(), &pb.GetDependenciesRequest{
 			ServiceId: providerId1,
 		})
+		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, pb.ResponseSuccess, respPro.Response.GetCode())
 
-		respCon, err := datasource.Instance().SearchConsumerDependency(getContext(), &pb.GetDependenciesRequest{
+		//get consumer
+		resp, err = datasource.Instance().SearchProviderDependency(getContext(), &pb.GetDependenciesRequest{
+			ServiceId: consumerId1,
+		})
+		assert.NotNil(t, resp)
+		assert.NoError(t, err)
+	})
+
+	t.Run("when after finding instance, should created dependencies between C and P", func(t *testing.T) {
+		// find provider
+		resp, err := datasource.Instance().FindInstances(getContext(), &pb.FindInstancesRequest{
+			ConsumerServiceId: consumerId1,
+			AppId:             "dep_get_dep_group",
+			ServiceName:       "dep_get_dep_provider",
+			VersionRule:       "1.0.0+",
+		})
+		assert.NotNil(t, resp)
+		assert.NoError(t, err)
+		assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+
+		// get consumer's deps
+		respGetP, err := datasource.Instance().SearchProviderDependency(getContext(), &pb.GetDependenciesRequest{
+			ServiceId: providerId1,
+		})
+		assert.NotNil(t, respGetP)
+		assert.NoError(t, err)
+
+		// get provider's deps
+		respGetC, err := datasource.Instance().SearchConsumerDependency(getContext(), &pb.GetDependenciesRequest{
+			ServiceId: consumerId1,
+		})
+		assert.NotNil(t, respGetC)
+		assert.NoError(t, err)
+
+		// get self deps
+		resp, err = datasource.Instance().FindInstances(getContext(), &pb.FindInstancesRequest{
+			ConsumerServiceId: consumerId1,
+			AppId:             "dep_get_dep_group",
+			ServiceName:       "dep_get_dep_consumer",
+			VersionRule:       "1.0.0+",
+		})
+		assert.NotNil(t, resp)
+		assert.NoError(t, err)
+		assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+
+		respGetC, err = datasource.Instance().SearchConsumerDependency(getContext(), &pb.GetDependenciesRequest{
 			ServiceId: consumerId1,
+			NoSelf:    true,
+		})
+		assert.NotNil(t, respGetC)
+		assert.NoError(t, err)
+
+		// find before provider register
+		resp, err = datasource.Instance().FindInstances(getContext(), &pb.FindInstancesRequest{
+			ConsumerServiceId: providerId2,
+			AppId:             "dep_get_dep_group",
+			ServiceName:       "dep_get_dep_finder",
+			VersionRule:       "1.0.0+",
+		})
+		assert.NotNil(t, resp)
+		assert.NoError(t, err)
+		assert.Equal(t, pb.ErrServiceNotExists, resp.Response.GetCode())
+
+		respCreateF, err := datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+			Service: &pb.MicroService{
+				AppId:       "dep_get_dep_group",
+				ServiceName: "dep_get_dep_finder",
+				Version:     "1.0.0",
+				Level:       "FRONT",
+				Status:      pb.MS_UP,
+			},
+		})
+		assert.NotNil(t, respCreateF)
+		assert.NoError(t, err)
+		assert.Equal(t, pb.ResponseSuccess, respCreateF.Response.GetCode())
+		finder1 := respCreateF.ServiceId
+
+		resp, err = datasource.Instance().FindInstances(getContext(), &pb.FindInstancesRequest{
+			ConsumerServiceId: providerId2,
+			AppId:             "dep_get_dep_group",
+			ServiceName:       "dep_get_dep_finder",
+			VersionRule:       "1.0.0+",
+		})
+		assert.NotNil(t, resp)
+		assert.NoError(t, err)
+		assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+
+		respGetC, err = datasource.Instance().SearchConsumerDependency(getContext(), &pb.GetDependenciesRequest{
+			ServiceId: providerId2,
+		})
+		assert.NotNil(t, respGetC)
+		assert.NoError(t, err)
+
+		// find after delete micro service
+		respDelP, err := datasource.Instance().UnregisterService(getContext(), &pb.DeleteServiceRequest{
+			ServiceId: finder1, Force: true,
+		})
+		assert.NotNil(t, respDelP)
+		assert.NoError(t, err)
+		assert.Equal(t, pb.ResponseSuccess, respDelP.Response.GetCode())
+
+		respGetC, err = datasource.Instance().SearchConsumerDependency(getContext(), &pb.GetDependenciesRequest{
+			ServiceId: providerId2,
+		})
+		assert.NotNil(t, respGetC)
+		assert.NoError(t, err)
+		assert.Equal(t, 0, len(respGetC.Providers))
+
+		respCreateF, err = datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+			Service: &pb.MicroService{
+				ServiceId:   finder1,
+				AppId:       "dep_get_dep_group",
+				ServiceName: "dep_get_dep_finder",
+				Version:     "1.0.0",
+				Level:       "FRONT",
+				Status:      pb.MS_UP,
+			},
 		})
+		assert.NotNil(t, respCreateF)
+		assert.NoError(t, err)
+		assert.Equal(t, pb.ResponseSuccess, respCreateF.Response.GetCode())
 
+		resp, err = datasource.Instance().FindInstances(getContext(), &pb.FindInstancesRequest{
+			ConsumerServiceId: providerId2,
+			AppId:             "dep_get_dep_group",
+			ServiceName:       "dep_get_dep_finder",
+			VersionRule:       "1.0.0+",
+		})
+		assert.NotNil(t, resp)
 		assert.NoError(t, err)
-		assert.Equal(t, pb.ResponseSuccess, respCon.Response.GetCode())
+		assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
 
+		respGetC, err = datasource.Instance().SearchConsumerDependency(getContext(), &pb.GetDependenciesRequest{
+			ServiceId: providerId2,
+		})
+		assert.NotNil(t, respGetC)
+		assert.NoError(t, err)
+		assert.Equal(t, 0, len(respGetC.Providers))
 	})
 }
diff --git a/datasource/mongo/dependency_query.go b/datasource/mongo/dependency_query.go
new file mode 100644
index 0000000..8025aba
--- /dev/null
+++ b/datasource/mongo/dependency_query.go
@@ -0,0 +1,474 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package mongo
+
+import (
+	"context"
+	"fmt"
+	"strings"
+
+	"github.com/apache/servicecomb-service-center/datasource/mongo/client"
+	"github.com/apache/servicecomb-service-center/pkg/log"
+	pb "github.com/go-chassis/cari/discovery"
+	"go.mongodb.org/mongo-driver/bson"
+	"go.mongodb.org/mongo-driver/mongo/options"
+)
+
+type DependencyRelation struct {
+	ctx           context.Context
+	domainProject string
+	consumer      *pb.MicroService
+	provider      *pb.MicroService
+}
+
+type DependencyRelationFilterOpt struct {
+	SameDomainProject bool
+	NonSelf           bool
+}
+
+type DependencyRelationFilterOption func(opt DependencyRelationFilterOpt) DependencyRelationFilterOpt
+
+func NewConsumerDependencyRelation(ctx context.Context, domainProject string, consumer *pb.MicroService) *DependencyRelation {
+	return NewDependencyRelation(ctx, domainProject, consumer, nil)
+}
+
+func NewProviderDependencyRelation(ctx context.Context, domainProject string, provider *pb.MicroService) *DependencyRelation {
+	return NewDependencyRelation(ctx, domainProject, nil, provider)
+}
+
+func NewDependencyRelation(ctx context.Context, domainProject string, consumer *pb.MicroService, provider *pb.MicroService) *DependencyRelation {
+	return &DependencyRelation{
+		ctx:           ctx,
+		domainProject: domainProject,
+		consumer:      consumer,
+		provider:      provider,
+	}
+}
+
+func (dr *DependencyRelation) GetDependencyProviders(opts ...DependencyRelationFilterOption) ([]*pb.MicroService, error) {
+	keys, err := dr.getProviderKeys()
+	if err != nil {
+		return nil, err
+	}
+	services := make([]*pb.MicroService, 0, len(keys))
+	op := ToDependencyRelationFilterOpt(opts...)
+
+	for _, key := range keys {
+		if op.SameDomainProject && key.Tenant != dr.domainProject {
+			continue
+		}
+		providerIDs, err := dr.parseDependencyRule(key)
+
+		if err != nil {
+			return nil, err
+		}
+
+		if key.ServiceName == "*" {
+			services = services[:0]
+		}
+
+		for _, providerID := range providerIDs {
+			filter := GeneratorServiceFilter(dr.ctx, providerID)
+			provider, err := GetService(dr.ctx, filter)
+			if err != nil {
+				log.Warn(fmt.Sprintf("get provider[%s/%s/%s/%s] failed",
+					key.Environment, key.AppId, key.ServiceName, key.Version))
+				continue
+			}
+			if provider == nil {
+				log.Warn(fmt.Sprintf("provider[%s/%s/%s/%s] does not exist",
+					key.Environment, key.AppId, key.ServiceName, key.Version))
+				continue
+			}
+			if op.NonSelf && providerID == dr.consumer.ServiceId {
+				continue
+			}
+			services = append(services, provider.ServiceInfo)
+		}
+		if key.ServiceName == "*" {
+			break
+		}
+	}
+	return services, nil
+}
+
+func (dr *DependencyRelation) GetDependencyConsumers(opts ...DependencyRelationFilterOption) ([]*pb.MicroService, error) {
+	consumerDependAllList, err := dr.GetDependencyConsumersOfProvider()
+	if err != nil {
+		log.Error(fmt.Sprintf("get service[%s]'s consumers failed", dr.provider.ServiceId), err)
+		return nil, err
+	}
+	consumers := make([]*pb.MicroService, 0)
+	op := ToDependencyRelationFilterOpt(opts...)
+	for _, consumer := range consumerDependAllList {
+		if op.SameDomainProject && consumer.Tenant != dr.domainProject {
+			continue
+		}
+		service, err := dr.GetServiceByMicroServiceKey(consumer)
+		if err != nil {
+			return nil, err
+		}
+		if service == nil {
+			log.Warn(fmt.Sprintf("consumer[%s/%s/%s/%s] does not exist",
+				consumer.Environment, consumer.AppId, consumer.ServiceName, consumer.Version))
+			continue
+		}
+		if op.NonSelf && service.ServiceId == dr.provider.ServiceId {
+			continue
+		}
+		consumers = append(consumers, service)
+	}
+	return consumers, nil
+}
+
+func (dr *DependencyRelation) GetDependencyConsumersOfProvider() ([]*pb.MicroServiceKey, error) {
+	if dr.provider == nil {
+		return nil, ErrInvalidConsumer
+	}
+	consumerDependAllList, err := dr.getConsumerOfDependAllServices()
+	if err != nil {
+		log.Error(fmt.Sprintf("get consumers that depend on all services failed, %s", dr.provider.ServiceId), err)
+		return nil, err
+	}
+	return consumerDependAllList, nil
+}
+
+func (dr *DependencyRelation) GetServiceByMicroServiceKey(service *pb.MicroServiceKey) (*pb.MicroService, error) {
+	filter, err := MicroServiceKeyFilter(service)
+	if err != nil {
+		log.Error("get serivce failed", err)
+		return nil, err
+	}
+	findRes, err := client.GetMongoClient().Find(dr.ctx, CollectionService, filter)
+	if err != nil {
+		return nil, err
+	}
+	if findRes.Err() != nil {
+		return nil, findRes.Err()
+	}
+
+	for findRes.Next(dr.ctx) {
+		var service Service
+		err = findRes.Decode(&service)
+		if err != nil {
+			return nil, err
+		}
+		if service.ServiceInfo != nil {
+			return service.ServiceInfo, nil
+		}
+	}
+	return nil, nil
+}
+
+func (dr *DependencyRelation) getConsumerOfDependAllServices() ([]*pb.MicroServiceKey, error) {
+	providerService := pb.MicroServiceToKey(dr.domainProject, dr.provider)
+	providerService.ServiceName = "*"
+	filter := GenerateProviderDependencyRuleKey(dr.domainProject, dr.provider.ServiceId, providerService)
+	findRes, err := client.GetMongoClient().Find(dr.ctx, CollectionDep, filter)
+	if err != nil {
+		return nil, err
+	}
+	if findRes.Err() != nil {
+		return nil, findRes.Err()
+	}
+
+	var msKeys []*pb.MicroServiceKey
+	for findRes.Next(dr.ctx) {
+		var dep *Dependency
+		err = findRes.Decode(&dep)
+		if err != nil {
+			return nil, err
+		}
+		msKeys = append(msKeys, dep.DependencyInfo.Consumer)
+	}
+	return msKeys, nil
+}
+
+func (dr *DependencyRelation) getProviderKeys() ([]*pb.MicroServiceKey, error) {
+	if dr.consumer == nil {
+		return nil, ErrInvalidConsumer
+	}
+	consumerMicroServiceKey := pb.MicroServiceToKey(dr.domainProject, dr.consumer)
+	filter := GenerateConsumerDependencyRuleKey(dr.domainProject, dr.consumer.ServiceId, consumerMicroServiceKey)
+	findRes, err := client.GetMongoClient().Find(dr.ctx, CollectionDep, filter)
+	if err != nil {
+		return nil, err
+	}
+	if findRes.Err() != nil {
+		return nil, findRes.Err()
+	}
+	var dep *Dependency
+	for findRes.Next(dr.ctx) {
+		err = findRes.Decode(&dep)
+		if err != nil {
+			return nil, err
+		}
+		if dep != nil {
+			break
+		}
+	}
+	if dep != nil {
+		return dep.DependencyInfo.Providers, nil
+	}
+	return nil, nil
+}
+
+func (dr *DependencyRelation) parseDependencyRule(dependencyRule *pb.MicroServiceKey) (serviceIDs []string, err error) {
+	switch {
+	case dependencyRule.ServiceName == "*":
+		log.Info(fmt.Sprintf("service[%s/%s/%s/%s] rely all service",
+			dr.consumer.Environment, dr.consumer.AppId, dr.consumer.ServiceName, dr.consumer.Version))
+		filter, err := MicroServiceKeyFilter(dependencyRule)
+		if err != nil {
+			log.Error("get serivce failed", err)
+			return nil, err
+		}
+		findRes, err := client.GetMongoClient().Find(dr.ctx, CollectionService, filter)
+		if err != nil {
+			return nil, err
+		}
+		if findRes.Err() != nil {
+			return nil, findRes.Err()
+		}
+		for findRes.Next(dr.ctx) {
+			var service Service
+			err = findRes.Decode(&service)
+			if err != nil {
+				return nil, err
+			}
+			serviceIDs = append(serviceIDs, service.ServiceInfo.ServiceId)
+		}
+	default:
+		serviceIDs, _, err = FindServiceIds(dr.ctx, dependencyRule.Version, dependencyRule)
+	}
+	return
+}
+
+func (dr *DependencyRelation) GetDependencyConsumerIds() ([]string, error) {
+	consumerDependAllList, err := dr.GetDependencyConsumersOfProvider()
+	if err != nil {
+		return nil, err
+	}
+	consumerIDs := make([]string, 0, len(consumerDependAllList))
+	for _, consumer := range consumerDependAllList {
+		consumerID, err := GetServiceID(dr.ctx, consumer)
+		if err != nil {
+			log.Error(fmt.Sprintf("get consumer[%s/%s/%s/%s] failed",
+				consumer.Environment, consumer.AppId, consumer.ServiceName, consumer.Version), err)
+			return nil, err
+		}
+		if len(consumerID) == 0 {
+			log.Warn(fmt.Sprintf("get consumer[%s/%s/%s/%s] not exist",
+				consumer.Environment, consumer.AppId, consumer.ServiceName, consumer.Version))
+			continue
+		}
+		consumerIDs = append(consumerIDs, consumerID)
+	}
+	return consumerIDs, nil
+}
+
+func MicroServiceKeyFilter(key *pb.MicroServiceKey) (bson.M, error) {
+	tenant := strings.Split(key.Tenant, "/")
+	if len(tenant) != 2 {
+		return nil, ErrInvalidDomainProject
+	}
+	return bson.M{
+		ColumnDomain:  tenant[0],
+		ColumnProject: tenant[1],
+		StringBuilder([]string{ColumnServiceInfo, ColumnEnv}):     key.Environment,
+		StringBuilder([]string{ColumnServiceInfo, ColumnAppID}):   key.AppId,
+		StringBuilder([]string{ColumnServiceInfo, ColumnAlias}):   key.Alias,
+		StringBuilder([]string{ColumnServiceInfo, ColumnVersion}): key.Version}, nil
+}
+
+func FindServiceIds(ctx context.Context, versionRule string, key *pb.MicroServiceKey) (serviceIDs []string, b bool, err error) {
+	match, err := ParseVersionRule(ctx, versionRule, key)
+	if err != nil {
+		return nil, false, ErrInvalidDomainProject
+	}
+	if match == nil {
+		tenant := strings.Split(key.Tenant, "/")
+		if len(tenant) != 2 {
+			return nil, false, ErrInvalidDomainProject
+		}
+		filter := bson.M{
+			ColumnDomain:  tenant[0],
+			ColumnProject: tenant[1],
+			StringBuilder([]string{ColumnServiceInfo, ColumnEnv}):         key.Environment,
+			StringBuilder([]string{ColumnServiceInfo, ColumnVersion}):     versionRule,
+			StringBuilder([]string{ColumnServiceInfo, ColumnAppID}):       key.AppId,
+			StringBuilder([]string{ColumnServiceInfo, ColumnServiceName}): key.ServiceName,
+			StringBuilder([]string{ColumnServiceInfo, ColumnAlias}):       key.Alias}
+		findRes, err := client.GetMongoClient().Find(ctx, CollectionService, filter)
+		if err != nil {
+			return nil, false, nil
+		}
+		if findRes.Err() != nil {
+			return nil, false, findRes.Err()
+		}
+		for findRes.Next(ctx) {
+			var service Service
+			err = findRes.Decode(&service)
+			if err != nil {
+				return nil, false, err
+			}
+			serviceIDs = append(serviceIDs, service.ServiceInfo.ServiceId)
+		}
+		return serviceIDs, false, nil
+	}
+	return match, false, nil
+}
+
+func ParseVersionRule(ctx context.Context, versionRule string, key *pb.MicroServiceKey) ([]string, error) {
+	tenant := strings.Split(key.Tenant, "/")
+	if len(tenant) != 2 {
+		return nil, ErrInvalidDomainProject
+	}
+	if len(versionRule) == 0 {
+		return nil, nil
+	}
+
+	rangeIdx := strings.Index(versionRule, "-")
+	switch {
+	case versionRule == "latest":
+		filter := bson.M{
+			ColumnDomain:  tenant[0],
+			ColumnProject: tenant[1]}
+		return GetFilterVersionServiceLatest(ctx, filter)
+	case versionRule[len(versionRule)-1:] == "+":
+		start := versionRule[:len(versionRule)-1]
+		filter := bson.M{
+			ColumnDomain:  tenant[0],
+			ColumnProject: tenant[1],
+			StringBuilder([]string{ColumnServiceInfo, ColumnVersion}): bson.M{"$gte": start}}
+		return GetFilterVersionService(ctx, filter)
+	case rangeIdx > 0:
+		start := versionRule[:rangeIdx]
+		end := versionRule[rangeIdx+1:]
+		filter := bson.M{
+			ColumnDomain:  tenant[0],
+			ColumnProject: tenant[1],
+			StringBuilder([]string{ColumnServiceInfo, ColumnVersion}): bson.M{"$gte": start, "$lte": end}}
+		return GetFilterVersionService(ctx, filter)
+	default:
+		return nil, nil
+	}
+}
+
+func GetFilterVersionService(ctx context.Context, m bson.M) (serviceIDs []string, err error) {
+	findRes, err := client.GetMongoClient().Find(ctx, CollectionService, m)
+	if err != nil {
+		return nil, err
+	}
+	if findRes.Err() != nil {
+		return nil, findRes.Err()
+	}
+	for findRes.Next(ctx) {
+		var service Service
+		err = findRes.Decode(&service)
+		if err != nil {
+			return nil, err
+		}
+		serviceIDs = append(serviceIDs, service.ServiceInfo.ServiceId)
+	}
+	return
+}
+
+func GetFilterVersionServiceLatest(ctx context.Context, m bson.M) (serviceIDs []string, err error) {
+	findRes, err := client.GetMongoClient().Find(ctx, CollectionService, m,
+		&options.FindOptions{
+			Sort: bson.M{StringBuilder([]string{ColumnServiceInfo, ColumnVersion}): -1}})
+	if err != nil {
+		return nil, err
+	}
+	if findRes.Err() != nil {
+		return nil, findRes.Err()
+	}
+	for findRes.Next(ctx) {
+		var service Service
+		err = findRes.Decode(&service)
+		if err != nil {
+			return nil, err
+		}
+		serviceIDs = append(serviceIDs, service.ServiceInfo.ServiceId)
+		if serviceIDs != nil {
+			return serviceIDs, nil
+		}
+	}
+	return
+}
+
+func WithSameDomainProject() DependencyRelationFilterOption {
+	return func(opt DependencyRelationFilterOpt) DependencyRelationFilterOpt {
+		opt.SameDomainProject = true
+		return opt
+	}
+}
+func WithoutSelfDependency() DependencyRelationFilterOption {
+	return func(opt DependencyRelationFilterOpt) DependencyRelationFilterOpt {
+		opt.NonSelf = true
+		return opt
+	}
+}
+
+func ToDependencyFilterOptions(in *pb.GetDependenciesRequest) (opts []DependencyRelationFilterOption) {
+	if in.SameDomain {
+		opts = append(opts, WithSameDomainProject())
+	}
+	if in.NoSelf {
+		opts = append(opts, WithoutSelfDependency())
+	}
+	return opts
+}
+
+func ToDependencyRelationFilterOpt(opts ...DependencyRelationFilterOption) (op DependencyRelationFilterOpt) {
+	for _, opt := range opts {
+		op = opt(op)
+	}
+	return
+}
+
+func GenerateConsumerDependencyRuleKey(domainProject string, serviceID string, in *pb.MicroServiceKey) bson.M {
+	return GenerateServiceDependencyRuleKey(domainProject, serviceID, in)
+}
+
+func GenerateProviderDependencyRuleKey(domainProject string, serviceID string, in *pb.MicroServiceKey) bson.M {
+	return GenerateServiceDependencyRuleKey(domainProject, serviceID, in)
+}
+
+func GenerateServiceDependencyRuleKey(domainProject string, serviceID string, in *pb.MicroServiceKey) bson.M {
+	if in == nil {
+		return bson.M{
+			ColumnConsumerID: serviceID,
+			StringBuilder([]string{ColumnDependencyInfo, ColumnConsumer, ColumnTenant}): domainProject}
+	}
+	if in.ServiceName == "*" {
+		return bson.M{
+			ColumnConsumerID: serviceID,
+			StringBuilder([]string{ColumnDependencyInfo, ColumnConsumer, ColumnTenant}):      domainProject,
+			StringBuilder([]string{ColumnDependencyInfo, ColumnConsumer, ColumnEnv}):         in.Environment,
+			StringBuilder([]string{ColumnDependencyInfo, ColumnConsumer, ColumnServiceName}): in.ServiceName}
+	}
+	return bson.M{
+		ColumnConsumerID: serviceID,
+		StringBuilder([]string{ColumnDependencyInfo, ColumnConsumer, ColumnTenant}):      domainProject,
+		StringBuilder([]string{ColumnDependencyInfo, ColumnConsumer, ColumnEnv}):         in.Environment,
+		StringBuilder([]string{ColumnDependencyInfo, ColumnConsumer, ColumnAppID}):       in.AppId,
+		StringBuilder([]string{ColumnDependencyInfo, ColumnConsumer, ColumnVersion}):     in.Version,
+		StringBuilder([]string{ColumnDependencyInfo, ColumnConsumer, ColumnServiceName}): in.ServiceName}
+}
diff --git a/datasource/mongo/ms.go b/datasource/mongo/ms.go
index 46811ee..106cfca 100644
--- a/datasource/mongo/ms.go
+++ b/datasource/mongo/ms.go
@@ -1470,15 +1470,17 @@ func (ds *DataSource) GetInstance(ctx context.Context, request *discovery.GetOne
 				fmt.Sprintf("Provider[%s] does not exist.", request.ProviderServiceId)),
 		}, nil
 	}
-	findFlag := fmt.Sprintf("consumer[%s][%s/%s/%s/%s] find provider[%s][%s/%s/%s/%s] instance[%s]",
-		request.ConsumerServiceId, service.ServiceInfo.Environment, service.ServiceInfo.AppId, service.ServiceInfo.ServiceName, service.ServiceInfo.Version,
-		provider.ServiceInfo.ServiceId, provider.ServiceInfo.Environment, provider.ServiceInfo.AppId, provider.ServiceInfo.ServiceName, provider.ServiceInfo.Version,
-		request.ProviderInstanceId)
+	findFlag := func() string {
+		return fmt.Sprintf("consumer[%s][%s/%s/%s/%s] find provider[%s][%s/%s/%s/%s] instance[%s]",
+			request.ConsumerServiceId, service.ServiceInfo.Environment, service.ServiceInfo.AppId, service.ServiceInfo.ServiceName, service.ServiceInfo.Version,
+			provider.ServiceInfo.ServiceId, provider.ServiceInfo.Environment, provider.ServiceInfo.AppId, provider.ServiceInfo.ServiceName, provider.ServiceInfo.Version,
+			request.ProviderInstanceId)
+	}
 
 	domainProject := util.ParseDomainProject(ctx)
 	services, err := findServices(ctx, discovery.MicroServiceToKey(domainProject, provider.ServiceInfo))
 	if err != nil {
-		log.Error(fmt.Sprintf("get instance failed %s", findFlag), err)
+		log.Error(fmt.Sprintf("get instance failed %s", findFlag()), err)
 		return &discovery.GetOneInstanceResponse{
 			Response: discovery.CreateResponse(discovery.ErrInternal, err.Error()),
 		}, err
@@ -1487,7 +1489,7 @@ func (ds *DataSource) GetInstance(ctx context.Context, request *discovery.GetOne
 		serviceIDs = filterServiceIDs(ctx, request.ConsumerServiceId, request.Tags, services)
 	}
 	if services == nil || len(serviceIDs) == 0 {
-		mes := fmt.Errorf("%s failed, provider does not exist", findFlag)
+		mes := fmt.Errorf("%s failed, provider does not exist", findFlag())
 		log.Error("get instance failed", mes)
 		return &discovery.GetOneInstanceResponse{
 			Response: discovery.CreateResponse(discovery.ErrServiceNotExists, mes.Error()),
@@ -1495,7 +1497,7 @@ func (ds *DataSource) GetInstance(ctx context.Context, request *discovery.GetOne
 	}
 	instances, err := instancesFilter(ctx, serviceIDs)
 	if len(instances) == 0 {
-		mes := fmt.Errorf("%s failed, provider instance does not exist", findFlag)
+		mes := fmt.Errorf("%s failed, provider instance does not exist", findFlag())
 		log.Error("get instance failed", err)
 		return &discovery.GetOneInstanceResponse{
 			Response: discovery.CreateResponse(discovery.ErrInstanceNotExists, mes.Error()),
@@ -1551,13 +1553,15 @@ func (ds *DataSource) GetInstances(ctx context.Context, request *discovery.GetIn
 		}, nil
 	}
 
-	findFlag := fmt.Sprintf("consumer[%s][%s/%s/%s/%s] find provider[%s][%s/%s/%s/%s] instances",
-		request.ConsumerServiceId, service.ServiceInfo.Environment, service.ServiceInfo.AppId, service.ServiceInfo.ServiceName, service.ServiceInfo.Version,
-		provider.ServiceInfo.ServiceId, provider.ServiceInfo.Environment, provider.ServiceInfo.AppId, provider.ServiceInfo.ServiceName, provider.ServiceInfo.Version)
+	findFlag := func() string {
+		return fmt.Sprintf("consumer[%s][%s/%s/%s/%s] find provider[%s][%s/%s/%s/%s] instances",
+			request.ConsumerServiceId, service.ServiceInfo.Environment, service.ServiceInfo.AppId, service.ServiceInfo.ServiceName, service.ServiceInfo.Version,
+			provider.ServiceInfo.ServiceId, provider.ServiceInfo.Environment, provider.ServiceInfo.AppId, provider.ServiceInfo.ServiceName, provider.ServiceInfo.Version)
+	}
 
 	services, err := findServices(ctx, discovery.MicroServiceToKey(domainProject, provider.ServiceInfo))
 	if err != nil {
-		log.Error(fmt.Sprintf("get instances failed %s", findFlag), err)
+		log.Error(fmt.Sprintf("get instances failed %s", findFlag()), err)
 		return &discovery.GetInstancesResponse{
 			Response: discovery.CreateResponse(discovery.ErrInternal, err.Error()),
 		}, err
@@ -1566,7 +1570,7 @@ func (ds *DataSource) GetInstances(ctx context.Context, request *discovery.GetIn
 		serviceIDs = filterServiceIDs(ctx, request.ConsumerServiceId, request.Tags, services)
 	}
 	if services == nil || len(serviceIDs) == 0 {
-		mes := fmt.Errorf("%s failed, provider does not exist", findFlag)
+		mes := fmt.Errorf("%s failed, provider does not exist", findFlag())
 		log.Error("get instances failed", mes)
 		return &discovery.GetInstancesResponse{
 			Response: discovery.CreateResponse(discovery.ErrServiceNotExists, mes.Error()),
@@ -1574,7 +1578,7 @@ func (ds *DataSource) GetInstances(ctx context.Context, request *discovery.GetIn
 	}
 	instances, err := instancesFilter(ctx, serviceIDs)
 	if err != nil {
-		log.Error(fmt.Sprintf("get instances failed %s", findFlag), err)
+		log.Error(fmt.Sprintf("get instances failed %s", findFlag()), err)
 		return &discovery.GetInstancesResponse{
 			Response: discovery.CreateResponse(discovery.ErrInternal, err.Error()),
 		}, err
@@ -1924,16 +1928,18 @@ func (ds *DataSource) findSharedServiceInstance(ctx context.Context, request *di
 	var err error
 	// it means the shared micro-services must be the same env with SC.
 	provider.Environment = apt.Service.Environment
-	findFlag := fmt.Sprintf("find shared provider[%s/%s/%s/%s]", provider.Environment, provider.AppId, provider.ServiceName, provider.Version)
+	findFlag := func() string {
+		return fmt.Sprintf("find shared provider[%s/%s/%s/%s]", provider.Environment, provider.AppId, provider.ServiceName, provider.Version)
+	}
 	services, err := findServices(ctx, provider)
 	if err != nil {
-		log.Error(fmt.Sprintf("find shared service instance failed %s", findFlag), err)
+		log.Error(fmt.Sprintf("find shared service instance failed %s", findFlag()), err)
 		return &discovery.FindInstancesResponse{
 			Response: discovery.CreateResponse(discovery.ErrInternal, err.Error()),
 		}, err
 	}
 	if services == nil {
-		mes := fmt.Errorf("%s failed, provider does not exist", findFlag)
+		mes := fmt.Errorf("%s failed, provider does not exist", findFlag())
 		log.Error("find shared service instance failed", mes)
 		return &discovery.FindInstancesResponse{
 			Response: discovery.CreateResponse(discovery.ErrServiceNotExists, mes.Error()),
@@ -1948,7 +1954,7 @@ func (ds *DataSource) findSharedServiceInstance(ctx context.Context, request *di
 	}
 	instances, err := instancesFilter(ctx, serviceIDs)
 	if err != nil {
-		log.Error(fmt.Sprintf("find shared service instance failed %s", findFlag), err)
+		log.Error(fmt.Sprintf("find shared service instance failed %s", findFlag()), err)
 		return &discovery.FindInstancesResponse{
 			Response: discovery.CreateResponse(discovery.ErrInternal, err.Error()),
 		}, err
@@ -1989,18 +1995,20 @@ func (ds *DataSource) findInstance(ctx context.Context, request *discovery.FindI
 	ctx = util.SetTargetDomainProject(ctx, util.ParseDomain(ctx), util.ParseProject(ctx))
 	provider.Tenant = util.ParseTargetDomainProject(ctx)
 
-	findFlag := fmt.Sprintf("Consumer[%s][%s/%s/%s/%s] find provider[%s/%s/%s/%s]",
-		request.ConsumerServiceId, service.ServiceInfo.Environment, service.ServiceInfo.AppId, service.ServiceInfo.ServiceName, service.ServiceInfo.Version,
-		provider.Environment, provider.AppId, provider.ServiceName, provider.Version)
+	findFlag := func() string {
+		return fmt.Sprintf("Consumer[%s][%s/%s/%s/%s] find provider[%s/%s/%s/%s]",
+			request.ConsumerServiceId, service.ServiceInfo.Environment, service.ServiceInfo.AppId, service.ServiceInfo.ServiceName, service.ServiceInfo.Version,
+			provider.Environment, provider.AppId, provider.ServiceName, provider.Version)
+	}
 	services, err := findServices(ctx, provider)
 	if err != nil {
-		log.Error(fmt.Sprintf("find instance failed %s", findFlag), err)
+		log.Error(fmt.Sprintf("find instance failed %s", findFlag()), err)
 		return &discovery.FindInstancesResponse{
 			Response: discovery.CreateResponse(discovery.ErrInternal, err.Error()),
 		}, err
 	}
 	if services == nil {
-		mes := fmt.Errorf("%s failed, provider does not exist", findFlag)
+		mes := fmt.Errorf("%s failed, provider does not exist", findFlag())
 		log.Error("find instance failed", mes)
 		return &discovery.FindInstancesResponse{
 			Response: discovery.CreateResponse(discovery.ErrServiceNotExists, mes.Error()),
@@ -2015,7 +2023,7 @@ func (ds *DataSource) findInstance(ctx context.Context, request *discovery.FindI
 	}
 	instances, err := instancesFilter(ctx, serviceIDs)
 	if err != nil {
-		log.Error(fmt.Sprintf("find instance failed %s", findFlag), err)
+		log.Error(fmt.Sprintf("find instance failed %s", findFlag()), err)
 		return &discovery.FindInstancesResponse{
 			Response: discovery.CreateResponse(discovery.ErrInternal, err.Error()),
 		}, err
@@ -2030,14 +2038,14 @@ func (ds *DataSource) findInstance(ctx context.Context, request *discovery.FindI
 		if provider != nil {
 			err = AddServiceVersionRule(ctx, domainProject, service.ServiceInfo, provider)
 		} else {
-			mes := fmt.Errorf("%s failed, provider does not exist", findFlag)
+			mes := fmt.Errorf("%s failed, provider does not exist", findFlag())
 			log.Error("add service version rule failed", mes)
 			return &discovery.FindInstancesResponse{
 				Response: discovery.CreateResponse(discovery.ErrServiceNotExists, mes.Error()),
 			}, nil
 		}
 		if err != nil {
-			log.Error(fmt.Sprintf("add service version rule failed %s", findFlag), err)
+			log.Error(fmt.Sprintf("add service version rule failed %s", findFlag()), err)
 			return &discovery.FindInstancesResponse{
 				Response: discovery.CreateResponse(discovery.ErrInternal, err.Error()),
 			}, err