Why Does Dubbo 2.7.3 Throw Duplicate Unregister Errors and How to Fix It

This article investigates the duplicate unregister bug in Dubbo 2.7.3, explains how the shutdown hook interaction causes the error, and shows how the issue was fixed in later versions and can be mitigated without upgrading the whole framework.

Xiao Lou's Tech Notes
Xiao Lou's Tech Notes
Xiao Lou's Tech Notes
Why Does Dubbo 2.7.3 Throw Duplicate Unregister Errors and How to Fix It

Background

I am responsible for the in‑house Dubbo registry center, and we frequently receive reports that Dubbo interface unregistration throws errors. Investigation revealed that the same interface was being unregistered twice, and because our registry does not allow repeated unregistration, the second call fails with an "instance not found" error.

Although the error only logs a single line and does not affect business, I decided to investigate further because repeated unregistration also prolongs application shutdown and slows rollback.

Problem Reproduction

Using the business side's customized Dubbo 2.7.3 (based on the open‑source 2.7.3 with security fixes and business adaptations), I ran a demo and killed the process, which reproduced the error.

Testing with the pure open‑source 2.7.3 produced the same error, confirming it is not caused by our internal modifications.

Switching to Dubbo 2.7.7 eliminated the error, indicating that the duplicate unregistration is a bug in 2.7.3 that was fixed in later versions.

Therefore, simply upgrading Dubbo would solve the problem, but internal modifications and business constraints make a direct upgrade non‑trivial.

Our internal Dubbo has custom changes that need to be merged into the new version, which is cumbersome.

Even if we upgraded, pushing the new version to the business side cannot be done quickly.

Thus we need to locate the root cause of the bug and see whether the registry extension can be patched; otherwise we must fix it in our customized Dubbo version.

Investigation

Suspecting ShutdownHook

Because I had recently studied ShutdownHook, I first suspected it might be involved.

In Dubbo 2.7.3 the shutdown hook implementation resides in the DubboShutdownHook class, and the relationship is shown below.

Both Dubbo and Spring register a ShutdownHook, so I debugged to see if the hook was registered twice. Using IntelliJ IDEA, the process must be killed manually to trigger the debug; clicking the IDE’s close button does not fire the hook.

Setting a breakpoint in DubboShutdownHook.doDestroy showed it executes only once, meaning Spring and Dubbo each register the hook only once. The following diagram illustrates the registration order.

In Dubbo, the register and unregister methods manage the ShutdownHook. When Spring’s ConfigurableApplicationContext is initialized, it registers its own hook and then calls DubboShutdownHook.getDubboShutdownHook().unregister(), effectively replacing Dubbo’s hook with Spring’s.

public static void addApplicationContext(ApplicationContext context) {
    CONTEXTS.add(context);
    if (context instanceof ConfigurableApplicationContext) {
        ((ConfigurableApplicationContext) context).registerShutdownHook();
        DubboShutdownHook.getDubboShutdownHook().unregister();
    }
    BeanFactoryUtils.addApplicationListener(context, SHUTDOWN_HOOK_LISTENER);
}

This proved the ShutdownHook suspicion was not the cause of the duplicate unregistration.

Continuing Investigation from the Unregister Stack

Because the issue could be reproduced reliably, I examined the call stacks of the two unregister invocations. Adding breakpoints in the registry extension’s unregister method revealed two distinct stack traces.

The code shows that AbstractRegistryFactory.destroyAll() destroys all registries, which in turn calls destroyProtocols(). Each protocol obtains the registry and invokes its unregister method, leading to two separate unregister calls.

Thus a single ShutdownHook execution triggers two unregisters.

In Dubbo 2.7.7, the registry protocol adds a small piece of code during destruction: after the registry is destroyed, a destroyed flag is set to true. When the protocol later attempts to obtain the registry again, it receives a null registry, so the subsequent unregister call has no effect.

The fix was introduced in a pull request that landed in version 2.7.5.

https://github.com/apache/dubbo/pull/5450

Therefore the duplicate unregister bug exists in Dubbo 2.7.0 ~ 2.7.4, was fixed in 2.7.5, and while Zookeeper registries may not surface an error, the extra unregistration slows down application shutdown.

Summary

Dubbo duplicate unregister issue exists in 2.7.0‑2.7.4 and is fixed in 2.7.5; ZK registry does not error but the slowdown is real.

The problem can be resolved by adjusting the registry extension so that destroy is invoked only once.

Investigating even small issues can reveal clever designs, such as Dubbo’s elegant handling of ShutdownHook registration.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaBackend DevelopmentDubboBug FixShutdownHookDuplicate Unregister
Xiao Lou's Tech Notes
Written by

Xiao Lou's Tech Notes

Backend technology sharing, architecture design, performance optimization, source code reading, troubleshooting, and pitfall practices

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.