Skip to content

fix(router/affinity): prevent panic caused by nil return in initialization phase#3216

Open
Aetherance wants to merge 1 commit intoapache:developfrom
Aetherance:fix/affinity-router
Open

fix(router/affinity): prevent panic caused by nil return in initialization phase#3216
Aetherance wants to merge 1 commit intoapache:developfrom
Aetherance:fix/affinity-router

Conversation

@Aetherance
Copy link
Contributor

@Aetherance Aetherance commented Feb 17, 2026

Description

在一些情况下,client 配置 affinity router 时,会因为 nil 而触发段错误

2026-02-17 21:27:55     ERROR   affinity/router.go:90       Application affinity router must set application name
2026/02/17 21:27:55 Authenticated: id=72061538416853150, timeout=4000
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0xe915e9]

该 bug 只会在配置了 application 模式的 affinity router 上出现,如果配置 service 模式的 affinity router 则不会触发该 bug

配置代码:
client:

	conn, _, _ := zk.Connect([]string{"127.0.0.1:2181"}, time.Second*5)
	defer conn.Close()
	conn.Create("/dubbo/config/dubbo/router_affinity_consumer.affinity-router", []byte(`configVersion: v3.1
scope: application
key: router_affinity_consumer
enabled: true
runtime: true
affinityAware:
  key: region
  ratio: 1`), 0, zk.WorldACL(zk.PermAll))

	ins, _ := dubbo.NewInstance(
		dubbo.WithName("router_affinity_consumer"),
		dubbo.WithRegistry(registry.WithZookeeper(), registry.WithAddress("127.0.0.1:2181")),
		dubbo.WithConfigCenter(config_center.WithZookeeper(), config_center.WithAddress("127.0.0.1:2181"), config_center.WithGroup("dubbo")),
	)

	cli, _ := ins.NewClient(client.WithClientProtocolTriple())
	svc, _ := greet.NewGreetService(cli, client.WithParam("region", "shanghai"))

	ctx := context.WithValue(context.Background(),
		constant.DubboCtxKey("attachment"),
		map[string]interface{}{"region": "shanghai"},
	)

server:

	ins, _ := dubbo.NewInstance(
		dubbo.WithName("router_affinity_provider_a"),
		dubbo.WithRegistry(registry.WithZookeeper(), registry.WithAddress("127.0.0.1:2181")),
	)

	srv, _ := ins.NewServer(server.WithServerProtocol(protocol.WithTriple(), protocol.WithPort(20000)))

	handler := &AffinityGreetServer{}
	greet.RegisterGreetServiceHandler(srv, handler, server.WithParam("region", "hangzhou"))

	srv.Serve()

bug 原因是当前版本的client应用名未能被正确传递至 router chain。这导致 router chain 在 初始化 affinity router 时,由于获取到空应用名而直接返回 nil。最终造成 nil 被访问而 panic

本 pr 添加了在 router chain 读取应用名的逻辑来修复此 bug

Fixes #3203

Checklist

  • I confirm the target branch is develop
  • Code has passed local testing
  • I have added tests that prove my fix is effective or that my feature works

@codecov-commenter
Copy link

codecov-commenter commented Feb 17, 2026

Codecov Report

❌ Patch coverage is 0% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 47.91%. Comparing base (60d1c2a) to head (f0f2cd8).
⚠️ Report is 736 commits behind head on develop.

Files with missing lines Patch % Lines
cluster/router/chain/chain.go 0.00% 6 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #3216      +/-   ##
===========================================
+ Coverage    46.76%   47.91%   +1.15%     
===========================================
  Files          295      463     +168     
  Lines        17172    33749   +16577     
===========================================
+ Hits          8031    16172    +8141     
- Misses        8287    16269    +7982     
- Partials       854     1308     +454     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

// NewRouterChain init router chain
// Loop routerFactories and call NewRouter method
func NewRouterChain(url *common.URL) (*RouterChain, error) {
if url.GetParam(constant.ApplicationKey, "") == "" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里整个过程需要加上锁吧?
假设gr1 在 line 112这里获取的值为空,运行到 line114 的时候,另外一个 gr2 在 line 112 也获取为空后进入了这 if 条件,进而导致两个 gr 竞争进行 SetParam,这就不对了吧?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.
plz review again

…ation phase

Signed-off-by: Aetherance <inkToAether@gmail.com>
@sonarqubecloud
Copy link

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a panic in the affinity router initialization when the application name is not present in the URL by propagating it from the SubURL. The panic occurred because newApplicationAffinityRouter returns nil when the application name is empty, causing a nil pointer dereference during router chain operations.

Changes:

  • Added logic to populate the application name from SubURL to the main URL in NewRouterChain
  • Added a mutex to serialize access during the application name population

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +115 to +123
appNameSetMu.Lock()
if url.GetParam(constant.ApplicationKey, "") == "" {
if url.SubURL != nil {
if appName := url.SubURL.GetParam(constant.ApplicationKey, ""); appName != "" {
url.SetParam(constant.ApplicationKey, appName)
}
}
}
appNameSetMu.Unlock()
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mutex usage here is unnecessary and incorrect. The URL.SetParam method already has internal locking (paramsLock) for thread safety, as seen in common/url.go:558-564. Additionally, this global mutex serializes all NewRouterChain calls across the entire application, which could become a performance bottleneck when creating multiple router chains concurrently. Since URL modification is already thread-safe, the mutex should be removed.

Copilot uses AI. Check for mistakes.
Comment on lines +115 to +123
appNameSetMu.Lock()
if url.GetParam(constant.ApplicationKey, "") == "" {
if url.SubURL != nil {
if appName := url.SubURL.GetParam(constant.ApplicationKey, ""); appName != "" {
url.SetParam(constant.ApplicationKey, appName)
}
}
}
appNameSetMu.Unlock()
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR description claims tests have been added, but there are no new test files or test functions in this change. A unit test should be added to verify that the application name is correctly propagated from SubURL when the main URL doesn't have it set, and that the fix prevents the nil panic in ApplicationAffinityRouter initialization.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3.3.2 version 3.3.2 ☢️ Bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[讨论] dubbo-go router report

5 participants