springboot+mina框架服務端的實現(三) ------ 關於用tomcat優雅關閉mina的簡單研究

在之前的代碼中,創建mina連接時,NioSocketAcceptor採用的註解@bean中,destroyMethoddestroy
在tomcat中執行shutdown.sh後,可能會出現內存泄漏的情況,例如:

 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.6.RELEASE)

2019-07-08 15:26:14.928  INFO 27200 --- [250-startStop-1] org.my.ServletInitializer                : Starting ServletInitializer on ybtserver with PID 27200 (/usr/src/springboot_mina-0.0.1-SNAPSHOT/WEB-INF/classes started by root in /usr/local/tomcat/bin)
2019-07-08 15:26:14.932  INFO 27200 --- [250-startStop-1] org.my.ServletInitializer                : No active profile set, falling back to default profiles: default
08-Jul-2019 15:26:15.844 INFO [192.168.10.250-startStop-1] org.apache.catalina.core.ApplicationContext.log Initializing Spring embedded WebApplicationContext
2019-07-08 15:26:15.845  INFO 27200 --- [250-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 860 ms
2019-07-08 15:26:16.136  INFO 27200 --- [250-startStop-1] org.my.mina.handler.ServerHandler        : >>>>>> server handlers set success!
2019-07-08 15:26:16.595  INFO 27200 --- [250-startStop-1] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2019-07-08 15:26:16.825  INFO 27200 --- [250-startStop-1] org.my.ServletInitializer                : Started ServletInitializer in 2.394 seconds (JVM running for 4.674)
2019-07-08 15:26:16.832  INFO 27200 --- [250-startStop-1] org.my.mina.MinaServerRun                : ---springboot mina server start---
08-Jul-2019 15:26:16.895 INFO [192.168.10.250-startStop-1] org.apache.jasper.servlet.TldScanner.scanJars At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
08-Jul-2019 15:26:16.941 WARNING [main] org.apache.catalina.mapper.MapperListener.findDefaultHost Unknown default host [localhost] for service [StandardService[Catalina]]
08-Jul-2019 15:26:16.943 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-20080"]
08-Jul-2019 15:26:16.952 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["ajp-nio-20009"]
08-Jul-2019 15:26:16.954 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 4059 ms
08-Jul-2019 15:26:44.670 INFO [main] org.apache.catalina.core.StandardServer.await A valid shutdown command was received via the shutdown port. Stopping the Server instance.
08-Jul-2019 15:26:44.671 INFO [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["http-nio-20080"]
08-Jul-2019 15:26:44.682 INFO [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["ajp-nio-20009"]
08-Jul-2019 15:26:44.688 INFO [main] org.apache.catalina.core.StandardService.stopInternal Stopping service [Catalina]
08-Jul-2019 15:26:44.696 INFO [192.168.10.250-startStop-2] org.apache.catalina.core.ApplicationContext.log Closing Spring root WebApplicationContext
08-Jul-2019 15:26:44.722 WARNING [192.168.10.250-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [ROOT] appears to have started a thread named [NioSocketAcceptor-2] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 java.lang.ClassLoader.defineClass1(Native Method)
 java.lang.ClassLoader.defineClass(ClassLoader.java:760)
 java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
 org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2401)
 org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:859)
 org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1333)
 org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1185)
 ch.qos.logback.classic.spi.PackagingDataCalculator.populateFrames(PackagingDataCalculator.java:74)
 ch.qos.logback.classic.spi.PackagingDataCalculator.calculate(PackagingDataCalculator.java:58)
 ch.qos.logback.classic.spi.ThrowableProxy.calculatePackagingData(ThrowableProxy.java:142)
 ch.qos.logback.classic.spi.LoggingEvent.<init>(LoggingEvent.java:122)
 ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:419)
 ch.qos.logback.classic.Logger.filterAndLog_0_Or3Plus(Logger.java:383)
 ch.qos.logback.classic.Logger.warn(Logger.java:692)
 org.apache.mina.util.DefaultExceptionMonitor.exceptionCaught(DefaultExceptionMonitor.java:47)
 org.apache.mina.core.polling.AbstractPollingIoAcceptor$Acceptor.run(AbstractPollingIoAcceptor.java:497)
 org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:64)
 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
 java.lang.Thread.run(Thread.java:745)
08-Jul-2019 15:26:44.734 INFO [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["http-nio-20080"]
08-Jul-2019 15:26:44.738 INFO [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["ajp-nio-20009"]
08-Jul-2019 15:26:44.741 INFO [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["http-nio-20080"]
08-Jul-2019 15:26:44.742 INFO [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["ajp-nio-20009"]

查詢了網上的資料,打算採用ServletContextListener來啓動mina,通過contextDestroyed方法來關閉mina,同時去掉@bean註解中的destroyMethod參數。

首先註釋掉MinaServerRun類的@Component註解,不再由這個類啓動mina。

然後創建一個listener來啓動mina,實現如下:

@WebListener
public class MinaRunServletContextListener implements ServletContextListener {

    private static final Logger logger = LoggerFactory.getLogger(MinaRunServletContextListener.class);

    @Autowired
    private NioSocketAcceptor acceptor;

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        logger.info("---server acceptor unbind---");
//        System.out.println("---server acceptor unbind---" + Thread.currentThread().getName());
        acceptor.unbind();
        logger.info("---server acceptor dispose---");
//        System.out.println("---server acceptor dispose---" + Thread.currentThread().getName());
        acceptor.dispose();
    }

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        WebApplicationContextUtils.getRequiredWebApplicationContext(sce.getServletContext())
                .getAutowireCapableBeanFactory().autowireBean(this);
        try {
            acceptor.bind(new InetSocketAddress(Const.PORT));
            logger.info("---springboot mina server start---");
        } catch (IOException e) {
            logger.error("---springboot mina server start error : ", e.getMessage() + "---");
        }
    }

}

同時啓動類中,加上@ServletComponentScan註解, 以便能夠掃描到自定義的這個listener。

結果如下:

08-Jul-2019 15:36:48.361 INFO [main] org.apache.catalina.core.StandardServer.await A valid shutdown command was received via the shutdown port. Stopping the Server instance.
08-Jul-2019 15:36:48.362 INFO [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["http-nio-20080"]
08-Jul-2019 15:36:48.373 INFO [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["ajp-nio-20009"]
08-Jul-2019 15:36:48.379 INFO [main] org.apache.catalina.core.StandardService.stopInternal Stopping service [Catalina]
08-Jul-2019 15:36:48.386 INFO [192.168.10.250-startStop-1] org.apache.catalina.core.ApplicationContext.log Closing Spring root WebApplicationContext
08-Jul-2019 15:36:48.414 WARNING [192.168.10.250-startStop-1] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [ROOT] appears to have started a thread named [NioSocketAcceptor-2] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 java.lang.Object.wait(Native Method)
 org.apache.mina.core.future.DefaultIoFuture.await0(DefaultIoFuture.java:218)
 org.apache.mina.core.future.DefaultIoFuture.awaitUninterruptibly(DefaultIoFuture.java:148)
 org.apache.mina.core.polling.AbstractPollingIoProcessor.dispose(AbstractPollingIoProcessor.java:188)
 org.apache.mina.core.service.SimpleIoProcessorPool.dispose(SimpleIoProcessorPool.java:337)
 org.apache.mina.core.polling.AbstractPollingIoAcceptor$Acceptor.run(AbstractPollingIoAcceptor.java:515)
 org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:64)
 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
 java.lang.Thread.run(Thread.java:745)
08-Jul-2019 15:36:48.416 WARNING [192.168.10.250-startStop-1] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [ROOT] appears to have started a thread named [NioProcessor-5] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:351)
 java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:941)
 java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1066)
 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
 java.lang.Thread.run(Thread.java:745)
08-Jul-2019 15:36:48.423 INFO [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["http-nio-20080"]
08-Jul-2019 15:36:48.428 INFO [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["ajp-nio-20009"]
08-Jul-2019 15:36:48.432 INFO [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["http-nio-20080"]
08-Jul-2019 15:36:48.433 INFO [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["ajp-nio-20009"]

好像不太對,除了NioSocketAcceptor外,NioProcessor創建的線程也出現了內存泄漏的情況,而且定義的contextDestroyed方法中的日誌也沒打印,怎麼回事?

查詢了網上的衆多帖子,終於在一個帖子中找到了可能的原因:
springboot優雅的關閉應用

裏面提到:

將springboot應用註冊爲linux服務時,發現通過service xxx stop命令停止應用時,contextDestroyed的日誌根本沒打印出來,懷疑是LOGGER對象已經被jvm回收,於是改成System.out,這次begin打印出來了,但是並沒有調用 ShutdownUtil.destroy()方法,懷疑同上,具體的機制沒去詳細瞭解,猜測是springboot自己的回收策略,或者是該插件的坑。

於是採用sysout試了一下,結果如下:

08-Jul-2019 15:42:15.213 INFO [main] org.apache.catalina.core.StandardServer.await A valid shutdown command was received via the shutdown port. Stopping the Server instance.
08-Jul-2019 15:42:15.214 INFO [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["http-nio-20080"]
08-Jul-2019 15:42:15.224 INFO [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["ajp-nio-20009"]
08-Jul-2019 15:42:15.230 INFO [main] org.apache.catalina.core.StandardService.stopInternal Stopping service [Catalina]
08-Jul-2019 15:42:15.237 INFO [192.168.10.250-startStop-1] org.apache.catalina.core.ApplicationContext.log Closing Spring root WebApplicationContext
---server acceptor unbind---192.168.10.250-startStop-1
---server acceptor dispose---192.168.10.250-startStop-1
08-Jul-2019 15:42:15.262 WARNING [192.168.10.250-startStop-1] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [ROOT] appears to have started a thread named [NioSocketAcceptor-2] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 java.security.AccessController.getStackAccessControlContext(Native Method)
 java.security.AccessController.getContext(AccessController.java:820)
 java.lang.Thread.init(Thread.java:412)
 java.lang.Thread.init(Thread.java:349)
 java.lang.Thread.<init>(Thread.java:675)
 java.util.concurrent.Executors$DefaultThreadFactory.newThread(Executors.java:613)
 java.util.concurrent.ThreadPoolExecutor$Worker.<init>(ThreadPoolExecutor.java:612)
 java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:925)
 java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1368)
 org.apache.mina.core.polling.AbstractPollingIoProcessor.startupProcessor(AbstractPollingIoProcessor.java:475)
 org.apache.mina.core.polling.AbstractPollingIoProcessor.dispose(AbstractPollingIoProcessor.java:185)
 org.apache.mina.core.service.SimpleIoProcessorPool.dispose(SimpleIoProcessorPool.java:337)
 org.apache.mina.core.polling.AbstractPollingIoAcceptor$Acceptor.run(AbstractPollingIoAcceptor.java:515)
 org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:64)
 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
 java.lang.Thread.run(Thread.java:745)
08-Jul-2019 15:42:15.271 INFO [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["http-nio-20080"]
08-Jul-2019 15:42:15.275 INFO [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["ajp-nio-20009"]
08-Jul-2019 15:42:15.279 INFO [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["http-nio-20080"]
08-Jul-2019 15:42:15.280 INFO [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["ajp-nio-20009"]

發現sysout確實打印出來了,看來logger對象可能已經被spring回收了,但還是出現了內存泄漏的情況,這個可能是因爲NioSocketAcceptor對象已經被回收了,於是註釋掉contextDestroyed方法中的內容,同時在@bean註解中添加destroyMethod = "unbind"參數。
重新嘗試:

08-Jul-2019 15:49:58.150 INFO [main] org.apache.catalina.core.StandardServer.await A valid shutdown command was received via the shutdown port. Stopping the Server instance.
08-Jul-2019 15:49:58.151 INFO [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["http-nio-20080"]
08-Jul-2019 15:49:58.161 INFO [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["ajp-nio-20009"]
08-Jul-2019 15:49:58.167 INFO [main] org.apache.catalina.core.StandardService.stopInternal Stopping service [Catalina]
08-Jul-2019 15:49:58.174 INFO [192.168.10.250-startStop-1] org.apache.catalina.core.ApplicationContext.log Closing Spring root WebApplicationContext
08-Jul-2019 15:49:58.197 WARNING [192.168.10.250-startStop-1] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [ROOT] appears to have started a thread named [pool-3-thread-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 sun.misc.Unsafe.park(Native Method)
 java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
 java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:460)
 java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:362)
 java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:941)
 java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1066)
 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
 java.lang.Thread.run(Thread.java:745)
08-Jul-2019 15:49:58.207 INFO [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["http-nio-20080"]
08-Jul-2019 15:49:58.210 INFO [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["ajp-nio-20009"]
08-Jul-2019 15:49:58.213 INFO [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["http-nio-20080"]
08-Jul-2019 15:49:58.214 INFO [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["ajp-nio-20009"]

還是存在內存泄漏情況,打算放棄這種方式,採用最初的方式試一下,通過MinaServerRun類啓動,畢竟最初的方式沒有嘗試修改destroyMethod後是否能正常使用。

結果如下:

08-Jul-2019 15:53:27.170 INFO [main] org.apache.catalina.core.StandardServer.await A valid shutdown command was received via the shutdown port. Stopping the Server instance.
08-Jul-2019 15:53:27.171 INFO [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["http-nio-20080"]
08-Jul-2019 15:53:27.182 INFO [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["ajp-nio-20009"]
08-Jul-2019 15:53:27.188 INFO [main] org.apache.catalina.core.StandardService.stopInternal Stopping service [Catalina]
08-Jul-2019 15:53:27.193 INFO [192.168.10.250-startStop-1] org.apache.catalina.core.ApplicationContext.log Closing Spring root WebApplicationContext
08-Jul-2019 15:53:27.206 WARNING [192.168.10.250-startStop-1] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [ROOT] appears to have started a thread named [pool-3-thread-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 sun.misc.Unsafe.park(Native Method)
 java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
 java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:460)
 java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:362)
 java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:941)
 java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1066)
 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
 java.lang.Thread.run(Thread.java:745)
08-Jul-2019 15:53:27.211 INFO [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["http-nio-20080"]
08-Jul-2019 15:53:27.214 INFO [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["ajp-nio-20009"]
08-Jul-2019 15:53:27.217 INFO [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["http-nio-20080"]
08-Jul-2019 15:53:27.218 INFO [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["ajp-nio-20009"]

怎麼還是有問題,頭都大了。。。。。。

嘗試將destroyMethod換成dispose

08-Jul-2019 15:55:52.872 INFO [main] org.apache.catalina.core.StandardServer.await A valid shutdown command was received via the shutdown port. Stopping the Server instance.
08-Jul-2019 15:55:52.873 INFO [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["http-nio-20080"]
08-Jul-2019 15:55:52.883 INFO [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["ajp-nio-20009"]
08-Jul-2019 15:55:52.888 INFO [main] org.apache.catalina.core.StandardService.stopInternal Stopping service [Catalina]
08-Jul-2019 15:55:52.895 INFO [192.168.10.250-startStop-1] org.apache.catalina.core.ApplicationContext.log Closing Spring root WebApplicationContext
08-Jul-2019 15:55:52.941 INFO [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["http-nio-20080"]
08-Jul-2019 15:55:52.944 INFO [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["ajp-nio-20009"]
08-Jul-2019 15:55:52.948 INFO [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["http-nio-20080"]
08-Jul-2019 15:55:52.949 INFO [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["ajp-nio-20009"]

終於不再出現內存泄漏情況。。。。。。

爲避免是偶爾出現,再次嘗試:

08-Jul-2019 15:57:06.149 INFO [main] org.apache.catalina.core.StandardServer.await A valid shutdown command was received via the shutdown port. Stopping the Server instance.
08-Jul-2019 15:57:06.150 INFO [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["http-nio-20080"]
08-Jul-2019 15:57:06.161 INFO [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["ajp-nio-20009"]
08-Jul-2019 15:57:06.167 INFO [main] org.apache.catalina.core.StandardService.stopInternal Stopping service [Catalina]
08-Jul-2019 15:57:06.173 INFO [192.168.10.250-startStop-1] org.apache.catalina.core.ApplicationContext.log Closing Spring root WebApplicationContext
08-Jul-2019 15:57:06.213 INFO [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["http-nio-20080"]
08-Jul-2019 15:57:06.216 INFO [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["ajp-nio-20009"]
08-Jul-2019 15:57:06.219 INFO [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["http-nio-20080"]
08-Jul-2019 15:57:06.219 INFO [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["ajp-nio-20009"]
08-Jul-2019 15:57:57.310 INFO [main] org.apache.catalina.core.StandardServer.await A valid shutdown command was received via the shutdown port. Stopping the Server instance.
08-Jul-2019 15:57:57.311 INFO [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["http-nio-20080"]
08-Jul-2019 15:57:57.319 INFO [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["ajp-nio-20009"]
08-Jul-2019 15:57:57.325 INFO [main] org.apache.catalina.core.StandardService.stopInternal Stopping service [Catalina]
08-Jul-2019 15:57:57.330 INFO [192.168.10.250-startStop-1] org.apache.catalina.core.ApplicationContext.log Closing Spring root WebApplicationContext
08-Jul-2019 15:57:57.358 INFO [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["http-nio-20080"]
08-Jul-2019 15:57:57.361 INFO [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["ajp-nio-20009"]
08-Jul-2019 15:57:57.364 INFO [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["http-nio-20080"]
08-Jul-2019 15:57:57.365 INFO [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["ajp-nio-20009"]

貌似可以了,看來採用listener的方式應該也行的通,於是嘗試使用listener,調整的地方和上面嘗試listener時一樣,在contextDestroyed方法中多打印一句System.out.println("---test contextDestroyed method---");
結果如下:

08-Jul-2019 16:03:03.981 INFO [main] org.apache.catalina.core.StandardServer.await A valid shutdown command was received via the shutdown port. Stopping the Server instance.
08-Jul-2019 16:03:03.982 INFO [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["http-nio-20080"]
08-Jul-2019 16:03:03.992 INFO [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["ajp-nio-20009"]
08-Jul-2019 16:03:03.998 INFO [main] org.apache.catalina.core.StandardService.stopInternal Stopping service [Catalina]
08-Jul-2019 16:03:04.003 INFO [192.168.10.250-startStop-1] org.apache.catalina.core.ApplicationContext.log Closing Spring root WebApplicationContext
---test contextDestroyed method---
08-Jul-2019 16:03:04.041 INFO [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["http-nio-20080"]
08-Jul-2019 16:03:04.043 INFO [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["ajp-nio-20009"]
08-Jul-2019 16:03:04.046 INFO [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["http-nio-20080"]
08-Jul-2019 16:03:04.046 INFO [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["ajp-nio-20009"]

God bless me !!!
終於優雅的關閉了mina!!!

還是建議通過MinaServerRun類來啓動mina,因爲可以在啓動mina服務後,增加鉤子方法,當linux採用kill指令關閉tomcat時,還可以優雅的關閉mina:

		Runtime.getRuntime().addShutdownHook(new Thread() {

            @Override
            public void run() {
                logger.info("---server acceptor unbind---");
                acceptor.unbind();
                logger.info("---server acceptor dispose---");
                acceptor.dispose();
            }

        });

首先查出來tomcat所在的進程,然後使用kill指令:

[root@server bin]# ps -ef|grep tomcat
root     31849     1  0 16:08 pts/0    00:00:00 /bin/sh /usr/local/tomcat/bin/catalina.sh start
root     31850 31849 99 16:08 pts/0    00:00:18 /usr/local/jdk1.8.0_66/bin/java -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -classpath /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp org.apache.catalina.startup.Bootstrap start
root     31926 15970  0 16:08 pts/0    00:00:00 grep tomcat
[root@server bin]# kill 31850
[root@server bin]# tail -n 50 -f /usr/local/tomcat/logs/catalina.out

查看日誌關鍵內容如下:

2019-07-08 16:08:29.872  INFO 31850 --- [       Thread-7] org.my.mina.MinaServerRun                : ---server acceptor unbind---
08-Jul-2019 16:08:29.873 INFO [Thread-8] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["http-nio-20080"]
2019-07-08 16:08:29.878  INFO 31850 --- [       Thread-6] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'
2019-07-08 16:08:29.880  INFO 31850 --- [       Thread-7] org.my.mina.MinaServerRun                : ---server acceptor dispose---
08-Jul-2019 16:08:29.894 INFO [Thread-8] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["ajp-nio-20009"]
08-Jul-2019 16:08:29.900 INFO [Thread-8] org.apache.catalina.core.StandardService.stopInternal Stopping service [Catalina]
08-Jul-2019 16:08:29.906 INFO [192.168.10.250-startStop-2] org.apache.catalina.core.ApplicationContext.log Closing Spring root WebApplicationContext
08-Jul-2019 16:08:29.918 INFO [Thread-8] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["http-nio-20080"]
08-Jul-2019 16:08:29.921 INFO [Thread-8] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["ajp-nio-20009"]
08-Jul-2019 16:08:29.924 INFO [Thread-8] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["http-nio-20080"]
08-Jul-2019 16:08:29.924 INFO [Thread-8] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["ajp-nio-20009"]

可以看到NioSocketAcceptor對象被正常的關閉了。

工程的github地址:
https://github.com/gavinL93/springboot_mina

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章