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.(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.(Thread.java:675)
 java.util.concurrent.Executors$DefaultThreadFactory.newThread(Executors.java:613)
 java.util.concurrent.ThreadPoolExecutor$Worker.(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

你可能感兴趣的:(springboot实战,mina框架)