diff --git a/cluster/directory/base_directory.go b/cluster/directory/base_directory.go
index 8a7e0c0e8359c69faf0e504adeb1778c38a08e04..651c90ff6862bd75e604b0572bb15e583a00065e 100644
--- a/cluster/directory/base_directory.go
+++ b/cluster/directory/base_directory.go
@@ -85,15 +85,21 @@ func (dir *BaseDirectory) SetRouters(urls []*common.URL) {
 	for _, url := range urls {
 		routerKey := url.GetParam(constant.ROUTER_KEY, "")
 
-		if len(routerKey) > 0 {
-			factory := extension.GetRouterFactory(url.Protocol)
-			r, err := factory.NewPriorityRouter(url)
-			if err != nil {
-				logger.Errorf("Create router fail. router key: %s, url:%s, error: %+v", routerKey, url.Service(), err)
-				return
+		if len(routerKey) == 0 {
+			continue
+		}
+		if url.Protocol == constant.CONDITION_ROUTE_PROTOCOL {
+			if !dir.isProperRouter(url) {
+				continue
 			}
-			routers = append(routers, r)
 		}
+		factory := extension.GetRouterFactory(url.Protocol)
+		r, err := factory.NewPriorityRouter(url)
+		if err != nil {
+			logger.Errorf("Create router fail. router key: %s, url:%s, error: %+v", routerKey, url.Service(), err)
+			return
+		}
+		routers = append(routers, r)
 	}
 
 	logger.Infof("Init file condition router success, size: %v", len(routers))
@@ -104,6 +110,21 @@ func (dir *BaseDirectory) SetRouters(urls []*common.URL) {
 	rc.AddRouters(routers)
 }
 
+func (dir *BaseDirectory) isProperRouter(url *common.URL) bool {
+	app := url.GetParam(constant.APPLICATION_KEY, "")
+	serviceKey := dir.GetUrl().ServiceKey()
+	if serviceKey == "" {
+		serviceKey = dir.GetUrl().SubURL.ServiceKey()
+	}
+	if len(app) > 0 && app == dir.GetUrl().GetParam(constant.APPLICATION_KEY, "") {
+		return true
+	}
+	if url.ServiceKey() == serviceKey {
+		return true
+	}
+	return false
+}
+
 // Destroy Destroy
 func (dir *BaseDirectory) Destroy(doDestroy func()) {
 	if dir.destroyed.CAS(false, true) {
diff --git a/cluster/directory/base_directory_test.go b/cluster/directory/base_directory_test.go
index 8b60163b79b7120829e51f69238474a127133fb4..a2b62dfa008e6cd17b1200d93cd235da17d03905 100644
--- a/cluster/directory/base_directory_test.go
+++ b/cluster/directory/base_directory_test.go
@@ -37,7 +37,7 @@ import (
 var (
 	url, _ = common.NewURL(
 		fmt.Sprintf("dubbo://%s:%d/com.ikurento.user.UserProvider", constant.LOCAL_HOST_VALUE, constant.DEFAULT_PORT))
-	anyUrl, _ = common.NewURL(fmt.Sprintf("condition://%s/com.foo.BarService", constant.ANYHOST_VALUE))
+	anyURL, _ = common.NewURL(fmt.Sprintf("condition://%s/com.foo.BarService", constant.ANYHOST_VALUE))
 )
 
 func TestNewBaseDirectory(t *testing.T) {
@@ -48,13 +48,17 @@ func TestNewBaseDirectory(t *testing.T) {
 }
 
 func TestBuildRouterChain(t *testing.T) {
-	directory := NewBaseDirectory(&url)
+
+	regURL := url
+	regURL.AddParam(constant.INTERFACE_KEY, "mock-app")
+	directory := NewBaseDirectory(&regURL)
 
 	assert.NotNil(t, directory)
 
 	localIP, _ := gxnet.GetLocalIP()
 	rule := base64.URLEncoding.EncodeToString([]byte("true => " + " host = " + localIP))
-	routeURL := getRouteUrl(rule)
+	routeURL := getRouteURL(rule, anyURL)
+	routeURL.AddParam(constant.INTERFACE_KEY, "mock-app")
 	routerURLs := make([]*common.URL, 0)
 	routerURLs = append(routerURLs, routeURL)
 	directory.SetRouters(routerURLs)
@@ -63,9 +67,53 @@ func TestBuildRouterChain(t *testing.T) {
 	assert.NotNil(t, chain)
 }
 
-func getRouteUrl(rule string) *common.URL {
-	anyUrl.AddParam("rule", rule)
-	anyUrl.AddParam("force", "true")
-	anyUrl.AddParam(constant.ROUTER_KEY, "router")
-	return &url
+func getRouteURL(rule string, u common.URL) *common.URL {
+	ru := u
+	ru.AddParam("rule", rule)
+	ru.AddParam("force", "true")
+	ru.AddParam(constant.ROUTER_KEY, "router")
+	return &ru
+}
+
+func TestIsProperRouter(t *testing.T) {
+	regURL := url
+	regURL.AddParam(constant.APPLICATION_KEY, "mock-app")
+	d := NewBaseDirectory(&regURL)
+	localIP, _ := gxnet.GetLocalIP()
+	rule := base64.URLEncoding.EncodeToString([]byte("true => " + " host = " + localIP))
+	routeURL := getRouteURL(rule, anyURL)
+	routeURL.AddParam(constant.APPLICATION_KEY, "mock-app")
+	rst := d.isProperRouter(routeURL)
+	assert.True(t, rst)
+
+	regURL.AddParam(constant.APPLICATION_KEY, "")
+	regURL.AddParam(constant.INTERFACE_KEY, "com.foo.BarService")
+	d = NewBaseDirectory(&regURL)
+	routeURL = getRouteURL(rule, anyURL)
+	routeURL.AddParam(constant.INTERFACE_KEY, "com.foo.BarService")
+	rst = d.isProperRouter(routeURL)
+	assert.True(t, rst)
+
+	regURL.AddParam(constant.APPLICATION_KEY, "")
+	regURL.AddParam(constant.INTERFACE_KEY, "")
+	d = NewBaseDirectory(&regURL)
+	routeURL = getRouteURL(rule, anyURL)
+	rst = d.isProperRouter(routeURL)
+	assert.True(t, rst)
+
+	regURL.SetParam(constant.APPLICATION_KEY, "")
+	regURL.SetParam(constant.INTERFACE_KEY, "")
+	d = NewBaseDirectory(&regURL)
+	routeURL = getRouteURL(rule, anyURL)
+	routeURL.AddParam(constant.APPLICATION_KEY, "mock-service")
+	rst = d.isProperRouter(routeURL)
+	assert.False(t, rst)
+
+	regURL.SetParam(constant.APPLICATION_KEY, "")
+	regURL.SetParam(constant.INTERFACE_KEY, "")
+	d = NewBaseDirectory(&regURL)
+	routeURL = getRouteURL(rule, anyURL)
+	routeURL.AddParam(constant.INTERFACE_KEY, "mock-service")
+	rst = d.isProperRouter(routeURL)
+	assert.False(t, rst)
 }
diff --git a/cluster/router/chain/chain_test.go b/cluster/router/chain/chain_test.go
index c1f723525f5307e7732f0ea1ecc27eca7ba09c8d..065f0e49d9a2a465c7bb26a9541b34ad569bb93a 100644
--- a/cluster/router/chain/chain_test.go
+++ b/cluster/router/chain/chain_test.go
@@ -66,7 +66,9 @@ func TestNewRouterChain(t *testing.T) {
 	err = z.Create(path)
 	assert.NoError(t, err)
 
-	testyml := `enabled: true
+	testyml := `scope: application
+key: mock-app
+enabled: true
 force: true
 runtime: false
 conditions:
@@ -93,7 +95,7 @@ conditions:
 	assert.NotNil(t, appRouter)
 	assert.NotNil(t, appRouter.RouterRule())
 	rule := appRouter.RouterRule()
-	assert.Equal(t, "", rule.Scope)
+	assert.Equal(t, "application", rule.Scope)
 	assert.True(t, rule.Force)
 	assert.True(t, rule.Enabled)
 	assert.True(t, rule.Valid)
@@ -101,7 +103,7 @@ conditions:
 	assert.Equal(t, testyml, rule.RawRule)
 	assert.Equal(t, false, rule.Runtime)
 	assert.Equal(t, false, rule.Dynamic)
-	assert.Equal(t, "", rule.Key)
+	assert.Equal(t, "mock-app", rule.Key)
 }
 
 func TestNewRouterChainURLNil(t *testing.T) {
@@ -116,7 +118,9 @@ func TestRouterChainAddRouters(t *testing.T) {
 	err = z.Create(path)
 	assert.NoError(t, err)
 
-	testyml := `enabled: true
+	testyml := `scope: application
+key: mock-app
+enabled: true
 force: true
 runtime: false
 conditions:
@@ -182,7 +186,9 @@ func TestRouterChainRouteAppRouter(t *testing.T) {
 	err = z.Create(path)
 	assert.NoError(t, err)
 
-	testyml := `enabled: true
+	testyml := `scope: application
+key: mock-app
+enabled: true
 force: true
 runtime: false
 conditions:
diff --git a/cluster/router/condition/app_router_test.go b/cluster/router/condition/app_router_test.go
index 8b38f2dd6136b4d31f46e7214c0ad1359537b198..53465f90516fed1d5cf94b8ecc077cbfde6c743f 100644
--- a/cluster/router/condition/app_router_test.go
+++ b/cluster/router/condition/app_router_test.go
@@ -52,7 +52,9 @@ var (
 
 func TestNewAppRouter(t *testing.T) {
 
-	testYML := `enabled: true
+	testYML := `scope: application
+key: mock-app
+enabled: true
 force: true
 runtime: false
 conditions:
@@ -83,7 +85,7 @@ conditions:
 	assert.NotNil(t, appRouter)
 	assert.NotNil(t, appRouter.RouterRule())
 	rule := appRouter.RouterRule()
-	assert.Equal(t, "", rule.Scope)
+	assert.Equal(t, "application", rule.Scope)
 	assert.True(t, rule.Force)
 	assert.True(t, rule.Enabled)
 	assert.True(t, rule.Valid)
@@ -91,13 +93,15 @@ conditions:
 	assert.Equal(t, testYML, rule.RawRule)
 	assert.Equal(t, false, rule.Runtime)
 	assert.Equal(t, false, rule.Dynamic)
-	assert.Equal(t, "", rule.Key)
+	assert.Equal(t, "mock-app", rule.Key)
 	assert.Equal(t, 0, rule.Priority)
 }
 
 func TestGenerateConditions(t *testing.T) {
 
-	testYML := `enabled: true
+	testYML := `scope: application
+key: mock-app
+enabled: true
 force: true
 runtime: false
 conditions:
@@ -135,7 +139,9 @@ conditions:
 
 func TestProcess(t *testing.T) {
 
-	testYML := `enabled: true
+	testYML := `scope: application
+key: mock-app
+enabled: true
 force: true
 runtime: false
 conditions:
@@ -165,7 +171,8 @@ conditions:
 
 	assert.Equal(t, 1, len(appRouter.conditionRouters))
 
-	testNewYML := `
+	testNewYML := `scope: application
+key: mock-app
 enabled: true
 force: true
 runtime: false
diff --git a/cluster/router/condition/file.go b/cluster/router/condition/file.go
index eabdf1c263446140b359b3e791238b020cecb50c..996db7443faff88d3baa1a2363f98fa62623d121 100644
--- a/cluster/router/condition/file.go
+++ b/cluster/router/condition/file.go
@@ -20,6 +20,7 @@ package condition
 import (
 	"encoding/base64"
 	"net/url"
+	"regexp"
 	"strconv"
 	"strings"
 	"sync"
@@ -71,11 +72,53 @@ func (f *FileConditionRouter) URL() common.URL {
 			common.WithParamsValue(constant.RouterPriority, strconv.Itoa(routerRule.Priority)),
 			common.WithParamsValue(constant.RULE_KEY, base64.URLEncoding.EncodeToString([]byte(rule))),
 			common.WithParamsValue(constant.ROUTER_KEY, constant.CONDITION_ROUTE_PROTOCOL),
-			common.WithParamsValue(constant.CATEGORY_KEY, constant.ROUTERS_CATEGORY))
+			common.WithParamsValue(constant.CATEGORY_KEY, constant.ROUTERS_CATEGORY),
+		)
+		if routerRule.Scope == constant.RouterApplicationScope {
+			f.url.AddParam(constant.APPLICATION_KEY, routerRule.Key)
+			return
+		}
+		grp, srv, ver, e := parseServiceRouterKey(routerRule.Key)
+		if e != nil {
+			return
+		}
+		if len(grp) > 0 {
+			f.url.AddParam(constant.GROUP_KEY, grp)
+		}
+		if len(ver) > 0 {
+			f.url.AddParam(constant.VERSION_KEY, ver)
+		}
+		if len(srv) > 0 {
+			f.url.AddParam(constant.INTERFACE_KEY, srv)
+		}
 	})
 	return f.url
 }
 
+// The input value must follow [{group}/]{service}[:{version}] pattern
+// the returning strings are representing group, service, version respectively.
+// input: mock-group/mock-service:1.0.0 ==> "mock-group", "mock-service", "1.0.0"
+// input: mock-group/mock-service ==> "mock-group", "mock-service", ""
+// input: mock-service:1.0.0 ==> "", "mock-service", "1.0.0"
+// For more samples, please refer to unit test.
+func parseServiceRouterKey(key string) (string, string, string, error) {
+	if len(strings.TrimSpace(key)) == 0 {
+		return "", "", "", nil
+	}
+	reg := regexp.MustCompile(`(.*/{1})?([^:/]+)(:{1}[^:]*)?`)
+	strs := reg.FindAllStringSubmatch(key, -1)
+	if strs == nil || len(strs) > 1 {
+		return "", "", "", perrors.Errorf("Invalid key, service key must follow [{group}/]{service}[:{version}] pattern")
+	}
+	if len(strs[0]) != 4 {
+		return "", "", "", perrors.Errorf("Parse service router key failed")
+	}
+	grp := strings.TrimSpace(strings.TrimRight(strs[0][1], "/"))
+	srv := strings.TrimSpace(strs[0][2])
+	ver := strings.TrimSpace(strings.TrimLeft(strs[0][3], ":"))
+	return grp, srv, ver, nil
+}
+
 func parseCondition(conditions []string) string {
 	var when, then string
 	for _, condition := range conditions {
diff --git a/cluster/router/condition/file_test.go b/cluster/router/condition/file_test.go
index 3092b12ff88dcacc9108c7cdd46ba1ac9f74eb2b..bd19a0d18c6692af181ffef77c5cd3f9fc16d67d 100644
--- a/cluster/router/condition/file_test.go
+++ b/cluster/router/condition/file_test.go
@@ -26,7 +26,9 @@ import (
 )
 
 func TestLoadYmlConfig(t *testing.T) {
-	router, e := NewFileConditionRouter([]byte(`priority: 1
+	router, e := NewFileConditionRouter([]byte(`scope: application
+key: mock-app
+priority: 1
 force: true
 conditions :
   - "a => b"
@@ -47,12 +49,78 @@ func TestParseCondition(t *testing.T) {
 }
 
 func TestFileRouterURL(t *testing.T) {
-	router, e := NewFileConditionRouter([]byte(`priority: 1
+	router, e := NewFileConditionRouter([]byte(`scope: application
+key: mock-app
+priority: 1
 force: true
 conditions :
   - "a => b"
   - "c => d"`))
 	assert.Nil(t, e)
 	assert.NotNil(t, router)
-	assert.Equal(t, "condition://0.0.0.0:?category=routers&force=true&priority=1&router=condition&rule=YSAmIGMgPT4gYiAmIGQ%3D", router.URL().String())
+	assert.Equal(t, "condition://0.0.0.0:?application=mock-app&category=routers&force=true&priority=1&router=condition&rule=YSAmIGMgPT4gYiAmIGQ%3D", router.URL().String())
+
+	router, e = NewFileConditionRouter([]byte(`scope: service
+key: mock-service
+priority: 1
+force: true
+conditions :
+  - "a => b"
+  - "c => d"`))
+	assert.Nil(t, e)
+	assert.NotNil(t, router)
+	assert.Equal(t, "condition://0.0.0.0:?category=routers&force=true&interface=mock-service&priority=1&router=condition&rule=YSAmIGMgPT4gYiAmIGQ%3D", router.URL().String())
+
+	router, e = NewFileConditionRouter([]byte(`scope: service
+key: grp1/mock-service:v1
+priority: 1
+force: true
+conditions :
+  - "a => b"
+  - "c => d"`))
+	assert.Nil(t, e)
+	assert.NotNil(t, router)
+	assert.Equal(t, "condition://0.0.0.0:?category=routers&force=true&group=grp1&interface=mock-service&priority=1&router=condition&rule=YSAmIGMgPT4gYiAmIGQ%3D&version=v1", router.URL().String())
+}
+
+func TestParseServiceRouterKey(t *testing.T) {
+	testString := " mock-group / mock-service:1.0.0"
+	grp, srv, ver, err := parseServiceRouterKey(testString)
+	assert.Equal(t, "mock-group", grp)
+	assert.Equal(t, "mock-service", srv)
+	assert.Equal(t, "1.0.0", ver)
+
+	testString = "mock-group/mock-service"
+	grp, srv, ver, err = parseServiceRouterKey(testString)
+	assert.Equal(t, "mock-group", grp)
+	assert.Equal(t, "mock-service", srv)
+	assert.Equal(t, "", ver)
+
+	testString = "mock-service:1.0.0"
+	grp, srv, ver, err = parseServiceRouterKey(testString)
+	assert.Equal(t, "", grp)
+	assert.Equal(t, "mock-service", srv)
+	assert.Equal(t, "1.0.0", ver)
+
+	testString = "mock-service"
+	grp, srv, ver, err = parseServiceRouterKey(testString)
+	assert.Equal(t, "", grp)
+	assert.Equal(t, "mock-service", srv)
+	assert.Equal(t, "", ver)
+
+	testString = "/mock-service:"
+	grp, srv, ver, err = parseServiceRouterKey(testString)
+	assert.Equal(t, "", grp)
+	assert.Equal(t, "mock-service", srv)
+	assert.Equal(t, "", ver)
+
+	testString = "grp:mock-service:123"
+	grp, srv, ver, err = parseServiceRouterKey(testString)
+	assert.Error(t, err)
+
+	testString = ""
+	grp, srv, ver, err = parseServiceRouterKey(testString)
+	assert.Equal(t, "", grp)
+	assert.Equal(t, "", srv)
+	assert.Equal(t, "", ver)
 }
diff --git a/cluster/router/condition/router.go b/cluster/router/condition/router.go
index 40a251573f5e73d40032972313565d98b288b1b1..800293da6c59f07a4bff1b6b832f482273394cec 100644
--- a/cluster/router/condition/router.go
+++ b/cluster/router/condition/router.go
@@ -117,7 +117,13 @@ func NewConditionRouter(url *common.URL) (*ConditionRouter, error) {
 	}
 
 	router.url = url
-	router.priority = url.GetParamInt(constant.RouterPriority, 0)
+	var defaultPriority int64 = 0
+	if url.GetParam(constant.APPLICATION_KEY, "") != "" {
+		defaultPriority = 150
+	} else if url.GetParam(constant.INTERFACE_KEY, "") != "" {
+		defaultPriority = 140
+	}
+	router.priority = url.GetParamInt(constant.RouterPriority, defaultPriority)
 	router.Force = url.GetParamBool(constant.RouterForce, false)
 	router.enabled = url.GetParamBool(constant.RouterEnabled, true)
 
diff --git a/cluster/router/condition/router_rule.go b/cluster/router/condition/router_rule.go
index ce397d6cc0f51519123dd427709e8dba42d72a20..9f2bf2d41a941398698f110f77a7a3051a0c9c11 100644
--- a/cluster/router/condition/router_rule.go
+++ b/cluster/router/condition/router_rule.go
@@ -28,12 +28,13 @@ import (
 import (
 	"github.com/apache/dubbo-go/cluster/router"
 	"github.com/apache/dubbo-go/common"
+	"github.com/apache/dubbo-go/common/constant"
 	"github.com/apache/dubbo-go/common/yaml"
 )
 
 // RouterRule RouterRule config read from config file or config center
 type RouterRule struct {
-	router.BaseRouterRule `yaml:",inline""`
+	router.BaseRouterRule `yaml:",inline"`
 	Conditions            []string
 }
 
@@ -57,7 +58,7 @@ func getRule(rawRule string) (*RouterRule, error) {
 		return r, err
 	}
 	r.RawRule = rawRule
-	if len(r.Conditions) != 0 {
+	if len(r.Conditions) > 0 && len(r.Key) > 0 && (r.Scope == constant.RouterApplicationScope || r.Scope == constant.RouterServiceScope) {
 		r.Valid = true
 	}
 
diff --git a/cluster/router/condition/router_rule_test.go b/cluster/router/condition/router_rule_test.go
index 675acaec912b413d8fa3d1a25463b1fd4813a7f5..369b14f08a6a650b36fe63a2d890c04fe7b892a5 100644
--- a/cluster/router/condition/router_rule_test.go
+++ b/cluster/router/condition/router_rule_test.go
@@ -32,6 +32,7 @@ import (
 func TestGetRule(t *testing.T) {
 	testyml := `
 scope: application
+key: test-provider
 runtime: true
 force: false
 conditions:
@@ -50,10 +51,31 @@ conditions:
 	assert.True(t, rule.Runtime)
 	assert.Equal(t, false, rule.Force)
 	assert.Equal(t, testyml, rule.RawRule)
-	assert.True(t, true, rule.Valid)
+	assert.True(t, rule.Valid)
 	assert.Equal(t, false, rule.Enabled)
 	assert.Equal(t, false, rule.Dynamic)
-	assert.Equal(t, "", rule.Key)
+	assert.Equal(t, "test-provider", rule.Key)
+
+	testyml = `
+key: test-provider
+runtime: true
+force: false
+conditions:
+  - >
+    method!=sayHello =>`
+	rule, e = getRule(testyml)
+	assert.Nil(t, e)
+	assert.False(t, rule.Valid)
+
+	testyml = `
+scope: noApplication
+key: test-provider
+conditions:
+  - >
+    method!=sayHello =>`
+	rule, e = getRule(testyml)
+	assert.Nil(t, e)
+	assert.False(t, rule.Valid)
 }
 
 func TestIsMatchGlobPattern(t *testing.T) {
diff --git a/cluster/router/condition/router_test.go b/cluster/router/condition/router_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..c27a1d9552a331d7e67af0eb3d444c480758891e
--- /dev/null
+++ b/cluster/router/condition/router_test.go
@@ -0,0 +1,88 @@
+/*
+ * 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 condition
+
+import (
+	"testing"
+)
+
+import (
+	"github.com/apache/dubbo-go/common"
+	"github.com/dubbogo/gost/container/set"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestParseRule(t *testing.T) {
+	testString := ``
+	matchPair, err := parseRule(testString)
+	assert.Nil(t, err)
+	assert.EqualValues(t, matchPair, make(map[string]MatchPair, 16))
+
+	testString = `method!=sayHello&application=sayGoodBye`
+	matchPair, err = parseRule(testString)
+	assert.Nil(t, err)
+	assert.EqualValues(t, matchPair["method"].Mismatches, gxset.NewSet("sayHello"))
+	assert.EqualValues(t, matchPair["application"].Matches, gxset.NewSet("sayGoodBye"))
+
+	testString = `noRule`
+	matchPair, err = parseRule(testString)
+	assert.Nil(t, err)
+	assert.EqualValues(t, matchPair["noRule"].Mismatches, gxset.NewSet())
+	assert.EqualValues(t, matchPair["noRule"].Matches, gxset.NewSet())
+
+	testString = `method!=sayHello,sayGoodBye`
+	matchPair, err = parseRule(testString)
+	assert.Nil(t, err)
+	assert.EqualValues(t, matchPair["method"].Mismatches, gxset.NewSet(`sayHello`, `sayGoodBye`))
+
+	testString = `method!=sayHello,sayGoodDay=sayGoodBye`
+	matchPair, err = parseRule(testString)
+	assert.Nil(t, err)
+	assert.EqualValues(t, matchPair["method"].Mismatches, gxset.NewSet(`sayHello`, `sayGoodDay`))
+	assert.EqualValues(t, matchPair["method"].Matches, gxset.NewSet(`sayGoodBye`))
+}
+
+func TestNewConditionRouter(t *testing.T) {
+	url, _ := common.NewURL(`condition://0.0.0.0:?application=mock-app&category=routers&force=true&priority=1&router=condition&rule=YSAmIGMgPT4gYiAmIGQ%3D`)
+	router, err := NewConditionRouter(&url)
+	assert.Nil(t, err)
+	assert.Equal(t, true, router.Enabled())
+	assert.Equal(t, true, router.Force)
+	assert.Equal(t, int64(1), router.Priority())
+	whenRule, _ := parseRule("a & c")
+	thenRule, _ := parseRule("b & d")
+	assert.EqualValues(t, router.WhenCondition, whenRule)
+	assert.EqualValues(t, router.ThenCondition, thenRule)
+
+	router, err = NewConditionRouter(nil)
+	assert.Error(t, err)
+
+	url, _ = common.NewURL(`condition://0.0.0.0:?application=mock-app&category=routers&force=true&priority=1&router=condition&rule=YSAmT4gYiAmIGQ%3D`)
+	router, err = NewConditionRouter(&url)
+	assert.Error(t, err)
+
+	url, _ = common.NewURL(`condition://0.0.0.0:?application=mock-app&category=routers&force=true&router=condition&rule=YSAmIGMgPT4gYiAmIGQ%3D`)
+	router, err = NewConditionRouter(&url)
+	assert.Nil(t, err)
+	assert.Equal(t, int64(150), router.Priority())
+
+	url, _ = common.NewURL(`condition://0.0.0.0:?category=routers&force=true&interface=mock-service&router=condition&rule=YSAmIGMgPT4gYiAmIGQ%3D`)
+	router, err = NewConditionRouter(&url)
+	assert.Nil(t, err)
+	assert.Equal(t, int64(140), router.Priority())
+}
diff --git a/cluster/router/tag/router_rule.go b/cluster/router/tag/router_rule.go
index 926446dcb2f18fa2fd4639a9246a85f435d75d45..fcf5542fdd5f5cf285f4060a234cf2ef2c4185ed 100644
--- a/cluster/router/tag/router_rule.go
+++ b/cluster/router/tag/router_rule.go
@@ -24,7 +24,7 @@ import (
 
 // RouterRule RouterRule config read from config file or config center
 type RouterRule struct {
-	router.BaseRouterRule `yaml:",inline""`
+	router.BaseRouterRule `yaml:",inline"`
 }
 
 func getRule(rawRule string) (*RouterRule, error) {
diff --git a/common/constant/key.go b/common/constant/key.go
index ea9bad9d501e7db63c69b0157e568f816ca7ba81..fb1b50db8cf565ee782a2d8aa85200b8c2595c05 100644
--- a/common/constant/key.go
+++ b/common/constant/key.go
@@ -197,7 +197,14 @@ const (
 	RouterEnabled = "enabled"
 	// Priority Priority key in router module
 	RouterPriority = "priority"
-
+	// RouterScope Scope key in router module
+	RouterScope = "scope"
+	// RouterApplicationScope Scope key in router module
+	RouterApplicationScope = "application"
+	// RouterServiceScope Scope key in router module
+	RouterServiceScope = "service"
+	// RouterRuleKey defines the key of the router, service's/application's name
+	RouterRuleKey = "key"
 	// ForceUseTag is the tag in attachment
 	ForceUseTag = "dubbo.force.tag"
 	Tagkey      = "dubbo.tag"
diff --git a/common/url.go b/common/url.go
index 807d0ed5eff4ecb70d3adeb8524b841d0ec92a58..ec6dce9175596e4f1774614f8f0cb978d181f300 100644
--- a/common/url.go
+++ b/common/url.go
@@ -381,7 +381,7 @@ func (c URL) Service() string {
 	if service != "" {
 		return service
 	} else if c.SubURL != nil {
-		service = c.GetParam(constant.INTERFACE_KEY, strings.TrimPrefix(c.Path, "/"))
+		service = c.SubURL.GetParam(constant.INTERFACE_KEY, strings.TrimPrefix(c.Path, "/"))
 		if service != "" { // if url.path is "" then return suburl's path, special for registry url
 			return service
 		}
diff --git a/common/yaml/yaml.go b/common/yaml/yaml.go
index 5edda1b3c7751e8171528d121148b6c3c60fe128..d7e1ca4e898ce64f316b2abf8cb9e3324eb31e32 100644
--- a/common/yaml/yaml.go
+++ b/common/yaml/yaml.go
@@ -27,7 +27,7 @@ import (
 	"gopkg.in/yaml.v2"
 )
 
-// loadYMLConfig Load yml config byte from file
+// LoadYMLConfig Load yml config byte from file
 func LoadYMLConfig(confProFile string) ([]byte, error) {
 	if len(confProFile) == 0 {
 		return nil, perrors.Errorf("application configure(provider) file name is nil")
@@ -40,7 +40,7 @@ func LoadYMLConfig(confProFile string) ([]byte, error) {
 	return ioutil.ReadFile(confProFile)
 }
 
-// unmarshalYMLConfig Load yml config byte from file, then unmarshal to object
+// UnmarshalYMLConfig Load yml config byte from file, then unmarshal to object
 func UnmarshalYMLConfig(confProFile string, out interface{}) ([]byte, error) {
 	confFileStream, err := LoadYMLConfig(confProFile)
 	if err != nil {
@@ -49,6 +49,12 @@ func UnmarshalYMLConfig(confProFile string, out interface{}) ([]byte, error) {
 	return confFileStream, yaml.Unmarshal(confFileStream, out)
 }
 
+//UnmarshalYML unmarshals decodes the first document found within the in byte slice and assigns decoded values into the out value.
 func UnmarshalYML(data []byte, out interface{}) error {
 	return yaml.Unmarshal(data, out)
 }
+
+// MarshalYML serializes the value provided into a YAML document.
+func MarshalYML(in interface{}) ([]byte, error) {
+	return yaml.Marshal(in)
+}
diff --git a/config/router_config.go b/config/router_config.go
index 16a2bec918d0f9a2de2174324e78ca21e853dabf..ed42577ed3cce2e5a1ab0da290f0d5450553d8fb 100644
--- a/config/router_config.go
+++ b/config/router_config.go
@@ -23,6 +23,7 @@ import (
 )
 
 import (
+	"github.com/apache/dubbo-go/cluster/router"
 	"github.com/apache/dubbo-go/common/extension"
 	"github.com/apache/dubbo-go/common/logger"
 	"github.com/apache/dubbo-go/common/yaml"
@@ -32,16 +33,37 @@ var (
 	routerURLSet = gxset.NewSet()
 )
 
+// LocalRouterRules defines the local router config structure
+type LocalRouterRules struct {
+	RouterRules []interface{} `yaml:"routerRules"`
+}
+
 // RouterInit Load config file to init router config
 func RouterInit(confRouterFile string) error {
-	fileRouterFactories := extension.GetFileRouterFactories()
 	bytes, err := yaml.LoadYMLConfig(confRouterFile)
 	if err != nil {
 		return perrors.Errorf("ioutil.ReadFile(file:%s) = error:%v", confRouterFile, perrors.WithStack(err))
 	}
-	logger.Warnf("get fileRouterFactories len{%+v})", len(fileRouterFactories))
-	for k, factory := range fileRouterFactories {
-		r, e := factory.NewFileRouter(bytes)
+	routerRules := &LocalRouterRules{}
+	err = yaml.UnmarshalYML(bytes, routerRules)
+	if err != nil {
+		return perrors.Errorf("Load router file %s failed due to error: %v", confRouterFile, perrors.WithStack(err))
+	}
+	if len(routerRules.RouterRules) == 0 {
+		return perrors.Errorf("No router configurations in file %s", confRouterFile)
+	}
+	fileRouterFactories := extension.GetFileRouterFactories()
+	for _, v := range routerRules.RouterRules {
+		content, _ := yaml.MarshalYML(v)
+		err = initRouterConfig(content, fileRouterFactories)
+	}
+	return err
+}
+
+func initRouterConfig(content []byte, factories map[string]router.FilePriorityRouterFactory) error {
+	logger.Warnf("get fileRouterFactories len{%+v})", len(factories))
+	for k, factory := range factories {
+		r, e := factory.NewFileRouter(content)
 		if e == nil {
 			url := r.URL()
 			routerURLSet.Add(&url)
@@ -52,6 +74,7 @@ func RouterInit(confRouterFile string) error {
 	return perrors.Errorf("no file router exists for parse %s , implement router.FIleRouterFactory please.", confRouterFile)
 }
 
+// GetRouterURLSet exposes the routerURLSet
 func GetRouterURLSet() *gxset.HashSet {
 	return routerURLSet
 }
diff --git a/config/router_config_test.go b/config/router_config_test.go
index 72e51c1c82562b03736fd0afef79b78d83d6f4f3..13af7056d5280ef4cca3c0f9ede9397407df7478 100644
--- a/config/router_config_test.go
+++ b/config/router_config_test.go
@@ -23,6 +23,7 @@ import (
 )
 
 import (
+	"github.com/dubbogo/gost/container/set"
 	"github.com/stretchr/testify/assert"
 )
 
@@ -31,6 +32,7 @@ import (
 )
 
 const testYML = "testdata/router_config.yml"
+const testMultiRouterYML = "testdata/router_multi_config.yml"
 const errorTestYML = "testdata/router_config_error.yml"
 
 func TestString(t *testing.T) {
@@ -63,4 +65,10 @@ func TestRouterInit(t *testing.T) {
 	assert.NoError(t, errPro)
 
 	assert.Equal(t, 1, routerURLSet.Size())
+
+	routerURLSet = gxset.NewSet()
+	errPro = RouterInit(testMultiRouterYML)
+	assert.NoError(t, errPro)
+
+	assert.Equal(t, 2, routerURLSet.Size())
 }
diff --git a/config/service_config_test.go b/config/service_config_test.go
index 0f7e404f6e336b8ad254e4007825ecbfcaf9d78b..d2bbda0c49ee18dfeb8e6475203f09d4c2fbb3b9 100644
--- a/config/service_config_test.go
+++ b/config/service_config_test.go
@@ -153,7 +153,7 @@ func TestExport(t *testing.T) {
 	providerConfig = nil
 }
 
-func TestgetRandomPort(t *testing.T) {
+func TestGetRandomPort(t *testing.T) {
 	protocolConfigs := make([]*ProtocolConfig, 0, 3)
 
 	ip, err := gxnet.GetLocalIP()
diff --git a/config/testdata/router_config.yml b/config/testdata/router_config.yml
index f6b91f5da7d95256e6279924b884bfd450c45a08..1845650d93c152585c4d4caf60ab7aa3d5b04887 100644
--- a/config/testdata/router_config.yml
+++ b/config/testdata/router_config.yml
@@ -1,6 +1,9 @@
 # dubbo router yaml configure file
-priority: 1
-force: true
-conditions :
-  - "a => b"
-  - "c => d"
\ No newline at end of file
+routerRules: 
+  - scope: application
+    key: mock-app
+    priority: 1
+    force: true
+    conditions :
+      - "a => b"
+      - "c => d"
\ No newline at end of file
diff --git a/config/testdata/router_config_error.yml b/config/testdata/router_config_error.yml
index 37894ac96474281d10131b53d8e644f10a18b14e..74e89cc52ec772a52c3c424a94276075fb099f8c 100644
--- a/config/testdata/router_config_error.yml
+++ b/config/testdata/router_config_error.yml
@@ -1,6 +1,7 @@
 # dubbo router yaml configure file
-priority: 1
-force: true
-noConditions :
-  - "a => b"
-  - "c => d"
\ No newline at end of file
+routerRules: 
+  - priority: 1
+    force: true
+    noConditions :
+    - "a => b"
+    - "c => d"
\ No newline at end of file
diff --git a/config/testdata/router_multi_config.yml b/config/testdata/router_multi_config.yml
new file mode 100644
index 0000000000000000000000000000000000000000..42bb4cbe70a43dc82ad4a4849059ad4344e6fd85
--- /dev/null
+++ b/config/testdata/router_multi_config.yml
@@ -0,0 +1,16 @@
+# dubbo router yaml configure file
+routerRules:
+  - scope: application
+    key: mock-app
+    priority: 1
+    force: true
+    conditions :
+      - "a => b"
+      - "c => d"
+  - scope: application
+    key: mock-app2
+    priority: 1
+    force: true
+    conditions :
+      - "a => b"
+      - "c => d"
\ No newline at end of file