You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@dubbo.apache.org by "superleo-cn (GitHub)" <gi...@apache.org> on 2019/09/22 03:17:27 UTC

[GitHub] [dubbo] superleo-cn commented on issue #4288: dubbo2.7.1官网上优雅停机示例方法没有

先说结论:如果是和Spring集成那么这个不用担心2个冲突执行的问题,因为初始化的时候dubbo就从runtime改到spring context上去了:

源码追踪如下:

Dubbo源码 org.apache.dubbo.config.spring.extension.SpringExtensionFactory.java:
```java
public class SpringExtensionFactory implements ExtensionFactory {
    private static final Logger logger = LoggerFactory.getLogger(SpringExtensionFactory.class);

    private static final Set<ApplicationContext> CONTEXTS = new ConcurrentHashSet<ApplicationContext>();
    private static final ApplicationListener SHUTDOWN_HOOK_LISTENER = new ShutdownHookListener();

    public static void addApplicationContext(ApplicationContext context) {
        CONTEXTS.add(context);
        if (context instanceof ConfigurableApplicationContext) {
            // 注册到spring上面
            ((ConfigurableApplicationContext) context).registerShutdownHook();
            // 从java.lang.Runtime.getRuntime() 中取消注册
            DubboShutdownHook.getDubboShutdownHook().unregister();
        }
        BeanFactoryUtils.addApplicationListener(context, SHUTDOWN_HOOK_LISTENER);
    }

```

然后在 Spring接到kill信号的时候,进入hook回调,然后spring在依次去调用Application Event通知各个注册在spring hook的bean去执行他们自己的hook回调:

这个是dubbo和spring集成后的hook操作
```java
private static class ShutdownHookListener implements ApplicationListener {
        @Override
        public void onApplicationEvent(ApplicationEvent event) {
            if (event instanceof ContextClosedEvent) {
                DubboShutdownHook shutdownHook = DubboShutdownHook.getDubboShutdownHook();
                shutdownHook.doDestroy();
            }
        }
    }
```

等到执行完成后,spring才去销毁对象。

Spring 源码 org.springframework.context.support.AbstractApplicationContext.java:
```java

protected void doClose() {
	// Check whether an actual close attempt is necessary...
	if (this.active.get() && this.closed.compareAndSet(false, true)) {
		if (logger.isDebugEnabled()) {
			logger.debug("Closing " + this);
		}

		LiveBeansView.unregisterApplicationContext(this);

		try {
			// 看这里,通知各个hook去关闭
			publishEvent(new ContextClosedEvent(this));
		}
		catch (Throwable ex) {
			logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
		}

		// Stop all Lifecycle beans, to avoid delays during individual destruction.
		if (this.lifecycleProcessor != null) {
			try {
				this.lifecycleProcessor.onClose();
			}
			catch (Throwable ex) {
				logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
			}
		}

		// 开始销毁单例对象等
		destroyBeans();

		// 销毁Bean工厂
		closeBeanFactory();

		// Let subclasses do some final clean-up if they wish...
		onClose();

		// Reset local application listeners to pre-refresh state.
		if (this.earlyApplicationListeners != null) {
			this.applicationListeners.clear();
			this.applicationListeners.addAll(this.earlyApplicationListeners);
		}

		// Switch to inactive.
		this.active.set(false);
		...
	}
}	

```



[ Full content available at: https://github.com/apache/dubbo/issues/4288 ]
This message was relayed via gitbox.apache.org for notifications@dubbo.apache.org