美文网首页
记一次服务Connection refused

记一次服务Connection refused

作者: 李昂的数字之旅 | 来源:发表于2018-05-10 20:56 被阅读0次

    起因

    服务B上日志显示,请求服务A连接被拒(Connection refused)???

    1. 猜测一 服务进程崩了?

    登录时服务A的机器,ps -ef|grpep java查看jvm还在。

    1. 猜测二 端口绑定错了?

    服务端口通过配置参数-Dserver.port=8080绑定,
    ps -ef|grpep java还是通过这个命令查看,端口是8080没错
    telnet 127.0.0.1 8080响应Connection refused
    netstat -lntp|grep 8080没有结果。 jvm进程启动成功,端口没绑上去???

    1. 猜测三 服务hang住了或死锁

    top -Hp pgrep java查看jvm进程的线程详情,看那个cpu使用率最高,cpu使用并不多,而且cpu使用率也是来回在换,不像死循环。
    printf "%x\n" {pid} 找了个相对比较活跃的进程号,格式转为十六进制,准备到打印线程快照找一下是哪个线程有问题。
    jstack -l pgrep java > stack.log查看线程,搜索{十六进制},看到是vert.x-eventpool-thread-0线程,状态是RUNNABLE稳稳的。搜索blocked/dead关键字没发现问题。

    1. 猜测四 看一下log文件

    最后一段日志是,服务重启了,启动过程中在调用DB相关Bean foo时报org.springframework.beans.factory.UnsatisfiedDependencyException,原因是foo在注册时因为“Too many connections”导致数据库连接不成功,时foo注册失败,spring boot报错,且应用启动失败Application startup failed

    这么看来问题已经找到,spring容易启动失败,所以端口也没去绑定。但是spring失败了,为什么jvm没结束???

    其实在前面的jstack日志里可以发现原因
    grep 'nid=' stack.log|grep -v 'daemon' 查看非守护线程数,还有好几个线程还没结束。
    来回顾下jvm结束的条件:所有非守护进程结束时,jvm自动退出

    问题总结

    问题原因是spring boot在启动因为Bean注册失败,抛异常而启动失败,但由于有其他非守护线程存在,而jvm不能正常结束。

    解决方案

    通过spring的FailureAnalyzer捕获异常UnsatisfiedDependencyException,把未关闭的线程资源关闭掉,做统一的处理,jvm就能正常关闭。

    FailureAnalyzer使用
    public class DBFailureAnlyzer extends AbstractFailureAnalyzer<XXXException> {
        @Override
        protected FailureAnalysis analyze(Throwable rootFailure, XXXException cause) {
           //do something
            return new FailureAnalysis("由于xx原因,应用启动失败", "清理存活的线程", cause);
        }
    }
    在META-INF/spring.factories文件中添加一下内容
    org.springframework.boot.diagnostics.FailureAnalyzer=\
    com.xx.www.DBFailureAnlyzer,\
    com.xx.www.DBFailureAnlyzer1
    

    相关文章

      网友评论

          本文标题:记一次服务Connection refused

          本文链接:https://www.haomeiwen.com/subject/pwytdftx.html