[FEATURE] etcdv3 registry: implement DoUnregister, DoUnsubscribe and reconnect subscription recovery
- Dominant language
- Go
- Stars
- 5k
- Forks
- 1k
- Avg merge
- 2d 8h
- Merged PRs (30d)
- 31
Description
### ⚠️ Verification
- [x] I have searched the [issues](https://github.com/apache/dubbo-go/issues) of this repository and believe that this is not a duplicate.
- [x] I have searched the [release notes](https://github.com/apache/dubbo-go/releases) of this repository and believe that this is not a duplicate.
### 🎯 Solution Description
The etcdv3 registry had three critical gaps compared to the zookeeper registry:
1. **DoUnregister was not implemented** — always returned `"DoUnregister is not support in etcdV3Registry"`.
The fix deletes the corresponding etcd key via `client.Delete`, guarded by a `client.Valid()` check.
2. **DoUnsubscribe was not implemented** — always returned an error.
The fix introduces a per-service listener architecture: `dataListener` now holds a
`subscribed map[string]ConfigurationListener` keyed by service key, replacing the old
single shared `configurationListener`. Each `DoSubscribe` call creates an independent
`configurationListener` for that service; `DoUnsubscribe` closes and removes it.
3. **Subscriptions were silently lost after reconnect** — `InitListeners` (called by `RestartCallBack`
on reconnect) replaced `dataListener` with an empty new instance, discarding all active
subscriptions. The fix stores `subscribeURL *common.URL` on each `configurationListener` and
adds a recovery loop in `InitListeners` that mirrors the zookeeper registry: close stale
listeners, create fresh ones, restart `ListenServiceEvent` goroutines for every recovered URL.
etcdv3 注册中心相比 zookeeper 注册中心存在三个关键缺口:
1. **DoUnregister 未实现** — 始终返回 `"DoUnregister is not support in etcdV3Registry"`。
修复:通过 `client.Delete` 删除对应 etcd key,调用前做 `client.Valid()` 校验。
2. **DoUnsubscribe 未实现** — 始终返回错误。
修复:引入 per-service listener 架构,`dataListener` 改为以 service key 为键的
`subscribed map`,取代原来全局共享的单个 `configurationListener`。每次 `DoSubscribe`
为该服务创建独立的 `configurationListener`;`DoUnsubscribe` 关闭并移除对应 listener。
3. **断线重连后订阅静默丢失** — `InitListeners`(重连时由 `RestartCallBack` 触发)将
`dataListener` 替换为空实例,所有活跃订阅被丢弃。
修复:在 `configurationListener` 上存储 `subscribeURL *common.URL`,在 `InitListeners`
中加入与 zookeeper 注册中心对齐的恢复循环:关闭旧 listener,为每个已订阅 URL 创建新
listener,重新启动 `ListenServiceEvent` goroutine。
### 📋 Use Cases
- Services that need to deregister from etcd on graceful shutdown.
- Services that dynamically subscribe/unsubscribe to providers at runtime.
- Long-running applications deployed in environments with unstable etcd connections (container
restarts, network partitions, etcd leader elections) that require seamless reconnect without
losing active subscriptions.
- 需要在优雅停机时从 etcd 注销的服务。
- 运行时动态订阅/取消订阅 provider 的服务。
- 部署在网络不稳定环境(容器重启、网络分区、etcd leader 选举)中、要求无感知重连且不丢失
订阅的长期运行应用。
### ⚖️ Complexity & Risks
- Medium complexity. The per-service listener refactor touches the core subscribe/unsubscribe path.
- `DataChange` now iterates all subscribed keys (instead of returning on first match), which is
a correctness improvement for wildcard/any-condition scenarios but changes the semantics slightly.
- `InitListeners` holds the old `dataListener` mutex for the duration of recovery via `defer`,
which may briefly delay concurrent `DataChange` calls — same trade-off as zookeeper.
- 中等复杂度,per-service listener 重构影响核心订阅/取消订阅路径。
- `DataChange` 改为遍历全部匹配 key(原先匹配即返回),对 wildcard/any-condition 场景是正确性
修复,但语义有轻微变化。
- `InitListeners` 通过 `defer` 持有旧 `dataListener` mutex 直至恢复完成,大量订阅时可能短暂
阻塞并发 `DataChange`,与 zookeeper 注册中心权衡一致。
### 🔗 External Dependencies
None. Changes are confined to `registry/etcdv3/listener.go` and `registry/etcdv3/registry.go`,
using existing `remoting/etcdv3` and `common.URL` APIs.
无外部依赖,改动限于 `registry/etcdv3/listener.go` 和 `registry/etcdv3/registry.go`,
使用已有的 `remoting/etcdv3` 和 `common.URL` API。
### 📘 Additional Context
Reference implementation for reconnect recovery: `registry/zookeeper/registry.go` — `InitListeners` (line 92-120).
重连恢复逻辑参考实现:`registry/zookeeper/registry.go` — `InitListeners`(第 92-120 行)。
如果觉得可以的话Assign me 然后我了解到我们目前需要将新注册中心迁移到dubbo-go-extension内作为插件使用 可以实现后进行迁移
Contributor guide
Assessment
This issue has not been assessed yet.