feat(router): add static router configuration injection#3252
feat(router): add static router configuration injection#3252Aetherance wants to merge 14 commits intoapache:developfrom
Conversation
23bbb21 to
b628d9a
Compare
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## develop #3252 +/- ##
===========================================
+ Coverage 46.76% 49.66% +2.89%
===========================================
Files 295 469 +174
Lines 17172 34660 +17488
===========================================
+ Hits 8031 17213 +9182
- Misses 8287 16065 +7778
- Partials 854 1382 +528 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Alanxtl
left a comment
There was a problem hiding this comment.
- 测试覆盖率太低了
- 在dubbo-website里面写一下文档
- 在dubbo-go-samples里面写一下sample
5d1e53d to
5dc9b8a
Compare
AlexStocks
left a comment
There was a problem hiding this comment.
加了 unit test,但之前 Alanxtl 提的几个设计问题还没回应,详见行内评论。
There was a problem hiding this comment.
Pull request overview
This PR adds support for injecting router configurations statically (via code/client options) into the Dubbo-Go router chain, so routing rules can take effect without relying on a dynamic config center.
Changes:
- Plumbs
[]*global.RouterConfigfrom instance/client/reference options into the consumer URL attributes viaconstant.RoutersConfigKey. - Injects matching static router configs into the
RouterChainduringNewRouterChain()initialization via a newrouter.StaticConfigSetterinterface. - Adds static-config application logic + tests for condition router and tag router.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
dubbo.go |
Passes instance-level cloned router configs into client options (SetClientRouters). |
common/constant/key.go |
Adds RoutersConfigKey and scope constants (service / application). |
cluster/router/router.go |
Introduces StaticConfigSetter interface for routers that accept static injection. |
cluster/router/chain/chain.go |
Implements static router config matching + injection into routers during chain init. |
cluster/router/chain/chain_test.go |
Adds unit tests for scope/key matching and injection filtering. |
cluster/router/condition/dynamic_router.go |
Adds SetStaticConfig for condition routing + scoped wrappers. |
cluster/router/condition/router_test.go |
Adds tests for static condition config behavior and scope gating. |
cluster/router/tag/router.go |
Adds SetStaticConfig for tag router storing cloned configs. |
cluster/router/tag/router_test.go |
Adds tests for static tag config cloning/storage + parse validation. |
client/options.go |
Adds router config fields/options for client and reference (Routers, WithRouter, WithClientRouter, SetClientRouters). |
client/options_test.go |
Adds tests for new reference/client router options behavior. |
client/client.go |
Propagates client router configs into reference initialization (setRouters). |
client/action.go |
Stores reference router configs into URL attributes (RoutersConfigKey). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
5dc9b8a to
51ebcc2
Compare
This comment was marked as duplicate.
This comment was marked as duplicate.
- Add StaticConfigSetter interface for static config injection - Add global static router registry - Add router chain injection mechanism - Implement static config setters for condition and tag routers
cd15177 to
74dda05
Compare
|
apache/dubbo-go-samples#1059 已在 samples 提交示例和在 website 提交文档 |
cluster/router/tag/router.go
Outdated
| // Process is designed for dynamic config-center updates that arrive as YAML text. | ||
| // Static and dynamic rules are not merged: later Process updates replace the current state built here. | ||
| func (p *PriorityRouter) SetStaticConfig(cfg *global.RouterConfig) { | ||
| if cfg == nil || len(cfg.Tags) == 0 { |
There was a problem hiding this comment.
[P1] 这里缺少 scope 约束。tag router 的运行时查找 key 一直是“provider application + tag suffix”,所以只有 application-scope 规则能命中;如果用户静态注入了 scope: service 且带 tags,这段代码仍会把规则存进去,但后续永远不会被 Route() 取到,表现成“配置通过但不生效”。建议和 condition router 一样在入口处显式限制 cfg.Scope == constant.RouterScopeApplication,或者在 RouterConfig.Init() 阶段直接拒绝 service-scope tag 规则。
cluster/router/chain/chain.go
Outdated
| return routerCfg.Key == url.SubURL.ServiceKey() | ||
| } | ||
| return routerCfg.Key == url.ServiceKey() | ||
| case constant.RouterScopeApplication: |
There was a problem hiding this comment.
[P1] 这里按 consumer URL 的 application 过滤 application-scope 规则,但 tag router 运行时取 key 的地方是 invokers[0].GetURL().GetParam(application),也就是 provider application。两边语义不一致:规则能在初始化时注入进去,真正路由时却会用另一套 key 去查,application-scope 的静态 tag 规则只有在 consumer/provider application 恰好同名时才会生效。建议把 application-scope 静态规则的匹配和存储 key 统一到同一侧,否则这个特性本身就是不稳定的。
There was a problem hiding this comment.
这里不应该再加一层错误使用了 consumer url 的 isRouterMatch(下层已实现按 scope 分配 router config 相关逻辑) 已删除该错误逻辑
而对于 tag router 来说 router config 查找和 存储 key 的语义是一致的,都是 provider application,存储时使用的 provider application 是由router config 中的 key 字段提供的
AlexStocks
left a comment
There was a problem hiding this comment.
[P1] client/options.go:862-864 nil 检查冗余,append 对 nil slice 安全,直接 append 即可。
[P2] client/options.go:448 注释不准确,应明确说明这是用户 API,与 setRouters 的区别。
[P0] cluster/router/chain/chain.go:178 并发安全问题:injectStaticRouters 持有读锁时调用 injectRouterConfig,后者又获取读锁,设计不清晰。建议 injectStaticRouters 不加锁,由 injectRouterConfig 统一加锁。
[P1] cluster/router/chain/chain.go:151 类型断言失败只记录警告,可能导致配置未生效而用户不知情,建议返回 error 或记录 error 级别日志。
|
|
||
| // WithClientRouter appends router configurations to the client options. | ||
| // This is a user-facing option for incrementally adding routers. | ||
| // It appends to the current router slice instead of replacing it. |
There was a problem hiding this comment.
[P1] nil 检查冗余。append 对 nil slice 安全,直接 opts.Routers = append(opts.Routers, routers...) 即可。
| c.injectRouterConfig(routerCfg) | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
[P0] 并发安全问题。injectStaticRouters 持有读锁时调用 injectRouterConfig,后者又获取读锁。虽然 RLock 可重入,但设计不清晰。建议 injectStaticRouters 不加锁,由 injectRouterConfig 统一加锁。
There was a problem hiding this comment.
injectStaticRouters 并没有加锁啊
| if !ok { | ||
| return | ||
| } | ||
| staticRoutersAttr, ok := staticRoutersAttrAny.([]*global.RouterConfig) |
There was a problem hiding this comment.
[P1] 类型断言失败只记录警告,可能导致配置未生效而用户不知情。建议返回 error 或记录 error 级别日志。
|
|
Hi @AlexStocks, any further comments or concerns on this PR? |



Description
Currently, router configurations in dubbo-go can only be updated through dynamic configuration centers. This PR introduces support for statically configuring routers through code, eliminating the need for a config center.
Fixes #3219
Key Changes
1. StaticConfigSetter Interface
A new interface
StaticConfigSetteris introduced incluster/router/router.go.Routers implementing this interface can receive static router
configurations and decide whether to apply them based on their own
logic.
2. Client Options Integration
Router configurations can now be provided through client initialization.
New APIs:
WithRouter(...)SetClientRouters(...)Configuration propagation:
3. Router Chain Injection
Static router configurations are injected into the router chain during
initialization.
New functions added in
chain.go:injectStaticRouters()injectRouterConfig()Features supported:
forceflagenabledflag4. Router Implementations
Condition Router
forceandenabledflagsTag Router
enabled/validflag handlingUsage
Static router rules can now be defined directly in application code:
Router v3 API Configuration Flow
The following diagram shows how router configurations propagate from
application code to the router chain at runtime.
Checklist
develop