V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
yangyuhan12138
V2EX  ›  程序员

springboot 优雅重启 钩子函数执行完成之后进程未消失

  •  1
     
  •   yangyuhan12138 · 2020-02-28 15:12:49 +08:00 · 3237 次点击
    这是一个创建于 1730 天前的主题,其中的信息可能已经有所发展或是发生改变。

    springboot1.x 优雅重启,钩子函数执行完成之后进程未消失,stop 脚本一直打印停止中,我也去看了 进程确实还在,但是请求也不再接收,而且钩子函数里的日志也打完了,说明钩子函数执行完成 测试环境测试无问题,生产上启动后过一会关闭也没问题,但是如果生产上程序跑了一两天,就关不了了

    22 条回复    2020-03-10 18:10:15 +08:00
    leonard916
        1
    leonard916  
       2020-02-28 15:32:18 +08:00
    為啥不升級到 Spring boot 2.2.x ?
    yangyuhan12138
        2
    yangyuhan12138  
    OP
       2020-02-28 15:36:28 +08:00
    @leonard916 版本不是你想升 想升就能升
    qfdk
        3
    qfdk  
       2020-02-28 15:38:55 +08:00 via iPhone
    优雅劝退 之前用过 actuator 里面有个重启的 boom
    yangyuhan12138
        4
    yangyuhan12138  
    OP
       2020-02-28 15:42:55 +08:00
    @qfdk 我没用 actuator 就是加了个钩子函数关闭 tomcat 线程池 在外边杀进程用的是 kill-15 ,很奇怪就是生产上不行 而且看日志 线程池是关完了的 就是进程一直在
    dzh213
        5
    dzh213  
       2020-02-28 16:16:09 +08:00
    之前遇到过,有任何线程关闭不了,都会造成程序假死,比如用过 Timer 写定时任务,kill -15 是杀不死的,手动申请的线程池没关闭等情况,尽量是优化代码。
    Kyle18Tang
        6
    Kyle18Tang  
       2020-02-28 16:20:31 +08:00
    我们按照官方文档, 打包成的 jar 可以用 systemctl restart 重启, 不知道 1.x 支不支持.
    yangyuhan12138
        7
    yangyuhan12138  
    OP
       2020-02-28 16:49:52 +08:00
    @dzh213 有没有办法看 java 中还在运行的所有线程啊 我这边没有单独开其他线程了 也没有定时任务
    yangyuhan12138
        8
    yangyuhan12138  
    OP
       2020-02-28 16:50:27 +08:00
    @Kyle18Tang 我们并没有把他做成系统服务 稍后我可以试试
    yangyuhan12138
        9
    yangyuhan12138  
    OP
       2020-02-28 17:12:24 +08:00
    systemctl 下边的停止命令还是自己写的啊 还不是得写 kill-15 应该没啥区别吧
    @Kyle18Tang
    Kyle18Tang
        10
    Kyle18Tang  
       2020-02-28 17:34:31 +08:00
    @yangyuhan12138 #9 停机也是使用的 stop, 不用自己写命令, 只是需要在打包的时候设置为可执行 jar 就行了, 但是要往 /etc/systemd/system/里新建一个.service 文件, 这个文件第一次建立就行了, 以后启动 jar 吧就可以使用 systemctl 了.
    dzh213
        11
    dzh213  
       2020-02-28 18:25:22 +08:00
    @yangyuhan12138 我是用比较笨的方法,一边猜一边测出来的,然后把相关代码优化了,比如我刚开始启动然后 kill 掉也是没问题的,启动后再请求一个接口,里面执行了一个没关闭的线程池,就 kill 不掉了。确实不好排查,建议修改 stop 脚本,先 kill -15,一定时长关闭不了,就强制 kill -9。
    AmmeLid
        12
    AmmeLid  
       2020-02-28 18:34:47 +08:00
    @dzh213 #11 可以 jstack 查线程状态
    yangyuhan12138
        13
    yangyuhan12138  
    OP
       2020-02-29 15:04:58 +08:00
    @AmmeLid 收到 我下周再试试 这个不是必然发生的 测试环境基本没有过 生产我们是双机 昨天测试的时候一台没 kill 掉 一台 kill 掉了
    yangyuhan12138
        14
    yangyuhan12138  
    OP
       2020-02-29 15:06:43 +08:00
    @Kyle18Tang 对啊 这个.service 文件里有 stop 的命令,但这个 stop 命令不还是自己写的吗 他只是把你写的 stop 命令执行了一下
    yangyuhan12138
        15
    yangyuhan12138  
    OP
       2020-02-29 15:38:26 +08:00
    @dzh213 可能是还有别的线程池没关到吧 我也觉得 但具体是哪个有点不好找
    Lighfer
        16
    Lighfer  
       2020-02-29 16:49:23 +08:00
    jstack 进程 id,所有线程都列出来,看看线程执行栈信息,过滤掉非 daemon 线程,基本就能定位了
    Kyle18Tang
        17
    Kyle18Tang  
       2020-02-29 21:08:41 +08:00
    @yangyuhan12138 没有 stop 命令,你可以看看官方文档。
    yangyuhan12138
        18
    yangyuhan12138  
    OP
       2020-03-04 17:02:12 +08:00
    @Lighfer 终于被我逮住了 又发生了两次 我 jstack 看了 我把文件 down 下来了 怎么分享出来给大家一起看呢 V2EX 咋分享文件啊
    yangyuhan12138
        19
    yangyuhan12138  
    OP
       2020-03-04 17:22:54 +08:00
    @Lighfer https://github.com/smartisanyyh/gracefulshutdowntrace 麻烦帮忙看看呢... 我看了下除掉 daemon 线程 有台机器上有些 rabbitmq 的连接没有关,另一台机器好像要正常许多 但是进程也没有掉
    yangyuhan12138
        20
    yangyuhan12138  
    OP
       2020-03-04 17:26:30 +08:00
    正常点的那台机器上只有三个线程不是 daemon 都处于 waiting 状态

    "DestroyJavaVM" #37 prio=5 os_prio=0 tid=0x00007f8d38008800 nid=0x49e waiting on condition [0x0000000000000000]
    java.lang.Thread.State: RUNNABLE

    "container-0" #20 prio=5 os_prio=0 tid=0x00007f8d39033800 nid=0x4bb waiting on condition [0x00007f8ce34f9000]
    java.lang.Thread.State: TIMED_WAITING (sleeping)
    at java.lang.Thread.sleep(Native Method)
    at org.apache.catalina.core.StandardServer.await(StandardServer.java:427)
    at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer$1.run(TomcatEmbeddedServletContainer.java:177)



    "Thread-3" #36 prio=5 os_prio=0 tid=0x00007f8ca8001000 nid=0x2e4e waiting on condition [0x00007f8ca0dda000]
    java.lang.Thread.State: TIMED_WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for <0x0000000086ede2a8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
    at java.util.concurrent.ThreadPoolExecutor.awaitTermination(ThreadPoolExecutor.java:1475)
    at com.dooffe.epay.common.api.DooffeEpayApiApplication$GracefulShutdown.shutDownThreadPool(DooffeEpayApiApplication.java:79)
    at com.dooffe.epay.common.api.DooffeEpayApiApplication$GracefulShutdown.onApplicationEvent(DooffeEpayApiApplication.java:69)
    at com.dooffe.epay.common.api.DooffeEpayApiApplication$GracefulShutdown.onApplicationEvent(DooffeEpayApiApplication.java:53)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:393)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:347)
    at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:991)
    at org.springframework.context.support.AbstractApplicationContext$2.run(AbstractApplicationContext.java:929)
    - locked <0x0000000085fe8e38> (a java.lang.Object)
    yangyuhan12138
        21
    yangyuhan12138  
    OP
       2020-03-10 18:06:41 +08:00
    @Kyle18Tang 我把生产上的服务变成了 service 启动 ,观察后发现还是有这个问题 ,执行完钩子函数后应用没有停止,因为 service stop 有超时时间所以一段时间后会强制结束进程
    yangyuhan12138
        22
    yangyuhan12138  
    OP
       2020-03-10 18:10:15 +08:00
    @Kyle18Tang 本质上和自己写脚本没有区别, 只是官方写了一段脚本让我们可以更方便的做成系统服务
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   912 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 39ms · UTC 21:45 · PVG 05:45 · LAX 13:45 · JFK 16:45
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.