• 记一次生产发版时SpringBoot服务停用启用的问题


    近期项目交接,接手了个SpringBoot项目。生产环境里,jar包是通过软链接做成linux服务来启动和停用。

    然而,每次通过jenkins构建发版,项目构建完毕,还要手动再去重启服务。

    听交接的同事说,可能是有一个钩子阻止服务停用了。

    但是,我还是有点纳闷的,既然阻止了服务停用,按道理服务是还能再运行的,不可能构建完了服务就不可用,然后还要手动重启。

    随后,我就开始了漫长的搜索……最后还是找到答案了。


    步骤重现:

    jenkins构建项目,执行脚本,停用服务

    service crm-base stop

    等了大约一分钟,窗口返回:

    Unable to kill process [*****]

    脚本执行完停止命令,随后执行启动命令

    Unable to kill process [*****]

    结果提示,服务正在运行。

    Already running [*****]

     

    然而,过了一会儿,去访问服务接口时,服务没有响应了。去查Eureka,微服务的状态此时是Down。

    查服务的状态

    service crm-base status

    结果服务是没有启动的

    Not running


    显然,执行了服务停止的命令是有效的,感觉是一段时间内服务没有停下来而提示“Unable to kill process”。

    接下来,在看到了SpringBoot的内嵌启动脚本源码,也印证了我的想法。

    stop() {
      working_dir=$(dirname "$jarfile")
      pushd "$working_dir" > /dev/null
      [[ -f $pid_file ]] || { echoYellow "Not running (pidfile not found)"; return 0; }
      pid=$(cat "$pid_file")
      isRunning "$pid" || { echoYellow "Not running (process ${pid}). Removing stale pid file."; rm -f "$pid_file"; return 0; }
      do_stop "$pid" "$pid_file"
    }
    
    do_stop() {
      kill "$1" &> /dev/null || { echoRed "Unable to kill process $1"; return 1; }
      for i in $(seq 1 $STOP_WAIT_TIME); do
        isRunning "$1" || { echoGreen "Stopped [$1]"; rm -f "$2"; return 0; }
        [[ $i -eq STOP_WAIT_TIME/2 ]] && kill "$1" &> /dev/null
        sleep 1
      done
      echoRed "Unable to kill process $1";
      return 1;
    }

    可以看到,执行停止方法,本质是做kill操作。方法内有一个for循环,从1遍历到$STOP_WAIT_TIME,每次循环休眠1秒。提示“Unable to kill process”有两处,一处是for循环前,一次是for循环后。

    至于$STOP_WAIT_TIME的默认值是多少,我们用Ctrl+F搜脚本

    # Initialize stop wait time if not provided by the config file
    [[ -z "$STOP_WAIT_TIME" ]] && STOP_WAIT_TIME="{{stopWaitTime:60}}"

    可以看到,如果没有配置设置停止等待时间,默认就是60秒。正好印证了这一问题,服务停止约一分钟就提示杀进程失败,而实际上是进程还在处理,需要等待,并非是钩子的问题。


    解决方法:

    在jar包路径下加jar包同名的配置文件(e.g.:jar包文件名为crm-base.jar,则添加配置的文件名称为crm-base.conf),在配置中调整停止等待时间为120秒

    STOP_WAIT_TIME=120

    再次尝试用jenkins构建,服务终于能顺利重启了。

    开始关闭服务
    -------------
    Stopped [28032]
    -------------
    开始启动服务
    Started [24119]

    所以,遇到问题的时候,百度是能短时间解决同类问题,但是找不到解决方法的,还是通过阅读源码最可靠。


    参考文档:

    [1]. https://github.com/spring-projects/spring-boot/issues/4369

    [2]. https://github.com/spring-projects/spring-boot/issues/10159

    [3]. https://www.jianshu.com/p/e21b95006371

    [4]. https://www.jianshu.com/p/1414dc49d3a9


  • 相关阅读:
    论工作动力的来源是什么?答案是来自于实现自己的梦想
    向梦想者致敬
    内置函数,递归函数,模块与包,开发目录规范
    迭代器,生成器
    闭包函数,装饰器,语法糖
    函数对象,名称空间及查找,作用域
    函数调用与参数
    字符编码
    文件处理
    python 11.5数据类型及常用方法
  • 原文地址:https://www.cnblogs.com/linhui0705/p/10793541.html
Copyright © 2020-2023  润新知