You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2021/09/10 13:38:32 UTC

[servicecomb-service-center] branch master updated: Fix: Add Dependency API (#1151)

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

littlecui 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 426e92a  Fix: Add Dependency API (#1151)
426e92a is described below

commit 426e92a8e96ddcdbb2a6a043862ff47759a0613d
Author: little-cui <su...@qq.com>
AuthorDate: Fri Sep 10 21:38:26 2021 +0800

    Fix: Add Dependency API (#1151)
---
 datasource/dep.go                                  |   3 +
 datasource/dep_test.go                             | 341 ++++++++++++++++
 datasource/dependency_util.go                      |  14 +-
 datasource/etcd/dep.go                             |  73 +++-
 datasource/etcd/event/dependency_event_handler.go  |  16 +-
 datasource/etcd/ms.go                              |   2 +-
 datasource/etcd/util/dependency_util.go            |  58 +--
 datasource/etcd/util/dependency_util_test.go       |  50 ---
 datasource/mongo/dep.go                            |  64 ++-
 integration/apis.go                                |   1 +
 integration/microservices_test.go                  | 268 +++++++++++-
 pkg/proto/service.go                               |   2 +
 server/rest/controller/v4/dependency_controller.go |  55 +++
 server/service/disco/dependency.go                 |  24 ++
 server/service/disco/dependency_test.go            | 451 +++++++++++++++++++--
 server/service/validator/dependency_validator.go   |  70 ++++
 server/service/validator/validator.go              |   4 +
 17 files changed, 1365 insertions(+), 131 deletions(-)

diff --git a/datasource/dep.go b/datasource/dep.go
index d3cee31..a8e430d 100644
--- a/datasource/dep.go
+++ b/datasource/dep.go
@@ -23,9 +23,12 @@ import (
 	pb "github.com/go-chassis/cari/discovery"
 )
 
+const AllVersions = "0.0.0+"
+
 // DependencyManager contains the CRUD of microservice dependencies
 type DependencyManager interface {
 	SearchProviderDependency(ctx context.Context, request *pb.GetDependenciesRequest) (*pb.GetProDependenciesResponse, error)
 	SearchConsumerDependency(ctx context.Context, request *pb.GetDependenciesRequest) (*pb.GetConDependenciesResponse, error)
+	AddOrUpdateDependencies(ctx context.Context, dependencyInfos []*pb.ConsumerDependency, override bool) (*pb.Response, error)
 	DependencyHandle(ctx context.Context) error
 }
diff --git a/datasource/dep_test.go b/datasource/dep_test.go
index 435d881..da5daba 100644
--- a/datasource/dep_test.go
+++ b/datasource/dep_test.go
@@ -27,6 +27,292 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
+func Test_Create(t *testing.T) {
+	var (
+		consumerId1 string
+		consumerId2 string
+	)
+	resp, err := datasource.GetMetadataManager().RegisterService(depGetContext(), &pb.CreateServiceRequest{
+		Service: &pb.MicroService{
+			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, resp.Response.GetCode())
+	consumerId1 = resp.ServiceId
+	defer datasource.GetMetadataManager().UnregisterService(depGetContext(), &pb.DeleteServiceRequest{ServiceId: resp.ServiceId, Force: true})
+
+	resp, err = datasource.GetMetadataManager().RegisterService(depGetContext(), &pb.CreateServiceRequest{
+		Service: &pb.MicroService{
+			Environment: pb.ENV_PROD,
+			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, resp.Response.GetCode())
+	consumerId2 = resp.ServiceId
+	defer datasource.GetMetadataManager().UnregisterService(depGetContext(), &pb.DeleteServiceRequest{ServiceId: resp.ServiceId, Force: true})
+
+	resp, err = datasource.GetMetadataManager().RegisterService(depGetContext(), &pb.CreateServiceRequest{
+		Service: &pb.MicroService{
+			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, resp.Response.GetCode())
+	defer datasource.GetMetadataManager().UnregisterService(depGetContext(), &pb.DeleteServiceRequest{ServiceId: resp.ServiceId, Force: true})
+
+	resp, err = datasource.GetMetadataManager().RegisterService(depGetContext(), &pb.CreateServiceRequest{
+		Service: &pb.MicroService{
+			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, resp.Response.GetCode())
+	defer datasource.GetMetadataManager().UnregisterService(depGetContext(), &pb.DeleteServiceRequest{ServiceId: resp.ServiceId, Force: true})
+
+	resp, err = datasource.GetMetadataManager().RegisterService(depGetContext(), &pb.CreateServiceRequest{
+		Service: &pb.MicroService{
+			AppId:       "dep_create_dep_group",
+			ServiceName: "dep_create_dep_provider_other",
+			Version:     "1.0.0",
+			Level:       "FRONT",
+			Status:      pb.MS_UP,
+		},
+	})
+	assert.NotNil(t, resp)
+	assert.NoError(t, err)
+	assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+	defer datasource.GetMetadataManager().UnregisterService(depGetContext(), &pb.DeleteServiceRequest{ServiceId: resp.ServiceId, Force: true})
+
+	resp, err = datasource.GetMetadataManager().RegisterService(depGetContext(), &pb.CreateServiceRequest{
+		Service: &pb.MicroService{
+			Environment: pb.ENV_PROD,
+			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, resp.Response.GetCode())
+	defer datasource.GetMetadataManager().UnregisterService(depGetContext(), &pb.DeleteServiceRequest{ServiceId: resp.ServiceId, Force: true})
+
+	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",
+			},
+		}
+
+		// consumer does not exist
+		resp, err := datasource.GetDependencyManager().AddOrUpdateDependencies(depGetContext(), []*pb.ConsumerDependency{
+			{
+				Consumer: &pb.MicroServiceKey{
+					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())
+
+		err = datasource.GetDependencyManager().DependencyHandle(getContext())
+		assert.NoError(t, err)
+
+		// provider in diff env
+		resp, err = datasource.GetDependencyManager().AddOrUpdateDependencies(depGetContext(), []*pb.ConsumerDependency{
+			{
+				Consumer: consumer,
+				Providers: []*pb.MicroServiceKey{
+					{
+						Environment: pb.ENV_PROD,
+						AppId:       "dep_service_group_provider",
+						ServiceName: "dep_service_name_provider",
+					},
+				},
+			},
+		}, false)
+		assert.NotNil(t, resp)
+		assert.NoError(t, err)
+		assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
+
+		//consumer in diff env
+		consumer.Environment = pb.ENV_PROD
+		resp, err = datasource.GetDependencyManager().AddOrUpdateDependencies(depGetContext(), []*pb.ConsumerDependency{
+			{
+				Consumer: consumer,
+				Providers: []*pb.MicroServiceKey{
+					{
+						AppId:       "dep_service_group_provider",
+						ServiceName: "dep_service_name_provider",
+					},
+				},
+			},
+		}, false)
+		assert.NotNil(t, resp)
+		assert.NoError(t, err)
+		assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
+
+		err = datasource.GetDependencyManager().DependencyHandle(getContext())
+		assert.NoError(t, err)
+
+		respCon, err := datasource.GetDependencyManager().SearchConsumerDependency(depGetContext(), &pb.GetDependenciesRequest{
+			ServiceId: consumerId1,
+		})
+		assert.NotNil(t, respCon)
+		assert.NoError(t, err)
+		assert.Equal(t, 0, len(respCon.Providers))
+
+		respCon, err = datasource.GetDependencyManager().SearchConsumerDependency(depGetContext(), &pb.GetDependenciesRequest{
+			ServiceId: consumerId2,
+		})
+		assert.NotNil(t, respCon)
+		assert.NoError(t, err)
+		assert.Equal(t, 0, len(respCon.Providers))
+	})
+
+	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",
+		}
+
+		resp, err := datasource.GetDependencyManager().AddOrUpdateDependencies(depGetContext(), []*pb.ConsumerDependency{
+			{
+				Consumer: consumer,
+				Providers: []*pb.MicroServiceKey{
+					{
+						AppId:       "dep_create_dep_group",
+						ServiceName: "dep_create_dep_provider",
+					},
+				},
+			},
+		}, false)
+		assert.NotNil(t, resp)
+		assert.NoError(t, err)
+		assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
+
+		err = datasource.GetDependencyManager().DependencyHandle(getContext())
+		assert.NoError(t, err)
+
+		respPro, err := datasource.GetDependencyManager().SearchConsumerDependency(depGetContext(), &pb.GetDependenciesRequest{
+			ServiceId: consumerId1,
+		})
+		assert.NotNil(t, respPro)
+		assert.NoError(t, err)
+		assert.Equal(t, 2, len(respPro.Providers))
+
+		// add multiple providers
+		resp, err = datasource.GetDependencyManager().AddOrUpdateDependencies(depGetContext(), []*pb.ConsumerDependency{
+			{
+				Consumer: consumer,
+				Providers: []*pb.MicroServiceKey{
+					{
+						AppId:       "dep_create_dep_group",
+						ServiceName: "dep_create_dep_provider",
+					},
+					{
+						AppId:       "dep_create_dep_group",
+						ServiceName: "dep_create_dep_provider_other",
+					},
+				},
+			},
+		}, false)
+		assert.NotNil(t, resp)
+		assert.NoError(t, err)
+		assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
+
+		err = datasource.GetDependencyManager().DependencyHandle(getContext())
+		assert.NoError(t, err)
+
+		respPro, err = datasource.GetDependencyManager().SearchConsumerDependency(depGetContext(), &pb.GetDependenciesRequest{
+			ServiceId: consumerId1,
+		})
+		assert.NotNil(t, respPro)
+		assert.NoError(t, err)
+		assert.Equal(t, 3, len(respPro.Providers))
+
+		// override
+		resp, err = datasource.GetDependencyManager().AddOrUpdateDependencies(depGetContext(), []*pb.ConsumerDependency{
+			{
+				Consumer: consumer,
+				Providers: []*pb.MicroServiceKey{
+					{
+						AppId:       "dep_create_dep_group",
+						ServiceName: "dep_create_dep_provider",
+					},
+				},
+			},
+		}, true)
+		assert.NotNil(t, resp)
+		assert.NoError(t, err)
+		assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
+		err = datasource.GetDependencyManager().DependencyHandle(getContext())
+		assert.NoError(t, err)
+
+		respPro, err = datasource.GetDependencyManager().SearchConsumerDependency(depGetContext(), &pb.GetDependenciesRequest{
+			ServiceId: consumerId1,
+		})
+		assert.NotNil(t, respPro)
+		assert.NoError(t, err)
+		assert.Equal(t, 2, len(respPro.Providers))
+
+		// clean all
+		resp, err = datasource.GetDependencyManager().AddOrUpdateDependencies(depGetContext(), []*pb.ConsumerDependency{
+			{
+				Consumer:  consumer,
+				Providers: nil,
+			},
+		}, true)
+		assert.NotNil(t, resp)
+		assert.NoError(t, err)
+		assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
+
+		err = datasource.GetDependencyManager().DependencyHandle(getContext())
+		assert.NoError(t, err)
+
+		respPro, err = datasource.GetDependencyManager().SearchConsumerDependency(depGetContext(), &pb.GetDependenciesRequest{
+			ServiceId: consumerId1,
+		})
+		assert.NotNil(t, respPro)
+		assert.NoError(t, err)
+		assert.Equal(t, 0, len(respPro.Providers))
+	})
+}
+
 func Test_Get(t *testing.T) {
 	var (
 		consumerId1 string
@@ -243,3 +529,58 @@ func Test_Get(t *testing.T) {
 func depGetContext() context.Context {
 	return util.WithNoCache(util.SetDomainProject(context.Background(), "new_default", "new_default"))
 }
+
+func TestParamsChecker(t *testing.T) {
+	p := datasource.ParamsChecker(nil, nil)
+	assert.Nil(t, p)
+
+	p = datasource.ParamsChecker(&pb.MicroServiceKey{
+		AppId:       "a",
+		ServiceName: "b",
+		Version:     "1.0.0",
+	}, nil)
+	assert.Nil(t, p)
+
+	producer := &pb.MicroServiceKey{ServiceName: "*"}
+	p = datasource.ParamsChecker(&pb.MicroServiceKey{
+		AppId:       "a",
+		ServiceName: "b",
+		Version:     "1.0.0",
+	}, []*pb.MicroServiceKey{
+		producer,
+	})
+	assert.Nil(t, p)
+	assert.Equal(t, "a", producer.AppId)
+	assert.Equal(t, "0.0.0+", producer.Version)
+
+	producer.ServiceName = "a"
+	producer.Version = "1"
+	p = datasource.ParamsChecker(&pb.MicroServiceKey{
+		AppId:       "a",
+		ServiceName: "b",
+		Version:     "1.0.0",
+	}, []*pb.MicroServiceKey{
+		producer,
+	})
+	assert.Nil(t, p)
+	assert.Equal(t, "0.0.0+", producer.Version)
+
+	p = datasource.ParamsChecker(&pb.MicroServiceKey{
+		AppId:       "a",
+		ServiceName: "b",
+		Version:     "1.0.0",
+	}, []*pb.MicroServiceKey{
+		{},
+	})
+	assert.NotNil(t, p)
+
+	p = datasource.ParamsChecker(&pb.MicroServiceKey{
+		AppId:       "a",
+		ServiceName: "b",
+		Version:     "1.0.0",
+	}, []*pb.MicroServiceKey{
+		{ServiceName: "a", Version: "1"},
+		{ServiceName: "a", Version: "1"},
+	})
+	assert.NotNil(t, p)
+}
diff --git a/datasource/dependency_util.go b/datasource/dependency_util.go
index 6733fbc..f57ce4f 100644
--- a/datasource/dependency_util.go
+++ b/datasource/dependency_util.go
@@ -43,25 +43,17 @@ type Dependency struct {
 func ParamsChecker(consumerInfo *discovery.MicroServiceKey, providersInfo []*discovery.MicroServiceKey) *discovery.CreateDependenciesResponse {
 	flag := make(map[string]bool, len(providersInfo))
 	for _, providerInfo := range providersInfo {
-		//存在带*的情况,后面的数据就不校验了
-		if providerInfo.ServiceName == "*" {
-			break
+		if len(providerInfo.ServiceName) == 0 {
+			return BadParamsResponse("Required provider serviceName")
 		}
 		if len(providerInfo.AppId) == 0 {
 			providerInfo.AppId = consumerInfo.AppId
 		}
-
-		version := providerInfo.Version
-		if len(version) == 0 {
-			return BadParamsResponse("Required provider version")
-		}
-
-		providerInfo.Version = ""
+		providerInfo.Version = AllVersions
 		if _, ok := flag[toString(providerInfo)]; ok {
 			return BadParamsResponse("Invalid request body for provider info.Duplicate provider or (serviceName and appId is same).")
 		}
 		flag[toString(providerInfo)] = true
-		providerInfo.Version = version
 	}
 	return nil
 }
diff --git a/datasource/etcd/dep.go b/datasource/etcd/dep.go
index 884aedb..ba3c837 100644
--- a/datasource/etcd/dep.go
+++ b/datasource/etcd/dep.go
@@ -19,6 +19,7 @@ package etcd
 
 import (
 	"context"
+	"encoding/json"
 	"errors"
 	"fmt"
 
@@ -104,17 +105,71 @@ func (dm *DepManager) DependencyHandle(ctx context.Context) error {
 	if err != nil {
 		return err
 	}
-	for {
-		key := path.GetServiceDependencyQueueRootKey("")
-		resp, err := sd.DependencyQueue().Search(ctx,
-			etcdadpt.WithStrKey(key), etcdadpt.WithPrefix(), etcdadpt.WithCountOnly())
+
+	key := path.GetServiceDependencyQueueRootKey("")
+	resp, err := sd.DependencyQueue().Search(ctx,
+		etcdadpt.WithStrKey(key), etcdadpt.WithPrefix(), etcdadpt.WithCountOnly())
+	if err != nil {
+		return err
+	}
+	// maintain dependency rules.
+	if resp.Count != 0 {
+		return fmt.Errorf("residual records[%d]", resp.Count)
+	}
+	return nil
+}
+
+func (dm *DepManager) AddOrUpdateDependencies(ctx context.Context, dependencyInfos []*pb.ConsumerDependency, override bool) (*pb.Response, error) {
+	opts := make([]etcdadpt.OpOptions, 0, len(dependencyInfos))
+	domainProject := util.ParseDomainProject(ctx)
+	for _, dependencyInfo := range dependencyInfos {
+		consumerFlag := util.StringJoin([]string{dependencyInfo.Consumer.Environment, dependencyInfo.Consumer.AppId, dependencyInfo.Consumer.ServiceName, dependencyInfo.Consumer.Version}, "/")
+		consumerInfo := pb.DependenciesToKeys([]*pb.MicroServiceKey{dependencyInfo.Consumer}, domainProject)[0]
+		providersInfo := pb.DependenciesToKeys(dependencyInfo.Providers, domainProject)
+
+		rsp := datasource.ParamsChecker(consumerInfo, providersInfo)
+		if rsp != nil {
+			log.Error(fmt.Sprintf("put request into dependency queue failed, override: %t, consumer is %s, %s",
+				override, consumerFlag, rsp.Response.GetMessage()), nil)
+			return rsp.Response, nil
+		}
+
+		consumerID, err := serviceUtil.GetServiceID(ctx, consumerInfo)
+		if err != nil {
+			log.Error(fmt.Sprintf("put request into dependency queue failed, override: %t, get consumer[%s] id failed",
+				override, consumerFlag), err)
+			return pb.CreateResponse(pb.ErrInternal, err.Error()), err
+		}
+		if len(consumerID) == 0 {
+			log.Error(fmt.Sprintf("put request into dependency queue failed, override: %t, consumer[%s] does not exist",
+				override, consumerFlag), nil)
+			return pb.CreateResponse(pb.ErrServiceNotExists, fmt.Sprintf("Consumer %s does not exist.", consumerFlag)), nil
+		}
+
+		dependencyInfo.Override = override
+		data, err := json.Marshal(dependencyInfo)
 		if err != nil {
-			return err
+			log.Error(fmt.Sprintf("put request into dependency queue failed, override: %t, marshal consumer[%s] dependency failed",
+				override, consumerFlag), err)
+			return pb.CreateResponse(pb.ErrInternal, err.Error()), err
 		}
-		// maintain dependency rules.
-		if resp.Count == 0 {
-			break
+
+		id := path.DepsQueueUUID
+		if !override {
+			id = util.GenerateUUID()
 		}
+		key := path.GenerateConsumerDependencyQueueKey(domainProject, consumerID, id)
+		opts = append(opts, etcdadpt.OpPut(etcdadpt.WithStrKey(key), etcdadpt.WithValue(data)))
 	}
-	return nil
+
+	err := etcdadpt.Txn(ctx, opts)
+	if err != nil {
+		log.Error(fmt.Sprintf("put request into dependency queue failed, override: %t, %v",
+			override, dependencyInfos), err)
+		return pb.CreateResponse(pb.ErrInternal, err.Error()), err
+	}
+
+	log.Info(fmt.Sprintf("put request into dependency queue successfully, override: %t, %v, from remote %s",
+		override, dependencyInfos, util.GetIPFromContext(ctx)))
+	return pb.CreateResponse(pb.ResponseSuccess, "Create dependency successfully."), nil
 }
diff --git a/datasource/etcd/event/dependency_event_handler.go b/datasource/etcd/event/dependency_event_handler.go
index 8a78baa..8a427d4 100644
--- a/datasource/etcd/event/dependency_event_handler.go
+++ b/datasource/etcd/event/dependency_event_handler.go
@@ -149,7 +149,10 @@ func (h *DependencyEventHandler) Handle() error {
 
 	key := path.GetServiceDependencyQueueRootKey("")
 	resp, err := sd.DependencyQueue().Search(context.Background(), etcdadpt.WithNoCache(),
-		etcdadpt.WithStrKey(key), etcdadpt.WithPrefix())
+		etcdadpt.WithStrKey(key), etcdadpt.WithPrefix(),
+		etcdadpt.WithOrderByCreate(), etcdadpt.WithAscendOrder(),
+		// get one page
+		etcdadpt.WithLimit(etcdadpt.DefaultPageCount))
 	if err != nil {
 		return err
 	}
@@ -193,11 +196,18 @@ func (h *DependencyEventHandler) dependencyRuleHandle(res interface{}) error {
 	consumerInfo := pb.DependenciesToKeys([]*pb.MicroServiceKey{r.Consumer}, domainProject)[0]
 	providersInfo := pb.DependenciesToKeys(r.Providers, domainProject)
 
-	var dep serviceUtil.Dependency
+	var (
+		dep serviceUtil.Dependency
+		err error
+	)
 	dep.DomainProject = domainProject
 	dep.Consumer = consumerInfo
 	dep.ProvidersRule = providersInfo
-	err := serviceUtil.AddDependencyRule(ctx, &dep)
+	if r.Override {
+		err = serviceUtil.CreateDependencyRule(ctx, &dep)
+	} else {
+		err = serviceUtil.AddDependencyRule(ctx, &dep)
+	}
 	if err != nil {
 		log.Error(fmt.Sprintf("modify dependency rule failed, override: %t, consumer %s", r.Override, consumerFlag), err)
 		return fmt.Errorf("override: %t, consumer is %s, %s", r.Override, consumerFlag, err.Error())
diff --git a/datasource/etcd/ms.go b/datasource/etcd/ms.go
index ad1b78e..b2c5a4f 100644
--- a/datasource/etcd/ms.go
+++ b/datasource/etcd/ms.go
@@ -1020,7 +1020,7 @@ func (ds *MetadataManager) reshapeProviderKey(ctx context.Context, provider *pb.
 	}
 
 	provider = pb.MicroServiceToKey(provider.Tenant, providerService)
-	provider.Version = "0.0.0+" // just compatible to old version
+	provider.Version = datasource.AllVersions // just compatible to old version
 	return provider, nil
 }
 
diff --git a/datasource/etcd/util/dependency_util.go b/datasource/etcd/util/dependency_util.go
index 48caebc..b03debb 100644
--- a/datasource/etcd/util/dependency_util.go
+++ b/datasource/etcd/util/dependency_util.go
@@ -201,6 +201,34 @@ func parseAddOrUpdateRules(ctx context.Context, dep *Dependency) (createDependen
 	return
 }
 
+func parseOverrideRules(ctx context.Context, dep *Dependency) (createDependencyRuleList, existDependencyRuleList, deleteDependencyRuleList []*pb.MicroServiceKey) {
+	conKey := path.GenerateConsumerDependencyRuleKey(dep.DomainProject, dep.Consumer)
+
+	oldProviderRules, err := TransferToMicroServiceDependency(ctx, conKey)
+	if err != nil {
+		log.Error(fmt.Sprintf("override dependency rule failed, get consumer[%s/%s/%s/%s]'s dependency rule failed",
+			dep.Consumer.Environment, dep.Consumer.AppId, dep.Consumer.ServiceName, dep.Consumer.Version), err)
+		return
+	}
+
+	deleteDependencyRuleList = make([]*pb.MicroServiceKey, 0, len(oldProviderRules.Dependency))
+	createDependencyRuleList = make([]*pb.MicroServiceKey, 0, len(dep.ProvidersRule))
+	existDependencyRuleList = make([]*pb.MicroServiceKey, 0, len(oldProviderRules.Dependency))
+	for _, oldProviderRule := range oldProviderRules.Dependency {
+		if ok, _ := ContainServiceDependency(dep.ProvidersRule, oldProviderRule); !ok {
+			deleteDependencyRuleList = append(deleteDependencyRuleList, oldProviderRule)
+		} else {
+			existDependencyRuleList = append(existDependencyRuleList, oldProviderRule)
+		}
+	}
+	for _, tmpProviderRule := range dep.ProvidersRule {
+		if ok, _ := ContainServiceDependency(existDependencyRuleList, tmpProviderRule); !ok {
+			createDependencyRuleList = append(createDependencyRuleList, tmpProviderRule)
+		}
+	}
+	return
+}
+
 func syncDependencyRule(ctx context.Context, dep *Dependency, filter func(context.Context, *Dependency) (_, _, _ []*pb.MicroServiceKey)) error {
 	//更新consumer的providers的值,consumer的版本是确定的
 	consumerFlag := strings.Join([]string{dep.Consumer.Environment, dep.Consumer.AppId, dep.Consumer.ServiceName, dep.Consumer.Version}, "/")
@@ -227,6 +255,10 @@ func AddDependencyRule(ctx context.Context, dep *Dependency) error {
 	return syncDependencyRule(ctx, dep, parseAddOrUpdateRules)
 }
 
+func CreateDependencyRule(ctx context.Context, dep *Dependency) error {
+	return syncDependencyRule(ctx, dep, parseOverrideRules)
+}
+
 func IsNeedUpdate(services []*pb.MicroServiceKey, service *pb.MicroServiceKey) *pb.MicroServiceKey {
 	for _, tmp := range services {
 		if DiffServiceVersion(tmp, service) {
@@ -259,32 +291,6 @@ func BadParamsResponse(detailErr string) *pb.CreateDependenciesResponse {
 	}
 }
 
-func ParamsChecker(consumerInfo *pb.MicroServiceKey, providersInfo []*pb.MicroServiceKey) *pb.CreateDependenciesResponse {
-	flag := make(map[string]bool, len(providersInfo))
-	for _, providerInfo := range providersInfo {
-		//存在带*的情况,后面的数据就不校验了
-		if providerInfo.ServiceName == "*" {
-			break
-		}
-		if len(providerInfo.AppId) == 0 {
-			providerInfo.AppId = consumerInfo.AppId
-		}
-
-		version := providerInfo.Version
-		if len(version) == 0 {
-			return BadParamsResponse("Required provider version")
-		}
-
-		providerInfo.Version = ""
-		if _, ok := flag[toString(providerInfo)]; ok {
-			return BadParamsResponse("Invalid request body for provider info.Duplicate provider or (serviceName and appId is same).")
-		}
-		flag[toString(providerInfo)] = true
-		providerInfo.Version = version
-	}
-	return nil
-}
-
 func DeleteDependencyForDeleteService(domainProject string, serviceID string, service *pb.MicroServiceKey) (etcdadpt.OpOptions, error) {
 	key := path.GenerateConsumerDependencyQueueKey(domainProject, serviceID, path.DepsQueueUUID)
 	conDep := new(pb.ConsumerDependency)
diff --git a/datasource/etcd/util/dependency_util_test.go b/datasource/etcd/util/dependency_util_test.go
index f22f061..5e89dce 100644
--- a/datasource/etcd/util/dependency_util_test.go
+++ b/datasource/etcd/util/dependency_util_test.go
@@ -112,56 +112,6 @@ func TestDependencyRuleExistUtil(t *testing.T) {
 	}
 }
 
-func TestParamsChecker(t *testing.T) {
-	p := ParamsChecker(nil, nil)
-	if p != nil {
-		t.Fatalf(`ParamsChecker invalid failed`)
-	}
-
-	p = ParamsChecker(&discovery.MicroServiceKey{
-		AppId:       "a",
-		ServiceName: "b",
-		Version:     "1.0.0",
-	}, nil)
-	if p != nil {
-		t.Fatalf(`ParamsChecker invalid failed`)
-	}
-
-	p = ParamsChecker(&discovery.MicroServiceKey{
-		AppId:       "a",
-		ServiceName: "b",
-		Version:     "1.0.0",
-	}, []*discovery.MicroServiceKey{
-		{ServiceName: "*"},
-	})
-	if p != nil {
-		t.Fatalf(`ParamsChecker * failed`)
-	}
-
-	p = ParamsChecker(&discovery.MicroServiceKey{
-		AppId:       "a",
-		ServiceName: "b",
-		Version:     "1.0.0",
-	}, []*discovery.MicroServiceKey{
-		{},
-	})
-	if p == nil {
-		t.Fatalf(`ParamsChecker invalid provider key failed`)
-	}
-
-	p = ParamsChecker(&discovery.MicroServiceKey{
-		AppId:       "a",
-		ServiceName: "b",
-		Version:     "1.0.0",
-	}, []*discovery.MicroServiceKey{
-		{ServiceName: "a", Version: "1"},
-		{ServiceName: "a", Version: "1"},
-	})
-	if p == nil {
-		t.Fatalf(`ParamsChecker duplicate provider key failed`)
-	}
-}
-
 func TestServiceDependencyRuleExist(t *testing.T) {
 	_, err := DependencyRuleExist(context.Background(), &discovery.MicroServiceKey{}, &discovery.MicroServiceKey{})
 	if err != nil {
diff --git a/datasource/mongo/dep.go b/datasource/mongo/dep.go
index d83da13..03e2202 100644
--- a/datasource/mongo/dep.go
+++ b/datasource/mongo/dep.go
@@ -110,6 +110,64 @@ func (ds *DepManager) SearchConsumerDependency(ctx context.Context, request *dis
 	}, nil
 }
 
+func (ds *DepManager) AddOrUpdateDependencies(ctx context.Context, dependencys []*discovery.ConsumerDependency, override bool) (*discovery.Response, error) {
+	domainProject := util.ParseDomainProject(ctx)
+	for _, dependency := range dependencys {
+		consumerFlag := util.StringJoin([]string{
+			dependency.Consumer.Environment,
+			dependency.Consumer.AppId,
+			dependency.Consumer.ServiceName,
+			dependency.Consumer.Version}, "/")
+		consumerInfo := discovery.DependenciesToKeys([]*discovery.MicroServiceKey{dependency.Consumer}, domainProject)[0]
+		providersInfo := discovery.DependenciesToKeys(dependency.Providers, domainProject)
+
+		rsp := datasource.ParamsChecker(consumerInfo, providersInfo)
+		if rsp != nil {
+			log.Error(fmt.Sprintf("put request into dependency queue failed, override: %t consumer is %s %s",
+				override, consumerFlag, rsp.Response.GetMessage()), nil)
+			return rsp.Response, nil
+		}
+
+		consumerID, err := GetServiceID(ctx, consumerInfo)
+		if err != nil && !errors.Is(err, datasource.ErrNoData) {
+			log.Error(fmt.Sprintf("put request into dependency queue failed, override: %t, get consumer %s id failed",
+				override, consumerFlag), err)
+			return discovery.CreateResponse(discovery.ErrInternal, err.Error()), err
+		}
+		if len(consumerID) == 0 {
+			log.Error(fmt.Sprintf("put request into dependency queue failed, override: %t consumer %s does not exist",
+				override, consumerFlag), err)
+			return discovery.CreateResponse(discovery.ErrServiceNotExists, fmt.Sprintf("Consumer %s does not exist.", consumerFlag)), nil
+		}
+
+		dependency.Override = override
+		if !override {
+			id := util.GenerateUUID()
+
+			domain := util.ParseDomain(ctx)
+			project := util.ParseProject(ctx)
+			data := &model.ConsumerDep{
+				Domain:      domain,
+				Project:     project,
+				ConsumerID:  consumerID,
+				UUID:        id,
+				ConsumerDep: dependency,
+			}
+			insertRes, err := client.GetMongoClient().Insert(ctx, model.CollectionDep, data)
+			if err != nil {
+				log.Error("failed to insert dep to mongodb", err)
+				return discovery.CreateResponse(discovery.ErrInternal, err.Error()), err
+			}
+			log.Info(fmt.Sprintf("insert dep to mongodb success %s", insertRes.InsertedID))
+		}
+		err = syncDependencyRule(ctx, domainProject, dependency)
+		if err != nil {
+			return nil, err
+		}
+	}
+	return discovery.CreateResponse(discovery.ResponseSuccess, "Create dependency successfully."), nil
+}
+
 func (ds *DepManager) DependencyHandle(ctx context.Context) (err error) {
 	return nil
 }
@@ -130,7 +188,11 @@ func syncDependencyRule(ctx context.Context, domainProject string, r *discovery.
 	if err != nil {
 		return err
 	}
-	datasource.ParseAddOrUpdateRules(ctx, &dep, oldProviderRules)
+	if r.Override {
+		datasource.ParseOverrideRules(ctx, &dep, oldProviderRules)
+	} else {
+		datasource.ParseAddOrUpdateRules(ctx, &dep, oldProviderRules)
+	}
 	return updateDeps(domainProject, &dep)
 }
 
diff --git a/integration/apis.go b/integration/apis.go
index 6debf13..a1a4f2b 100644
--- a/integration/apis.go
+++ b/integration/apis.go
@@ -32,6 +32,7 @@ var UPDATESCHEMA = "/v4/default/registry/microservices/:serviceId/schemas/:schem
 var GETSCHEMAS = "/v4/default/registry/microservices/:serviceId/schemas"
 var UPDATESCHEMAS = "/v4/default/registry/microservices/:serviceId/schemas"
 var DELETESCHEMA = "/v4/default/registry/microservices/:serviceId/schemas/:schemaId"
+var CREATEDEPENDENCIES = "/v4/default/registry/dependencies"
 var GETCONPRODEPENDENCY = "/v4/default/registry/microservices/:consumerId/providers"
 var GETPROCONDEPENDENCY = "/v4/default/registry/microservices/:providerId/consumers"
 
diff --git a/integration/microservices_test.go b/integration/microservices_test.go
index ee3027d..a78c493 100644
--- a/integration/microservices_test.go
+++ b/integration/microservices_test.go
@@ -17,9 +17,6 @@
 package integrationtest_test
 
 import (
-	. "github.com/onsi/ginkgo"
-	. "github.com/onsi/gomega"
-
 	"bytes"
 	"encoding/json"
 	"io/ioutil"
@@ -28,8 +25,12 @@ import (
 	"strconv"
 	"strings"
 	"testing"
+	"time"
 
 	. "github.com/apache/servicecomb-service-center/integration"
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+
 	"github.com/widuu/gojson"
 )
 
@@ -260,6 +261,267 @@ var _ = Describe("MicroService Api Test", func() {
 			})
 
 			By("Test Dependency API for Provider and Consumer", func() {
+				It("test Valid dependency creation", func() {
+					//Register second microservice
+					getServiceName(serviceId)
+					schema := []string{"testSchema"}
+					properties := map[string]string{"attr1": "aa"}
+					consumerApp := strconv.Itoa(rand.Intn(15))
+					servicemap := map[string]interface{}{
+						"serviceName": consumerApp,
+						"appId":       "consumerAppId",
+						"version":     "2.0.0",
+						"description": "examples",
+						"level":       "FRONT",
+						"schemas":     schema,
+						"status":      "UP",
+						"properties":  properties,
+					}
+					bodyParams := map[string]interface{}{
+						"service": servicemap,
+					}
+					body, _ := json.Marshal(bodyParams)
+					bodyBuf := bytes.NewReader(body)
+					req, _ := http.NewRequest(POST, SCURL+REGISTERMICROSERVICE, bodyBuf)
+					req.Header.Set("X-Domain-Name", "default")
+					resp, err := scclient.Do(req)
+					Expect(err).To(BeNil())
+					defer resp.Body.Close()
+
+					// Validate the service creation
+					Expect(resp.StatusCode).To(Equal(http.StatusOK))
+					respbody, _ := ioutil.ReadAll(resp.Body)
+					consumerServiceID := gojson.Json(string(respbody)).Get("serviceId").Tostring()
+
+					//Create Dependency
+					consumer := map[string]string{
+						"appId":       "consumerAppId",
+						"serviceName": consumerApp,
+						"version":     "2.0.0",
+					}
+					provider := map[string]string{
+						"appId":       serviceAppId,
+						"serviceName": serviceName,
+						"version":     serviceVersion,
+					}
+					providersArray := []interface{}{provider}
+					dependency := map[string]interface{}{
+						"consumer":  consumer,
+						"providers": providersArray,
+					}
+					dependencyArray := []interface{}{dependency}
+					bodyParams = map[string]interface{}{
+						"dependencies": dependencyArray,
+					}
+					body, _ = json.Marshal(bodyParams)
+					bodyBuf = bytes.NewReader(body)
+					req, _ = http.NewRequest(UPDATE, SCURL+CREATEDEPENDENCIES, bodyBuf)
+					req.Header.Set("X-Domain-Name", "default")
+					resp, err = scclient.Do(req)
+					Expect(err).To(BeNil())
+					defer resp.Body.Close()
+
+					// Validate the dependency creation
+					Expect(resp.StatusCode).To(Equal(http.StatusOK))
+
+					/*
+						//Now try to delete the provider //this will fail as consumer needs to be deleted first
+						url := strings.Replace(UNREGISTERMICROSERVICE, ":serviceId", serviceId, 1)
+						req, _ = http.NewRequest(DELETE, SCURL+url, nil)
+						req.Header.Set("X-Domain-Name", "default")
+						resp, _ = scclient.Do(req)
+						Expect(resp.StatusCode).To(Equal(http.StatusBadRequest))*/
+
+					//Now delete consumer and then provider
+
+					url := strings.Replace(UNREGISTERMICROSERVICE, ":serviceId", consumerServiceID, 1)
+					req, _ = http.NewRequest(DELETE, SCURL+url, nil)
+					req.Header.Set("X-Domain-Name", "default")
+					resp, _ = scclient.Do(req)
+					Expect(resp.StatusCode).To(Equal(http.StatusOK))
+
+					url = strings.Replace(UNREGISTERMICROSERVICE, ":serviceId", serviceId, 1)
+					req, _ = http.NewRequest(DELETE, SCURL+url, nil)
+					req.Header.Set("X-Domain-Name", "default")
+					resp, _ = scclient.Do(req)
+					Expect(resp.StatusCode).To(Equal(http.StatusOK))
+					serviceId = ""
+
+				})
+
+				It("Get Dependencies for providers and consumers", func() {
+					getServiceName(serviceId)
+					schema := []string{"testSchema"}
+					properties := map[string]string{"attr1": "aa"}
+					consumerAppName := strconv.Itoa(rand.Intn(15))
+					servicemap := map[string]interface{}{
+						"serviceName": consumerAppName,
+						"appId":       "consumerAppId",
+						"version":     "2.0.0",
+						"description": "examples",
+						"level":       "FRONT",
+						"schemas":     schema,
+						"status":      "UP",
+						"properties":  properties,
+					}
+					bodyParams := map[string]interface{}{
+						"service": servicemap,
+					}
+					body, _ := json.Marshal(bodyParams)
+					bodyBuf := bytes.NewReader(body)
+					req, _ := http.NewRequest(POST, SCURL+REGISTERMICROSERVICE, bodyBuf)
+					req.Header.Set("X-Domain-Name", "default")
+					resp, err := scclient.Do(req)
+					Expect(err).To(BeNil())
+					defer resp.Body.Close()
+
+					// Validate the service creation
+					Expect(resp.StatusCode).To(Equal(http.StatusOK))
+					respbody, _ := ioutil.ReadAll(resp.Body)
+					consumerServiceID := gojson.Json(string(respbody)).Get("serviceId").Tostring()
+
+					//Create Dependency
+					consumer := map[string]string{
+						"appId":       "consumerAppId",
+						"serviceName": consumerAppName,
+						"version":     "2.0.0",
+					}
+					provider := map[string]string{
+						"appId":       serviceAppId,
+						"serviceName": serviceName,
+						"version":     serviceVersion,
+					}
+					providersArray := []interface{}{provider}
+					dependency := map[string]interface{}{
+						"consumer":  consumer,
+						"providers": providersArray,
+					}
+					dependencyArray := []interface{}{dependency}
+					bodyParams = map[string]interface{}{
+						"dependencies": dependencyArray,
+					}
+					body, _ = json.Marshal(bodyParams)
+					bodyBuf = bytes.NewReader(body)
+					req, _ = http.NewRequest(UPDATE, SCURL+CREATEDEPENDENCIES, bodyBuf)
+					req.Header.Set("X-Domain-Name", "default")
+					resp, err = scclient.Do(req)
+					Expect(err).To(BeNil())
+					defer resp.Body.Close()
+
+					// Validate the dependency creation
+					Expect(resp.StatusCode).To(Equal(http.StatusOK))
+
+					// add new dependency
+					dependency["providers"] = []interface{}{consumer}
+					body, _ = json.Marshal(bodyParams)
+					bodyBuf = bytes.NewReader(body)
+					req, _ = http.NewRequest(POST, SCURL+CREATEDEPENDENCIES, bodyBuf)
+					req.Header.Set("X-Domain-Name", "default")
+					resp, err = scclient.Do(req)
+					Expect(err).To(BeNil())
+					defer resp.Body.Close()
+
+					// Validate the dependency creation
+					Expect(resp.StatusCode).To(Equal(http.StatusOK))
+
+					//Get Provider by ConsumerID
+					<-time.After(time.Second)
+					url := strings.Replace(GETCONPRODEPENDENCY, ":consumerId", consumerServiceID, 1)
+					req, _ = http.NewRequest(GET, SCURL+url, nil)
+					req.Header.Set("X-Domain-Name", "default")
+					resp, _ = scclient.Do(req)
+					respbody, _ = ioutil.ReadAll(resp.Body)
+					Expect(resp.StatusCode).To(Equal(http.StatusOK))
+					servicesStruct := map[string][]map[string]interface{}{}
+
+					json.Unmarshal(respbody, &servicesStruct)
+					foundMicroService := false
+					for _, services := range servicesStruct["providers"] {
+						if services["serviceName"] == serviceName {
+							foundMicroService = true
+							break
+						}
+					}
+					Expect(foundMicroService).To(Equal(true))
+
+					//Get Consumer by ProviderID
+					url = strings.Replace(GETPROCONDEPENDENCY, ":providerId", serviceId, 1)
+					req, _ = http.NewRequest(GET, SCURL+url, nil)
+					req.Header.Set("X-Domain-Name", "default")
+					resp, _ = scclient.Do(req)
+					respbody, _ = ioutil.ReadAll(resp.Body)
+					Expect(resp.StatusCode).To(Equal(http.StatusOK))
+					servicesStruct = map[string][]map[string]interface{}{}
+
+					json.Unmarshal(respbody, &servicesStruct)
+					foundMicroService = false
+					for _, services := range servicesStruct["consumers"] {
+						if services["serviceName"] == consumerAppName {
+							foundMicroService = true
+							break
+						}
+					}
+					Expect(foundMicroService).To(Equal(true))
+
+					//Get new dependency by ConsumerID
+					url = strings.Replace(GETCONPRODEPENDENCY, ":consumerId", consumerServiceID, 1)
+					req, _ = http.NewRequest(GET, SCURL+url, nil)
+					req.Header.Set("X-Domain-Name", "default")
+					resp, _ = scclient.Do(req)
+					respbody, _ = ioutil.ReadAll(resp.Body)
+					Expect(resp.StatusCode).To(Equal(http.StatusOK))
+					servicesStruct = map[string][]map[string]interface{}{}
+
+					json.Unmarshal(respbody, &servicesStruct)
+					foundMicroService = false
+					for _, services := range servicesStruct["providers"] {
+						if services["serviceName"] == consumerAppName {
+							foundMicroService = true
+							break
+						}
+					}
+					Expect(foundMicroService).To(Equal(true))
+
+					// override the dependency
+					dependency["providers"] = []interface{}{}
+					body, _ = json.Marshal(bodyParams)
+					bodyBuf = bytes.NewReader(body)
+					req, _ = http.NewRequest(UPDATE, SCURL+CREATEDEPENDENCIES, bodyBuf)
+					req.Header.Set("X-Domain-Name", "default")
+					resp, err = scclient.Do(req)
+					Expect(err).To(BeNil())
+					defer resp.Body.Close()
+
+					// Validate the dependency creation
+					Expect(resp.StatusCode).To(Equal(http.StatusOK))
+
+					//Get Provider by ConsumerID again
+					<-time.After(time.Second)
+					url = strings.Replace(GETCONPRODEPENDENCY, ":consumerId", consumerServiceID, 1)
+					req, _ = http.NewRequest(GET, SCURL+url, nil)
+					req.Header.Set("X-Domain-Name", "default")
+					resp, _ = scclient.Do(req)
+					respbody, _ = ioutil.ReadAll(resp.Body)
+					Expect(resp.StatusCode).To(Equal(http.StatusOK))
+					servicesStruct = map[string][]map[string]interface{}{}
+					json.Unmarshal(respbody, &servicesStruct)
+					Expect(len(servicesStruct["providers"])).To(Equal(0))
+
+					//Delete Consumer and Provider
+					url = strings.Replace(UNREGISTERMICROSERVICE, ":serviceId", consumerServiceID, 1)
+					req, _ = http.NewRequest(DELETE, SCURL+url, nil)
+					req.Header.Set("X-Domain-Name", "default")
+					resp, _ = scclient.Do(req)
+					Expect(resp.StatusCode).To(Equal(http.StatusOK))
+
+					url = strings.Replace(UNREGISTERMICROSERVICE, ":serviceId", serviceId, 1)
+					req, _ = http.NewRequest(DELETE, SCURL+url, nil)
+					req.Header.Set("X-Domain-Name", "default")
+					resp, _ = scclient.Do(req)
+					Expect(resp.StatusCode).To(Equal(http.StatusOK))
+					serviceId = ""
+				})
+
 				It("Invalid scenario for GET Providers and Consumers", func() {
 					//Get Provider by ConsumerID
 					url := strings.Replace(GETCONPRODEPENDENCY, ":consumerId", "wrongID", 1)
diff --git a/pkg/proto/service.go b/pkg/proto/service.go
index 5767d98..1cf5faf 100644
--- a/pkg/proto/service.go
+++ b/pkg/proto/service.go
@@ -42,6 +42,8 @@ type ServiceCtrlServer interface {
 	DeleteSchema(context.Context, *discovery.DeleteSchemaRequest) (*discovery.DeleteSchemaResponse, error)
 	ModifySchema(context.Context, *discovery.ModifySchemaRequest) (*discovery.ModifySchemaResponse, error)
 	ModifySchemas(context.Context, *discovery.ModifySchemasRequest) (*discovery.ModifySchemasResponse, error)
+	AddDependenciesForMicroServices(context.Context, *discovery.AddDependenciesRequest) (*discovery.AddDependenciesResponse, error)
+	CreateDependenciesForMicroServices(context.Context, *discovery.CreateDependenciesRequest) (*discovery.CreateDependenciesResponse, error)
 	GetProviderDependencies(context.Context, *discovery.GetDependenciesRequest) (*discovery.GetProDependenciesResponse, error)
 	GetConsumerDependencies(context.Context, *discovery.GetDependenciesRequest) (*discovery.GetConDependenciesResponse, error)
 	DeleteServices(context.Context, *discovery.DelServicesRequest) (*discovery.DelServicesResponse, error)
diff --git a/server/rest/controller/v4/dependency_controller.go b/server/rest/controller/v4/dependency_controller.go
index d2607c4..a3791e8 100644
--- a/server/rest/controller/v4/dependency_controller.go
+++ b/server/rest/controller/v4/dependency_controller.go
@@ -18,9 +18,14 @@
 package v4
 
 import (
+	"encoding/json"
+	"fmt"
+	"io/ioutil"
 	"net/http"
 
+	"github.com/apache/servicecomb-service-center/pkg/log"
 	"github.com/apache/servicecomb-service-center/pkg/rest"
+	"github.com/apache/servicecomb-service-center/pkg/util"
 	"github.com/apache/servicecomb-service-center/server/core"
 	pb "github.com/go-chassis/cari/discovery"
 )
@@ -30,11 +35,61 @@ type DependencyService struct {
 
 func (s *DependencyService) URLPatterns() []rest.Route {
 	return []rest.Route{
+		{Method: http.MethodPost, Path: "/v4/:project/registry/dependencies", Func: s.AddDependenciesForMicroServices},
+		{Method: http.MethodPut, Path: "/v4/:project/registry/dependencies", Func: s.CreateDependenciesForMicroServices},
 		{Method: http.MethodGet, Path: "/v4/:project/registry/microservices/:consumerId/providers", Func: s.GetConProDependencies},
 		{Method: http.MethodGet, Path: "/v4/:project/registry/microservices/:providerId/consumers", Func: s.GetProConDependencies},
 	}
 }
 
+//Deprecated
+func (s *DependencyService) AddDependenciesForMicroServices(w http.ResponseWriter, r *http.Request) {
+	requestBody, err := ioutil.ReadAll(r.Body)
+	if err != nil {
+		log.Error("read body failed", err)
+		rest.WriteError(w, pb.ErrInvalidParams, err.Error())
+		return
+	}
+	request := &pb.AddDependenciesRequest{}
+	err = json.Unmarshal(requestBody, request)
+	if err != nil {
+		log.Error(fmt.Sprintf("invalid json: %s", util.BytesToStringWithNoCopy(requestBody)), err)
+		rest.WriteError(w, pb.ErrInvalidParams, err.Error())
+		return
+	}
+
+	resp, err := core.ServiceAPI.AddDependenciesForMicroServices(r.Context(), request)
+	if err != nil {
+		rest.WriteError(w, pb.ErrInternal, err.Error())
+	}
+	w.Header().Add("Deprecation", "version=\"v4\"")
+	rest.WriteResponse(w, r, resp.Response, nil)
+}
+
+//Deprecated
+func (s *DependencyService) CreateDependenciesForMicroServices(w http.ResponseWriter, r *http.Request) {
+	requestBody, err := ioutil.ReadAll(r.Body)
+	if err != nil {
+		log.Error("read body failed", err)
+		rest.WriteError(w, pb.ErrInvalidParams, err.Error())
+		return
+	}
+	request := &pb.CreateDependenciesRequest{}
+	err = json.Unmarshal(requestBody, request)
+	if err != nil {
+		log.Error(fmt.Sprintf("invalid json: %s", util.BytesToStringWithNoCopy(requestBody)), err)
+		rest.WriteError(w, pb.ErrInvalidParams, err.Error())
+		return
+	}
+
+	resp, err := core.ServiceAPI.CreateDependenciesForMicroServices(r.Context(), request)
+	if err != nil {
+		rest.WriteError(w, pb.ErrInternal, err.Error())
+	}
+	w.Header().Add("Deprecation", "version=\"v4\"")
+	rest.WriteResponse(w, r, resp.Response, nil)
+}
+
 func (s *DependencyService) GetConProDependencies(w http.ResponseWriter, r *http.Request) {
 	query := r.URL.Query()
 	request := &pb.GetDependenciesRequest{
diff --git a/server/service/disco/dependency.go b/server/service/disco/dependency.go
index ea083a6..4169829 100644
--- a/server/service/disco/dependency.go
+++ b/server/service/disco/dependency.go
@@ -26,6 +26,30 @@ import (
 	pb "github.com/go-chassis/cari/discovery"
 )
 
+func (s *MicroServiceService) AddDependenciesForMicroServices(ctx context.Context,
+	in *pb.AddDependenciesRequest) (*pb.AddDependenciesResponse, error) {
+	if err := validator.Validate(in); err != nil {
+		return &pb.AddDependenciesResponse{
+			Response: datasource.BadParamsResponse(err.Error()).Response,
+		}, nil
+	}
+
+	resp, err := datasource.GetDependencyManager().AddOrUpdateDependencies(ctx, in.Dependencies, false)
+	return &pb.AddDependenciesResponse{Response: resp}, err
+}
+
+func (s *MicroServiceService) CreateDependenciesForMicroServices(ctx context.Context,
+	in *pb.CreateDependenciesRequest) (*pb.CreateDependenciesResponse, error) {
+	if err := validator.Validate(in); err != nil {
+		return &pb.CreateDependenciesResponse{
+			Response: datasource.BadParamsResponse(err.Error()).Response,
+		}, nil
+	}
+
+	resp, err := datasource.GetDependencyManager().AddOrUpdateDependencies(ctx, in.Dependencies, true)
+	return &pb.CreateDependenciesResponse{Response: resp}, err
+}
+
 func (s *MicroServiceService) GetProviderDependencies(ctx context.Context,
 	in *pb.GetDependenciesRequest) (*pb.GetProDependenciesResponse, error) {
 	err := validator.Validate(in)
diff --git a/server/service/disco/dependency_test.go b/server/service/disco/dependency_test.go
index 4bcae90..ea9a41d 100644
--- a/server/service/disco/dependency_test.go
+++ b/server/service/disco/dependency_test.go
@@ -17,21 +17,436 @@
 package disco_test
 
 import (
+	"strconv"
+
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
 
-	"github.com/apache/servicecomb-service-center/datasource/etcd/event"
-	"github.com/apache/servicecomb-service-center/datasource/etcd/path"
-	"github.com/apache/servicecomb-service-center/datasource/etcd/sd"
+	"github.com/apache/servicecomb-service-center/datasource"
 	"github.com/apache/servicecomb-service-center/server/service/disco"
 	pb "github.com/go-chassis/cari/discovery"
-	"github.com/go-chassis/go-archaius"
-	"github.com/little-cui/etcdadpt"
 )
 
-var deh event.DependencyEventHandler
-
 var _ = Describe("'Dependency' service", func() {
+	Describe("execute 'create' operation", func() {
+		var (
+			consumerId1 string
+			consumerId2 string
+		)
+
+		It("should be passed", func() {
+			respCreateService, err := serviceResource.Create(getContext(), &pb.CreateServiceRequest{
+				Service: &pb.MicroService{
+					AppId:       "create_dep_group",
+					ServiceName: "create_dep_consumer",
+					Version:     "1.0.0",
+					Level:       "FRONT",
+					Status:      pb.MS_UP,
+				},
+			})
+			Expect(err).To(BeNil())
+			Expect(respCreateService.Response.GetCode()).To(Equal(pb.ResponseSuccess))
+			consumerId1 = respCreateService.ServiceId
+
+			respCreateService, err = serviceResource.Create(getContext(), &pb.CreateServiceRequest{
+				Service: &pb.MicroService{
+					Environment: pb.ENV_PROD,
+					AppId:       "create_dep_group",
+					ServiceName: "create_dep_consumer",
+					Version:     "1.0.0",
+					Level:       "FRONT",
+					Status:      pb.MS_UP,
+				},
+			})
+			Expect(err).To(BeNil())
+			Expect(respCreateService.Response.GetCode()).To(Equal(pb.ResponseSuccess))
+			consumerId2 = respCreateService.ServiceId
+
+			respCreateService, err = serviceResource.Create(getContext(), &pb.CreateServiceRequest{
+				Service: &pb.MicroService{
+					AppId:       "create_dep_group",
+					ServiceName: "create_dep_provider",
+					Version:     "1.0.0",
+					Level:       "FRONT",
+					Status:      pb.MS_UP,
+				},
+			})
+			Expect(err).To(BeNil())
+			Expect(respCreateService.Response.GetCode()).To(Equal(pb.ResponseSuccess))
+
+			respCreateService, err = serviceResource.Create(getContext(), &pb.CreateServiceRequest{
+				Service: &pb.MicroService{
+					AppId:       "create_dep_group",
+					ServiceName: "create_dep_provider",
+					Version:     "1.0.1",
+					Level:       "FRONT",
+					Status:      pb.MS_UP,
+				},
+			})
+			Expect(err).To(BeNil())
+			Expect(respCreateService.Response.GetCode()).To(Equal(pb.ResponseSuccess))
+
+			respCreateService, err = serviceResource.Create(getContext(), &pb.CreateServiceRequest{
+				Service: &pb.MicroService{
+					Environment: pb.ENV_PROD,
+					AppId:       "create_dep_group",
+					ServiceName: "create_dep_provider",
+					Version:     "1.0.0",
+					Level:       "FRONT",
+					Status:      pb.MS_UP,
+				},
+			})
+			Expect(err).To(BeNil())
+			Expect(respCreateService.Response.GetCode()).To(Equal(pb.ResponseSuccess))
+
+			respCreateService, err = serviceResource.Create(getContext(), &pb.CreateServiceRequest{
+				Service: &pb.MicroService{
+					AppId:       "create_dep_group",
+					ServiceName: "create_dep_provider_other",
+					Version:     "1.0.0",
+					Level:       "FRONT",
+					Status:      pb.MS_UP,
+				},
+			})
+			Expect(err).To(BeNil())
+			Expect(respCreateService.Response.GetCode()).To(Equal(pb.ResponseSuccess))
+		})
+
+		Context("when request is invalid", func() {
+			It("should be failed", func() {
+				By("dependency is nil")
+				respCreateDependency, err := serviceResource.CreateDependenciesForMicroServices(getContext(), &pb.CreateDependenciesRequest{})
+				Expect(err).To(BeNil())
+				Expect(respCreateDependency.Response.GetCode()).ToNot(Equal(pb.ResponseSuccess))
+
+				consumer := &pb.MicroServiceKey{
+					AppId:       "create_dep_group",
+					ServiceName: "create_dep_consumer",
+					Version:     "1.0.0",
+				}
+				providers := []*pb.MicroServiceKey{
+					{
+						AppId:       "create_dep_group",
+						ServiceName: "create_dep_provider",
+					},
+				}
+
+				By("consumer does not exist")
+				respCreateDependency, err = serviceResource.CreateDependenciesForMicroServices(getContext(), &pb.CreateDependenciesRequest{
+					Dependencies: []*pb.ConsumerDependency{
+						{
+							Consumer: &pb.MicroServiceKey{
+								AppId:       "noexistapp",
+								ServiceName: "noexistservice",
+								Version:     "1.0.0",
+							},
+							Providers: providers,
+						},
+					},
+				})
+				Expect(err).To(BeNil())
+				Expect(respCreateDependency.Response.GetCode()).ToNot(Equal(pb.ResponseSuccess))
+
+				By("provider version is invalid")
+				respCreateDependency, err = serviceResource.CreateDependenciesForMicroServices(getContext(), &pb.CreateDependenciesRequest{
+					Dependencies: []*pb.ConsumerDependency{
+						{
+							Consumer: consumer,
+							Providers: []*pb.MicroServiceKey{
+								{
+									AppId:       "create_dep_group",
+									ServiceName: "",
+								},
+							},
+						},
+					},
+				})
+				Expect(err).To(BeNil())
+				Expect(respCreateDependency.Response.GetCode()).To(Equal(pb.ErrInvalidParams))
+
+				By("consumer version is invalid")
+				respCreateDependency, err = serviceResource.CreateDependenciesForMicroServices(getContext(), &pb.CreateDependenciesRequest{
+					Dependencies: []*pb.ConsumerDependency{
+						{
+							Consumer: &pb.MicroServiceKey{
+								AppId:       "create_dep_group",
+								ServiceName: "create_dep_consumer",
+								Version:     "1.0.0+",
+							},
+							Providers: providers,
+						},
+					},
+				})
+				Expect(err).To(BeNil())
+				Expect(respCreateDependency.Response.GetCode()).To(Equal(pb.ErrInvalidParams))
+				respCreateDependency, err = serviceResource.CreateDependenciesForMicroServices(getContext(), &pb.CreateDependenciesRequest{
+					Dependencies: []*pb.ConsumerDependency{
+						{
+							Consumer: &pb.MicroServiceKey{
+								AppId:       "create_dep_group",
+								ServiceName: "create_dep_consumer",
+								Version:     "1.0.0-1.0.1",
+							},
+							Providers: providers,
+						},
+					},
+				})
+				Expect(err).To(BeNil())
+				Expect(respCreateDependency.Response.GetCode()).To(Equal(pb.ErrInvalidParams))
+				respCreateDependency, err = serviceResource.CreateDependenciesForMicroServices(getContext(), &pb.CreateDependenciesRequest{
+					Dependencies: []*pb.ConsumerDependency{
+						{
+							Consumer: &pb.MicroServiceKey{
+								AppId:       "create_dep_group",
+								ServiceName: "create_dep_consumer",
+								Version:     "latest",
+							},
+							Providers: providers,
+						},
+					},
+				})
+				Expect(err).To(BeNil())
+				Expect(respCreateDependency.Response.GetCode()).To(Equal(pb.ErrInvalidParams))
+				respCreateDependency, err = serviceResource.CreateDependenciesForMicroServices(getContext(), &pb.CreateDependenciesRequest{
+					Dependencies: []*pb.ConsumerDependency{
+						{
+							Consumer: &pb.MicroServiceKey{
+								AppId:       "create_dep_group",
+								ServiceName: "create_dep_consumer",
+								Version:     "",
+							},
+							Providers: providers,
+						},
+					},
+				})
+				Expect(err).To(BeNil())
+				Expect(respCreateDependency.Response.GetCode()).To(Equal(pb.ErrInvalidParams))
+				respCreateDependency, err = serviceResource.CreateDependenciesForMicroServices(getContext(), &pb.CreateDependenciesRequest{
+					Dependencies: []*pb.ConsumerDependency{
+						{
+							Consumer: &pb.MicroServiceKey{
+								AppId:       "create_dep_group",
+								ServiceName: "create_dep_consumer",
+								Version:     "1.0.32768",
+							},
+							Providers: providers,
+						},
+					},
+				})
+				Expect(err).To(BeNil())
+				Expect(respCreateDependency.Response.GetCode()).To(Equal(pb.ErrInvalidParams))
+
+				By("consumer serviceName is invalid")
+				respCreateDependency, err = serviceResource.CreateDependenciesForMicroServices(getContext(), &pb.CreateDependenciesRequest{
+					Dependencies: []*pb.ConsumerDependency{
+						{
+							Consumer: &pb.MicroServiceKey{
+								AppId:       "create_dep_group",
+								ServiceName: "*",
+								Version:     "1.0.0",
+							},
+							Providers: providers,
+						},
+					},
+				})
+				Expect(err).To(BeNil())
+				Expect(respCreateDependency.Response.GetCode()).ToNot(Equal(pb.ResponseSuccess))
+
+				By("provider app is invalid")
+				respCreateDependency, err = serviceResource.CreateDependenciesForMicroServices(getContext(), &pb.CreateDependenciesRequest{
+					Dependencies: []*pb.ConsumerDependency{
+						{
+							Consumer: consumer,
+							Providers: []*pb.MicroServiceKey{
+								{
+									AppId:       "*",
+									ServiceName: "service_name_provider",
+									Version:     "2.0.0",
+								},
+							},
+						},
+					},
+				})
+				Expect(err).To(BeNil())
+				Expect(respCreateDependency.Response.GetCode()).ToNot(Equal(pb.ResponseSuccess))
+
+				By("provider serviceName is invalid")
+				respCreateDependency, err = serviceResource.CreateDependenciesForMicroServices(getContext(), &pb.CreateDependenciesRequest{
+					Dependencies: []*pb.ConsumerDependency{
+						{
+							Consumer: consumer,
+							Providers: []*pb.MicroServiceKey{
+								{
+									AppId:       "service_group_provider",
+									ServiceName: "-",
+									Version:     "2.0.0",
+								},
+							},
+						},
+					},
+				})
+				Expect(err).To(BeNil())
+				Expect(respCreateDependency.Response.GetCode()).ToNot(Equal(pb.ResponseSuccess))
+
+				By("provider in diff env")
+				respCreateDependency, err = serviceResource.CreateDependenciesForMicroServices(getContext(), &pb.CreateDependenciesRequest{
+					Dependencies: []*pb.ConsumerDependency{
+						{
+							Consumer: consumer,
+							Providers: []*pb.MicroServiceKey{
+								{
+									Environment: pb.ENV_PROD,
+									AppId:       "service_group_provider",
+									ServiceName: "service_name_provider",
+								},
+							},
+						},
+					},
+				})
+				Expect(err).To(BeNil())
+				Expect(respCreateDependency.Response.GetCode()).To(Equal(pb.ResponseSuccess))
+
+				By("consumer in diff env")
+				consumer.Environment = pb.ENV_PROD
+				respCreateDependency, err = serviceResource.CreateDependenciesForMicroServices(getContext(), &pb.CreateDependenciesRequest{
+					Dependencies: []*pb.ConsumerDependency{
+						{
+							Consumer: consumer,
+							Providers: []*pb.MicroServiceKey{
+								{
+									AppId:       "service_group_provider",
+									ServiceName: "service_name_provider",
+								},
+							},
+						},
+					},
+				})
+				Expect(err).To(BeNil())
+				Expect(respCreateDependency.Response.GetCode()).To(Equal(pb.ResponseSuccess))
+
+				DependencyHandle()
+
+				respCon, err := serviceResource.GetConsumerDependencies(getContext(), &pb.GetDependenciesRequest{
+					ServiceId: consumerId1,
+				})
+				Expect(err).To(BeNil())
+				Expect(respCon.Response.GetCode()).To(Equal(pb.ResponseSuccess))
+				Expect(len(respCon.Providers)).To(Equal(0))
+
+				respCon, err = serviceResource.GetConsumerDependencies(getContext(), &pb.GetDependenciesRequest{
+					ServiceId: consumerId2,
+				})
+				Expect(err).To(BeNil())
+				Expect(respCon.Response.GetCode()).To(Equal(pb.ResponseSuccess))
+				Expect(len(respCon.Providers)).To(Equal(0))
+
+				By("dependencies is invalid")
+				var deps []*pb.ConsumerDependency
+				for i := 0; i < 101; i++ {
+					deps = append(deps, &pb.ConsumerDependency{
+						Consumer: &pb.MicroServiceKey{
+							AppId:       "create_dep_group",
+							ServiceName: "create_dep_consumer" + strconv.Itoa(i),
+							Version:     "1.0.0",
+						},
+						Providers: []*pb.MicroServiceKey{
+							{
+								AppId:       "service_group_provider",
+								ServiceName: "service_name_provider",
+							},
+						},
+					})
+				}
+				respCreateDependency, err = serviceResource.CreateDependenciesForMicroServices(getContext(), &pb.CreateDependenciesRequest{
+					Dependencies: deps,
+				})
+				Expect(err).To(BeNil())
+				Expect(respCreateDependency.Response.GetCode()).To(Equal(pb.ErrInvalidParams))
+			})
+		})
+
+		Context("when request is valid", func() {
+			It("should be passed", func() {
+				consumer := &pb.MicroServiceKey{
+					ServiceName: "create_dep_consumer",
+					AppId:       "create_dep_group",
+					Version:     "1.0.0",
+				}
+
+				respCreateDependency, err := serviceResource.CreateDependenciesForMicroServices(getContext(), &pb.CreateDependenciesRequest{
+					Dependencies: []*pb.ConsumerDependency{
+						{
+							Consumer: consumer,
+							Providers: []*pb.MicroServiceKey{
+								{
+									AppId:       "create_dep_group",
+									ServiceName: "create_dep_provider",
+								},
+							},
+						},
+					},
+				})
+				Expect(err).To(BeNil())
+				Expect(respCreateDependency.Response.GetCode()).To(Equal(pb.ResponseSuccess))
+
+				DependencyHandle()
+
+				respPro, err := serviceResource.GetConsumerDependencies(getContext(), &pb.GetDependenciesRequest{
+					ServiceId: consumerId1,
+				})
+				Expect(err).To(BeNil())
+				Expect(respPro.Response.GetCode()).To(Equal(pb.ResponseSuccess))
+				Expect(len(respPro.Providers)).To(Equal(2))
+
+				respAddDependency, err := serviceResource.AddDependenciesForMicroServices(getContext(), &pb.AddDependenciesRequest{
+					Dependencies: []*pb.ConsumerDependency{
+						{
+							Consumer: consumer,
+							Providers: []*pb.MicroServiceKey{
+								{
+									AppId:       "create_dep_group",
+									ServiceName: "create_dep_provider_other",
+								},
+							},
+						},
+					},
+				})
+				Expect(err).To(BeNil())
+				Expect(respAddDependency.Response.GetCode()).To(Equal(pb.ResponseSuccess))
+
+				DependencyHandle()
+
+				respPro, err = serviceResource.GetConsumerDependencies(getContext(), &pb.GetDependenciesRequest{
+					ServiceId: consumerId1,
+				})
+				Expect(err).To(BeNil())
+				Expect(respPro.Response.GetCode()).To(Equal(pb.ResponseSuccess))
+				Expect(len(respPro.Providers)).To(Equal(3))
+
+				By("clean all")
+				respCreateDependency, err = serviceResource.CreateDependenciesForMicroServices(getContext(), &pb.CreateDependenciesRequest{
+					Dependencies: []*pb.ConsumerDependency{
+						{
+							Consumer:  consumer,
+							Providers: nil,
+						},
+					},
+				})
+				Expect(err).To(BeNil())
+				Expect(respCreateDependency.Response.GetCode()).To(Equal(pb.ResponseSuccess))
+
+				DependencyHandle()
+
+				respPro, err = serviceResource.GetConsumerDependencies(getContext(), &pb.GetDependenciesRequest{
+					ServiceId: consumerId1,
+				})
+				Expect(err).To(BeNil())
+				Expect(respPro.Response.GetCode()).To(Equal(pb.ResponseSuccess))
+				Expect(len(respPro.Providers)).To(Equal(0))
+			})
+		})
+	})
+
 	Describe("execute 'get' operation", func() {
 		var (
 			consumerId1 string
@@ -279,24 +694,6 @@ var _ = Describe("'Dependency' service", func() {
 })
 
 func DependencyHandle() {
-	t := archaius.Get("TEST_MODE")
-	if t == nil {
-		t = "etcd"
-	}
-	if t == "etcd" {
-		for {
-			Expect(deh.Handle()).To(BeNil())
-
-			key := path.GetServiceDependencyQueueRootKey("")
-			resp, err := sd.DependencyQueue().Search(getContext(),
-				etcdadpt.WithStrKey(key), etcdadpt.WithPrefix(), etcdadpt.WithCountOnly())
-
-			Expect(err).To(BeNil())
-
-			// maintain dependency rules.
-			if resp.Count == 0 {
-				break
-			}
-		}
-	}
+	err := datasource.GetDependencyManager().DependencyHandle(getContext())
+	Expect(err).To(BeNil())
 }
diff --git a/server/service/validator/dependency_validator.go b/server/service/validator/dependency_validator.go
new file mode 100644
index 0000000..7a349b3
--- /dev/null
+++ b/server/service/validator/dependency_validator.go
@@ -0,0 +1,70 @@
+/*
+ * 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 validator
+
+import (
+	"regexp"
+
+	"github.com/apache/servicecomb-service-center/pkg/validate"
+)
+
+var (
+	addDependenciesReqValidator       validate.Validator
+	overwriteDependenciesReqValidator validate.Validator
+)
+
+var versionAllowEmptyRegex, _ = regexp.Compile(`^(^\d+(\.\d+){0,2}\+?$|^\d+(\.\d+){0,2}-\d+(\.\d+){0,2}$|^latest$)?$`)
+
+func defaultDependencyValidator() *validate.Validator {
+	appIDRule := *(MicroServiceKeyValidator().GetRule("AppId"))
+	appIDRule.Min = 0
+	versionRule := &validate.Rule{Max: 128, Regexp: &validate.VersionRegexp{Fuzzy: true, Regex: versionAllowEmptyRegex}}
+
+	var (
+		consumerMsValidator validate.Validator
+		providerMsValidator validate.Validator
+	)
+	consumerMsValidator.AddRules(MicroServiceKeyValidator().GetRules())
+
+	providerMsValidator.AddRules(MicroServiceKeyValidator().GetRules())
+	providerMsValidator.AddRule("AppId", &appIDRule)
+	providerMsValidator.AddRule("Version", versionRule)
+
+	var dependenciesValidator validate.Validator
+	dependenciesValidator.AddRule("Consumer", &validate.Rule{Min: 1})
+	dependenciesValidator.AddSub("Consumer", &consumerMsValidator)
+	dependenciesValidator.AddSub("Providers", &providerMsValidator)
+
+	return &dependenciesValidator
+}
+
+func AddDependenciesReqValidator() *validate.Validator {
+	return addDependenciesReqValidator.Init(func(v *validate.Validator) {
+		dep := defaultDependencyValidator()
+		dep.AddRule("Providers", &validate.Rule{Min: 1})
+		v.AddRule("Dependencies", &validate.Rule{Min: 1, Max: 100})
+		v.AddSub("Dependencies", dep)
+	})
+}
+
+func CreateDependenciesReqValidator() *validate.Validator {
+	return overwriteDependenciesReqValidator.Init(func(v *validate.Validator) {
+		v.AddRule("Dependencies", &validate.Rule{Min: 1, Max: 100})
+		v.AddSub("Dependencies", defaultDependencyValidator())
+	})
+}
diff --git a/server/service/validator/validator.go b/server/service/validator/validator.go
index 055fc24..2b1c0be 100644
--- a/server/service/validator/validator.go
+++ b/server/service/validator/validator.go
@@ -65,6 +65,10 @@ func Validate(v interface{}) error {
 		*pb.DeleteServiceRequest,
 		*pb.GetDependenciesRequest:
 		return GetServiceReqValidator().Validate(v)
+	case *pb.CreateDependenciesRequest:
+		return CreateDependenciesReqValidator().Validate(v)
+	case *pb.AddDependenciesRequest:
+		return AddDependenciesReqValidator().Validate(v)
 	case *pb.UpdateServicePropsRequest:
 		return UpdateServicePropsReqValidator().Validate(v)
 	case *pb.GetServiceTagsRequest: