apache / apache/shenyu

[BUG] ZooKeeper registry keeps stale instances when the last child is removed

Open Beginner friendly
#6,526 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
8.8k
Forks
3.1k
Avg merge
7d 1h
Merged PRs (30d)
85

Description

### Search before asking

- [x] I had searched in the [issues](https://github.com/apache/shenyu/issues) and found no similar issues.

### Apache ShenYu Component

shenyu-registry

### What happened

`ZookeeperInstanceRegisterRepository.selectInstances()` maintains `watcherInstanceRegisterMap` from ZooKeeper child changes. The watcher callback only updates the cache when the new child list is not empty:

```java
List childrenList = StringUtils.isNotBlank(path) ? client.subscribeChildrenChanges(path, this)
: Collections.emptyList();
if (!childrenList.isEmpty()) {
watcherInstanceRegisterMap.put(selectKey, getInstanceRegisterFun.apply(childrenList));
}
```

When the last instance child under a watched service is removed, `childrenList` becomes empty. Because the callback skips the `put`, the old non-empty `watcherInstanceRegisterMap` entry remains.

Later `selectInstances(selectKey)` returns the stale cached instances immediately:

```java
if (watcherInstanceRegisterMap.containsKey(selectKey)) {
return watcherInstanceRegisterMap.get(selectKey);
}
```

So a service can continue to appear as having upstream instances even after all ZooKeeper instance nodes have been deleted.

### What you expected to happen

When ZooKeeper reports an empty child list for a watched service, ShenYu should update the cache to an empty list or remove the cache entry. Subsequent `selectInstances(selectKey)` calls should reflect that no instances remain.

### How to reproduce

1. Use ZooKeeper discovery.
2. Register one instance for a service and call `selectInstances(serviceName)` so `watcherInstanceRegisterMap` is populated.
3. Remove the only child instance node for that service.
4. Let the watcher callback run with an empty `childrenList`.
5. Call `selectInstances(serviceName)` again.
6. The method returns the old cached instance because the cache was not cleared or replaced with an empty list.

### Debug logs

_No response_

### Environment

Current master branch.

### Are you willing to submit PR?

- [ ] Yes I am willing to submit a PR!

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with ZookeeperInstanceRegisterRepository.selectInstances() and the watcher callback that updates watcherInstanceRegisterMap. Reproduce the sequence with one ZooKeeper child, remove it, and call selectInstances() again; done means an empty child list no longer leaves stale instances in the cache.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
distributed-systems
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.