Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ftr: Feature/application and service level router #662

Merged
35 changes: 28 additions & 7 deletions cluster/directory/base_directory.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -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
}

pantianying marked this conversation as resolved.
Show resolved Hide resolved
// Destroy Destroy
func (dir *BaseDirectory) Destroy(doDestroy func()) {
if dir.destroyed.CAS(false, true) {
Expand Down
64 changes: 56 additions & 8 deletions cluster/directory/base_directory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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)
Expand All @@ -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)
}
16 changes: 11 additions & 5 deletions cluster/router/chain/chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -93,15 +95,15 @@ 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)

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) {
Expand All @@ -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:
Expand Down Expand Up @@ -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:
Expand Down
19 changes: 13 additions & 6 deletions cluster/router/condition/app_router_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -83,21 +85,23 @@ 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)

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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down
45 changes: 44 additions & 1 deletion cluster/router/condition/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package condition
import (
"encoding/base64"
"net/url"
"regexp"
"strconv"
"strings"
"sync"
Expand Down Expand Up @@ -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) {
pantianying marked this conversation as resolved.
Show resolved Hide resolved
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], ":"))
zouyx marked this conversation as resolved.
Show resolved Hide resolved
return grp, srv, ver, nil
}

func parseCondition(conditions []string) string {
var when, then string
for _, condition := range conditions {
Expand Down
Loading