dubbo [Bug]Service reference fails when using providedBy after listener destruction

4urapxun  于 5个月前  发布在  其他
关注(0)|答案(3)|浏览(44)

Apache Dubbo Component

Java SDK (apache/dubbo)

Dubbo Version

3.1.11

Steps to reproduce this issue

  1. Define a service reference with a specific provider:
@DubboReference(providedBy = "app1")
private APIService apiService;
  1. Zookeeper has data:
    get /dubbo/mapping/com.example.APIService value:app1,app2
  2. The app1 listener gets destroyed.
  3. Try to use another service from app1:
@DubboReference(providedBy = "app1")
private API2Service api2Service;

Result: No provider found.

What you expected to happen

The service reference should succeed.

Anything else

  1. Why is the mapping being looked up when the provider is already specified?
  2. In the code that handles service instance changes:
if (!oldListener.hasListeners()) {
    oldListener.destroy(); // 🪵
    removeAppSubscriptionLock(appKey);
}

Is it necessary to remove the oldListener from the serviceListeners Map after it has called destroy?

  1. Would it be correct to add a line to remove old listeners from serviceListeners, like this:
if (!oldListener.hasListeners()) {
    oldListener.destroy();
    // Remove old listeners from serviceListeners
    serviceListeners.remove(appKey);
    removeAppSubscriptionLock(appKey);
}

Are you willing to submit a pull request to fix on your own?

No

Code of Conduct

  • I agree to follow this project's Code of Conduct

This consolidated version includes all the key points from your original issue, including the code snippets and your questions about the listener removal process.

7jmck4yq

7jmck4yq1#

for (String newAppName : newApps) {
                    if (!tempOldApps.contains(newAppName)) {
                        serviceNameMapping.removeCachedMapping(ServiceNameMapping.buildMappingKey(url));
                        serviceNameMapping.putCachedMapping(ServiceNameMapping.buildMappingKey(url), newApps);
                        // old instance listener related to old app list that needs to be destroyed after subscribe refresh.
                        ServiceInstancesChangedListener oldListener = listener.getServiceListener();
                        if (oldListener != null) {
                            String appKey = toStringKeys(toTreeSet(tempOldApps));
                            Lock appSubscriptionLock = getAppSubscription(appKey);
                            try {
                                appSubscriptionLock.lock();
                                oldListener.removeListener(url.getServiceKey(), listener);
                                if (!oldListener.hasListeners()) {
                                    oldListener.destroy(); // 🪵
                                    removeAppSubscriptionLock(appKey);
                                }
                            } finally {
                                appSubscriptionLock.unlock();
                            }
                        }

                        subscribeURLs(url, listener, newApps);
                        oldApps = newApps;
                        return;
                    }
                }

Is it necessary to remove the oldListener from the serviceListeners Map after it has called destroy?

fgw7neuy

fgw7neuy2#

After experimenting, if I add a new lineRemove old listeners from serviceListeners. Is it right to do so?

if (!oldListener.hasListeners()) {
      oldListener.destroy();
      // Remove old listeners from serviceListeners
      serviceListeners.remove(appKey);
      removeAppSubscriptionLock(appKey);
  }

相关问题