Aetherance commented on code in PR #3305:
URL: https://github.com/apache/dubbo-go/pull/3305#discussion_r3292969347
##########
cluster/router/tag/router.go:
##########
@@ -157,3 +172,269 @@ func parseRoute(routeContent string)
(*global.RouterConfig, error) {
}
return routerConfig, nil
}
+
+func (p *PriorityRouter) Name() string {
+ return "tag"
+}
+
+func (p *PriorityRouter) ShouldPool() bool {
+ return true
+}
+
+func (p *PriorityRouter) Pool(invokers []base.Invoker) (router.AddrPool,
router.AddrMetadata) {
+ pool := make(router.AddrPool)
+ for i, invoker := range invokers {
+ url := invoker.GetURL()
+ upsertBM(pool, "*", i)
+ tag := url.GetParam(constant.Tagkey, "")
+ upsertBM(pool, "tag\x00"+tag, i)
+ addr := url.Location
+ if addr != "" {
+ upsertBM(pool, "addr\x00"+addr, i)
+ if idx := strings.LastIndex(addr, ":"); idx > 0 {
+ upsertBM(pool, "port\x00"+addr[idx+1:], i)
+ }
+ }
+ for _, key := range []string{"version", "group"} {
+ if v := url.GetParam(key, ""); v != "" {
+ upsertBM(pool, "param\x00"+key+"\x00"+v, i)
+ } else {
+ upsertBM(pool, "param\x00"+key+"\x00\x00", i)
+ }
+ }
+ }
+ return pool, nil
+}
+
+func (p *PriorityRouter) SetCache(cache router.Cache) {
+ p.cache = cache
+}
+
+func (p *PriorityRouter) routeWithPool(invokers []base.Invoker, pool
router.AddrPool, url *common.URL, invocation base.Invocation) []base.Invoker {
+ tag := invocation.GetAttachmentWithDefaultValue(constant.Tagkey,
url.GetParam(constant.Tagkey, ""))
+
+ application := invokers[0].GetURL().GetParam(constant.ApplicationKey,
"")
+ key := strings.Join([]string{application,
constant.TagRouterRuleSuffix}, "")
+ value, ok := p.routerConfigs.Load(key)
+ if !ok {
+ return collectInvokers(invokers, p.staticTagMatchBM(pool, tag,
url, invocation))
+ }
+ routerCfg := value.(global.RouterConfig)
+ enabled := routerCfg.Enabled == nil || *routerCfg.Enabled
+ valid := (routerCfg.Valid != nil && *routerCfg.Valid) ||
(routerCfg.Valid == nil && len(routerCfg.Tags) > 0)
+ if !enabled || !valid {
+ return collectInvokers(invokers, p.staticTagMatchBM(pool, tag,
url, invocation))
+ }
+ if tag == "" {
+ return collectInvokers(invokers, p.emptyTagMatchBM(pool,
routerCfg))
+ }
+ bm := p.requestTagMatchBM(pool, url, invocation, routerCfg, tag)
+ if bm == nil {
+ return requestTag(invokers, url, invocation, routerCfg, tag)
+ }
+ return collectInvokers(invokers, bm)
+}
+
+func (p *PriorityRouter) staticTagMatchBM(pool router.AddrPool, tag string,
url *common.URL, invocation base.Invocation) *roaring.Bitmap {
+ if tag != "" {
+ if bm := pool["tag\x00"+tag]; bm != nil && !bm.IsEmpty() {
+ return bm
+ }
+ if requestIsForce(url, invocation) {
+ return nil
+ }
+ }
+ return pool["tag\x00"]
+}
+
+func (p *PriorityRouter) requestTagMatchBM(pool router.AddrPool, url
*common.URL, invocation base.Invocation,
+ cfg global.RouterConfig, tag string) *roaring.Bitmap {
+ var (
+ addresses []string
+ match []*common.ParamMatch
+ )
+ for _, tagCfg := range cfg.Tags {
+ if tagCfg.Name == tag {
+ addresses = tagCfg.Addresses
+ match = tagCfg.Match
+ break
+ }
+ }
+
+ var resultBM *roaring.Bitmap
+ if len(match) != 0 {
+ resultBM = p.matchBM(pool, match)
+ } else if len(addresses) != 0 {
+ resultBM = p.addressesBM(pool, addresses)
+ } else {
+ resultBM = pool["tag\x00"+tag]
+ }
+
+ if (cfg.Force != nil && *cfg.Force) || requestIsForce(url, invocation) {
+ return resultBM
+ }
+ if resultBM != nil && !resultBM.IsEmpty() {
+ return resultBM
+ }
+
+ emptyBM := pool["tag\x00"]
+ if emptyBM == nil {
+ return nil
+ }
+ if len(addresses) == 0 {
+ return emptyBM
+ }
+ addrBM := p.addressesBM(pool, addresses)
+ if addrBM != nil && !addrBM.IsEmpty() {
+ allBM := pool["*"]
+ if allBM != nil {
+ result := allBM.Clone()
+ result.AndNot(addrBM)
+ return result
+ }
+ }
+ return pool["*"]
+}
+
+func (p *PriorityRouter) emptyTagMatchBM(pool router.AddrPool, cfg
global.RouterConfig) *roaring.Bitmap {
+ bm := pool["tag\x00"]
+ if bm == nil || bm.IsEmpty() {
+ return bm
+ }
+ for _, tagCfg := range cfg.Tags {
+ if len(tagCfg.Addresses) == 0 {
+ continue
+ }
+ addrBM := p.addressesBM(pool, tagCfg.Addresses)
+ if addrBM != nil && !addrBM.IsEmpty() && bm != nil {
+ result := bm.Clone()
+ result.AndNot(addrBM)
+ bm = result
+ }
+ }
+ return bm
+}
+
+func (p *PriorityRouter) addressesBM(pool router.AddrPool, addrs []string)
*roaring.Bitmap {
+ bm := roaring.NewBitmap()
+ for _, addr := range addrs {
+ if ab := pool["addr\x00"+addr]; ab != nil {
+ bm.Or(ab)
+ }
+ if idx := strings.LastIndex(addr, ":"); idx > 0 && addr[:idx]
== constant.AnyHostValue {
+ if pb := pool["port\x00"+addr[idx+1:]]; pb != nil {
+ bm.Or(pb)
+ }
+ }
+ }
+ return bm
+}
+
+func (p *PriorityRouter) matchBM(pool router.AddrPool, matches
[]*common.ParamMatch) *roaring.Bitmap {
+ var result *roaring.Bitmap
+ for _, m := range matches {
+ bm := p.paramMatchBM(pool, m)
+ if bm == nil {
+ return nil
+ }
+ if result == nil {
+ result = bm.Clone()
+ } else {
+ result.And(bm)
+ }
+ if result.IsEmpty() {
+ return result
+ }
+ }
+ return result
+}
+
+func (p *PriorityRouter) paramMatchBM(pool router.AddrPool, pm
*common.ParamMatch) *roaring.Bitmap {
+ prefix := "param\x00" + pm.Key + "\x00"
+ switch {
+ case pm.Value.Exact != "":
+ return pool[prefix+pm.Value.Exact]
+ case pm.Value.Wildcard != "":
+ if pm.Value.Wildcard == constant.AnyValue {
+ return pool["*"]
+ }
+ return pool[prefix+pm.Value.Wildcard]
+ case pm.Value.Prefix != "":
+ return scanPrefixBM(pool, prefix, pm.Value.Prefix)
+ case pm.Value.Regex != "":
+ return scanRegexBM(pool, prefix, pm.Value.Regex)
+ case pm.Value.Empty != "":
+ return pool[prefix+"\x00"]
+ case pm.Value.Noempty != "":
+ emptyBM := pool[prefix+"\x00"]
+ allBM := pool["*"]
+ if allBM == nil {
+ return roaring.NewBitmap()
+ }
+ if emptyBM != nil {
+ result := allBM.Clone()
+ result.AndNot(emptyBM)
+ return result
+ }
+ return allBM
+ }
+ return roaring.NewBitmap()
+}
Review Comment:
Fixed: when `match` is non-empty, requestTagMatchBM now directly returns
nil, falling back to the original requestTag(filterInvokers).
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]