Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
2
22a7f0099
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Wiki
Code
Merge requests
0
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Summer2022
22a7f0099
Commits
f4075216
Commit
f4075216
authored
4 years ago
by
watermelo
Browse files
Options
Downloads
Patches
Plain Diff
Add: add ip address match function
parent
21976a30
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
cluster/router/tag/tag_router.go
+174
-41
174 additions, 41 deletions
cluster/router/tag/tag_router.go
cluster/router/tag/tag_router_test.go
+24
-11
24 additions, 11 deletions
cluster/router/tag/tag_router_test.go
with
198 additions
and
52 deletions
cluster/router/tag/tag_router.go
+
174
−
41
View file @
f4075216
...
...
@@ -18,8 +18,11 @@
package
tag
import
(
"errors"
"fmt"
"net"
"strconv"
"strings"
)
import
(
...
...
@@ -81,20 +84,27 @@ func (c *tagRouter) Route(invokers []protocol.Invoker, url *common.URL, invocati
addresses
,
_
=
tagRouterRuleCopy
.
getTagNameToAddresses
()[
tag
]
// filter by dynamic tag group first
if
len
(
addresses
)
>
0
{
result
=
filterAddressMatches
(
invokers
,
addresses
)
filterAddressMatches
:=
func
(
invoker
protocol
.
Invoker
)
bool
{
url
:=
invoker
.
GetUrl
()
if
len
(
addresses
)
>
0
&&
checkAddressMatch
(
addresses
,
url
.
Ip
,
url
.
Port
)
{
return
true
}
return
false
}
result
=
filterInvoker
(
invokers
,
filterAddressMatches
)
if
len
(
result
)
>
0
||
tagRouterRuleCopy
.
Force
{
return
result
}
}
else
{
// dynamic tag group doesn't have any item about the requested app OR it's null after filtered by
// dynamic tag group but force=false. check static tag
cond
:=
func
(
invoker
protocol
.
Invoker
)
bool
{
filter
:=
func
(
invoker
protocol
.
Invoker
)
bool
{
if
invoker
.
GetUrl
()
.
GetParam
(
constant
.
Tagkey
,
""
)
==
tag
{
return
true
}
return
false
}
result
=
filter
Condition
(
invokers
,
cond
)
result
=
filter
Invoker
(
invokers
,
filter
)
}
// If there's no tagged providers that can match the current tagged request. force.tag is set by default
// to false, which means it will invoke any providers without a tag unless it's explicitly disallowed.
...
...
@@ -102,20 +112,33 @@ func (c *tagRouter) Route(invokers []protocol.Invoker, url *common.URL, invocati
return
result
}
else
{
// FAILOVER: return all Providers without any tags.
result
=
filterAddressNotMatches
(
invokers
,
tagRouterRuleCopy
.
getAddresses
())
cond
:=
func
(
invoker
protocol
.
Invoker
)
bool
{
filterAddressNotMatches
:=
func
(
invoker
protocol
.
Invoker
)
bool
{
url
:=
invoker
.
GetUrl
()
if
len
(
addresses
)
==
0
||
!
checkAddressMatch
(
tagRouterRuleCopy
.
getAddresses
(),
url
.
Ip
,
url
.
Port
)
{
return
true
}
return
false
}
filterTagIsEmpty
:=
func
(
invoker
protocol
.
Invoker
)
bool
{
if
invoker
.
GetUrl
()
.
GetParam
(
constant
.
Tagkey
,
""
)
==
""
{
return
true
}
return
false
}
return
filter
Condition
(
result
,
cond
)
return
filter
Invoker
(
invokers
,
filterAddressNotMatches
,
filterTagIsEmpty
)
}
}
else
{
// return all addresses in dynamic tag group.
addresses
=
tagRouterRuleCopy
.
getAddresses
()
if
len
(
addresses
)
>
0
{
result
=
filterAddressNotMatches
(
invokers
,
addresses
)
filterAddressNotMatches
:=
func
(
invoker
protocol
.
Invoker
)
bool
{
url
:=
invoker
.
GetUrl
()
if
len
(
addresses
)
==
0
||
!
checkAddressMatch
(
addresses
,
url
.
Ip
,
url
.
Port
)
{
return
true
}
return
false
}
result
=
filterInvoker
(
invokers
,
filterAddressNotMatches
)
// 1. all addresses are in dynamic tag group, return empty list.
if
len
(
result
)
==
0
{
return
result
...
...
@@ -123,11 +146,11 @@ func (c *tagRouter) Route(invokers []protocol.Invoker, url *common.URL, invocati
// 2. if there are some addresses that are not in any dynamic tag group, continue to filter using the
// static tag group.
}
cond
:=
func
(
invoker
protocol
.
Invoker
)
bool
{
filter
:=
func
(
invoker
protocol
.
Invoker
)
bool
{
localTag
:=
invoker
.
GetUrl
()
.
GetParam
(
constant
.
Tagkey
,
""
)
return
localTag
==
""
||
!
(
tagRouterRuleCopy
.
hasTag
(
localTag
))
}
return
filter
Condition
(
result
,
cond
)
return
filter
Invoker
(
result
,
filter
)
}
}
...
...
@@ -185,53 +208,163 @@ func isForceUseTag(url *common.URL, invocation protocol.Invocation) bool {
return
false
}
func
filterAddressMatches
(
invokers
[]
protocol
.
Invoker
,
addresses
[]
string
)
[]
protocol
.
Invoker
{
var
idx
int
type
filter
func
(
protocol
.
Invoker
)
bool
func
filterInvoker
(
invokers
[]
protocol
.
Invoker
,
filters
...
filter
)
[]
protocol
.
Invoker
{
var
res
[]
protocol
.
Invoker
OUTER
:
for
_
,
invoker
:=
range
invokers
{
url
:=
invoker
.
GetUrl
()
if
!
(
len
(
addresses
)
>
0
&&
checkAddressMatch
(
addresses
,
url
.
Ip
,
url
.
Port
))
{
continue
for
_
,
filter
:=
range
filters
{
if
!
filter
(
invoker
)
{
continue
OUTER
}
}
invokers
[
idx
]
=
invoker
idx
++
res
=
append
(
res
,
invoker
)
}
return
invokers
[
:
idx
]
return
res
}
func
filterAddressNotMatches
(
invokers
[]
protocol
.
Invoker
,
addresses
[]
string
)
[]
protocol
.
Invoker
{
var
idx
int
for
_
,
invoker
:=
range
invokers
{
url
:=
invoker
.
GetUrl
()
if
!
(
len
(
addresses
)
==
0
||
!
checkAddressMatch
(
addresses
,
url
.
Ip
,
url
.
Port
))
{
continue
// TODO 需要搬到 dubbogo/gost, 可以先 review
func
checkAddressMatch
(
addresses
[]
string
,
host
,
port
string
)
bool
{
for
_
,
address
:=
range
addresses
{
if
matchIp
(
address
,
host
,
port
)
{
return
true
}
if
address
==
constant
.
ANYHOST_VALUE
+
":"
+
port
{
return
true
}
invokers
[
idx
]
=
invoker
idx
++
}
return
invokers
[
:
idx
]
return
false
}
func
filterCondition
(
invokers
[]
protocol
.
Invoker
,
condition
func
(
protocol
.
Invoker
)
bool
)
[]
protocol
.
Invoker
{
var
idx
int
for
_
,
invoker
:=
range
invokers
{
if
!
condition
(
invoker
)
{
func
matchIp
(
pattern
,
host
,
port
string
)
bool
{
// if the pattern is subnet format, it will not be allowed to config port param in pattern.
if
strings
.
Contains
(
pattern
,
"/"
)
{
_
,
subnet
,
_
:=
net
.
ParseCIDR
(
pattern
)
if
subnet
!=
nil
&&
subnet
.
Contains
(
net
.
ParseIP
(
host
))
{
return
true
}
return
false
}
return
matchIpRange
(
pattern
,
host
,
port
)
}
func
matchIpRange
(
pattern
,
host
,
port
string
)
bool
{
if
pattern
==
""
||
host
==
""
{
logger
.
Error
(
"Illegal Argument pattern or hostName. Pattern:"
+
pattern
+
", Host:"
+
host
)
return
false
}
pattern
=
strings
.
TrimSpace
(
pattern
)
if
"*.*.*.*"
==
pattern
||
"*"
==
pattern
{
return
true
}
isIpv4
:=
true
ip4
:=
net
.
ParseIP
(
host
)
.
To4
()
if
ip4
==
nil
{
isIpv4
=
false
}
hostAndPort
:=
getPatternHostAndPort
(
pattern
,
isIpv4
)
if
hostAndPort
[
1
]
!=
""
&&
hostAndPort
[
1
]
!=
port
{
return
false
}
pattern
=
hostAndPort
[
0
]
// TODO 常量化
splitCharacter
:=
"
\\
."
if
!
isIpv4
{
splitCharacter
=
":"
}
mask
:=
strings
.
Split
(
pattern
,
splitCharacter
)
// check format of pattern
if
err
:=
checkHostPattern
(
pattern
,
mask
,
isIpv4
);
err
!=
nil
{
logger
.
Error
(
err
)
return
false
}
if
pattern
==
host
{
return
true
}
// short name condition
if
!
ipPatternContains
(
pattern
)
{
return
pattern
==
host
}
// ip 段
ipAddress
:=
strings
.
Split
(
host
,
splitCharacter
)
for
i
:=
0
;
i
<
len
(
mask
);
i
++
{
if
"*"
==
mask
[
i
]
||
mask
[
i
]
==
ipAddress
[
i
]
{
continue
}
else
if
strings
.
Contains
(
mask
[
i
],
"-"
)
{
rangeNumStrs
:=
strings
.
Split
(
mask
[
i
],
"-"
)
if
len
(
rangeNumStrs
)
!=
2
{
logger
.
Error
(
"There is wrong format of ip Address: "
+
mask
[
i
])
return
false
}
min
:=
getNumOfIpSegment
(
rangeNumStrs
[
0
],
isIpv4
)
max
:=
getNumOfIpSegment
(
rangeNumStrs
[
1
],
isIpv4
)
ip
:=
getNumOfIpSegment
(
ipAddress
[
i
],
isIpv4
)
if
ip
<
min
||
ip
>
max
{
return
false
}
}
else
if
"0"
==
ipAddress
[
i
]
&&
"0"
==
mask
[
i
]
||
"00"
==
mask
[
i
]
||
"000"
==
mask
[
i
]
||
"0000"
==
mask
[
i
]
{
continue
}
else
if
mask
[
i
]
!=
ipAddress
[
i
]
{
return
false
}
invokers
[
idx
]
=
invoker
idx
++
}
return
invokers
[
:
idx
]
return
true
}
func
checkAddressMatch
(
addresses
[]
string
,
host
,
port
string
)
bool
{
for
_
,
address
:=
range
addresses
{
// TODO ip match
if
address
==
host
+
":"
+
port
{
return
true
func
ipPatternContains
(
pattern
string
)
bool
{
return
strings
.
Contains
(
pattern
,
"*"
)
||
strings
.
Contains
(
pattern
,
"-"
)
}
func
checkHostPattern
(
pattern
string
,
mask
[]
string
,
isIpv4
bool
)
error
{
if
!
isIpv4
{
if
len
(
mask
)
!=
8
&&
ipPatternContains
(
pattern
)
{
return
errors
.
New
(
"If you config ip expression that contains '*' or '-', please fill qualified ip pattern like 234e:0:4567:0:0:0:3d:*. "
)
}
if
address
==
constant
.
ANYHOST_VALUE
+
":"
+
port
{
return
true
if
len
(
mask
)
!=
8
&&
!
strings
.
Contains
(
pattern
,
"::"
)
{
return
errors
.
New
(
"The host is ipv6, but the pattern is not ipv6 pattern : "
+
pattern
)
}
}
else
{
if
len
(
mask
)
!=
4
{
return
errors
.
New
(
"The host is ipv4, but the pattern is not ipv4 pattern : "
+
pattern
)
}
}
return
false
return
nil
}
func
getPatternHostAndPort
(
pattern
string
,
isIpv4
bool
)
[]
string
{
result
:=
make
([]
string
,
2
)
if
strings
.
HasPrefix
(
pattern
,
"["
)
&&
strings
.
Contains
(
pattern
,
"]:"
)
{
end
:=
strings
.
Index
(
pattern
,
"]:"
)
result
[
0
]
=
pattern
[
1
:
end
]
result
[
1
]
=
pattern
[
end
+
2
:
]
}
else
if
strings
.
HasPrefix
(
pattern
,
"["
)
&&
strings
.
HasSuffix
(
pattern
,
"]"
)
{
result
[
0
]
=
pattern
[
1
:
len
(
pattern
)
-
1
]
result
[
1
]
=
""
}
else
if
isIpv4
&&
strings
.
Contains
(
pattern
,
":"
)
{
end
:=
strings
.
Index
(
pattern
,
":"
)
result
[
0
]
=
pattern
[
:
end
]
result
[
1
]
=
pattern
[
end
+
1
:
]
}
else
{
result
[
0
]
=
pattern
}
return
result
}
func
getNumOfIpSegment
(
ipSegment
string
,
isIpv4
bool
)
int
{
if
isIpv4
{
ipSeg
,
_
:=
strconv
.
Atoi
(
ipSegment
)
return
ipSeg
}
ipSeg
,
_
:=
strconv
.
ParseInt
(
ipSegment
,
0
,
16
)
return
int
(
ipSeg
)
}
This diff is collapsed.
Click to expand it.
cluster/router/tag/tag_router_test.go
+
24
−
11
View file @
f4075216
...
...
@@ -19,7 +19,6 @@ package tag
import
(
"context"
"github.com/apache/dubbo-go/common/constant"
"testing"
)
...
...
@@ -29,16 +28,18 @@ import (
import
(
"github.com/apache/dubbo-go/common"
"github.com/apache/dubbo-go/common/constant"
"github.com/apache/dubbo-go/protocol"
"github.com/apache/dubbo-go/protocol/invocation"
)
const
(
tagRouterTestHangZhouUrl
=
"dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider?interface=com.ikurento.user.UserProvider&group=&version=2.6.0&enabled=true&dubbo.tag=hangzhou"
tagRouterTestShangHaiUrl
=
"dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider?interface=com.ikurento.user.UserProvider&group=&version=2.6.0&enabled=true&dubbo.tag=shanghai"
tagRouterTestBeijingUrl
=
"dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider?interface=com.ikurento.user.UserProvider&group=&version=2.6.0&enabled=true&dubbo.tag=beijing"
tagRouterTestUserConsumer
=
"dubbo://127.0.0.1:20000/com.ikurento.user.UserConsumer?interface=com.ikurento.user.UserConsumer&group=&version=2.6.0&enabled=true"
tagRouterTestUserConsumerTag
=
"dubbo://127.0.0.1:20000/com.ikurento.user.UserConsumer?interface=com.ikurento.user.UserConsumer&group=&version=2.6.0&enabled=true&dubbo.force.tag=true"
tagRouterTestHangZhouUrl
=
"dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider?interface=com.ikurento.user.UserProvider&group=&version=2.6.0&enabled=true&dubbo.tag=hangzhou"
tagRouterTestShangHaiUrl
=
"dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider?interface=com.ikurento.user.UserProvider&group=&version=2.6.0&enabled=true&dubbo.tag=shanghai"
tagRouterTestBeijingUrl
=
"dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider?interface=com.ikurento.user.UserProvider&group=&version=2.6.0&enabled=true&dubbo.tag=beijing"
tagRouterTestEnabledBeijingUrl
=
"dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider?interface=com.ikurento.user.UserProvider&group=&version=2.6.0&enabled=false&dubbo.tag=beijing"
tagRouterTestUserConsumer
=
"dubbo://127.0.0.1:20000/com.ikurento.user.UserConsumer?interface=com.ikurento.user.UserConsumer&group=&version=2.6.0&enabled=true"
tagRouterTestUserConsumerTag
=
"dubbo://127.0.0.1:20000/com.ikurento.user.UserConsumer?interface=com.ikurento.user.UserConsumer&group=&version=2.6.0&enabled=true&dubbo.force.tag=true"
tagRouterTestDubboTag
=
"dubbo.tag"
tagRouterTestDubboForceTag
=
"dubbo.force.tag"
...
...
@@ -162,24 +163,36 @@ func TestTagRouterRouteNoForce(t *testing.T) {
assert
.
Equal
(
t
,
3
,
len
(
invRst2
))
}
func
TestFilter
Condition
(
t
*
testing
.
T
)
{
func
TestFilter
Invoker
(
t
*
testing
.
T
)
{
u2
,
e2
:=
common
.
NewURL
(
tagRouterTestHangZhouUrl
)
u3
,
e3
:=
common
.
NewURL
(
tagRouterTestShangHaiUrl
)
u4
,
e4
:=
common
.
NewURL
(
tagRouterTestBeijingUrl
)
u5
,
e5
:=
common
.
NewURL
(
tagRouterTestEnabledBeijingUrl
)
assert
.
Nil
(
t
,
e2
)
assert
.
Nil
(
t
,
e3
)
assert
.
Nil
(
t
,
e4
)
assert
.
Nil
(
t
,
e5
)
inv2
:=
NewMockInvoker
(
u2
)
inv3
:=
NewMockInvoker
(
u3
)
inv4
:=
NewMockInvoker
(
u4
)
inv5
:=
NewMockInvoker
(
u5
)
var
invokers
[]
protocol
.
Invoker
invokers
=
append
(
invokers
,
inv2
,
inv3
,
inv4
)
cond
:=
func
(
invoker
protocol
.
Invoker
)
bool
{
invokers
=
append
(
invokers
,
inv2
,
inv3
,
inv4
,
inv5
)
filterTag
:=
func
(
invoker
protocol
.
Invoker
)
bool
{
if
invoker
.
GetUrl
()
.
GetParam
(
constant
.
Tagkey
,
""
)
==
"beijing"
{
return
true
}
return
false
}
res
:=
filterCondition
(
invokers
,
cond
)
assert
.
Equal
(
t
,
[]
protocol
.
Invoker
{
inv4
},
res
)
res
:=
filterInvoker
(
invokers
,
filterTag
)
assert
.
Equal
(
t
,
[]
protocol
.
Invoker
{
inv4
,
inv5
},
res
)
flag
:=
true
filterEnabled
:=
func
(
invoker
protocol
.
Invoker
)
bool
{
if
invoker
.
GetUrl
()
.
GetParamBool
(
constant
.
RouterEnabled
,
false
)
==
flag
{
return
true
}
return
false
}
res2
:=
filterInvoker
(
invokers
,
filterTag
,
filterEnabled
)
assert
.
Equal
(
t
,
[]
protocol
.
Invoker
{
inv4
},
res2
)
}
This diff is collapsed.
Click to expand it.
Preview
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment