近期项目交接,接手了个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 ; }
pid=$(cat "$pid_file")
isRunning "$pid" || { echoYellow "Not running (process ${pid}). Removing stale pid file."; rm -f "$pid_file"; return ; }
do_stop "$pid" "$pid_file"
} do_stop() {
kill "$1" &> /dev/null || { echoRed "Unable to kill process $1"; return ; }
for i in $(seq $STOP_WAIT_TIME); do
isRunning "$1" || { echoGreen "Stopped [$1]"; rm -f "$2"; return ; }
[[ $i -eq STOP_WAIT_TIME/ ]] && kill "$1" &> /dev/null
sleep
done
echoRed "Unable to kill process $1";
return ;
}

可以看到,执行停止方法,本质是做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=

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

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

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

参考文档:

[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

记一次生产发版时SpringBoot服务停用启用的问题的更多相关文章

  1. vs 发版时,在发版的文件夹中,找不到应该有的某个文件

    检查:VS中,这个文件右击属性,查看生成操作.如果是“无”,改为“内容”.再重新发布就没问题了. 想看发版出来的内容包括哪些,可以从“发布”--“应用程序文件”查看

  2. 用node.js写一个jenkins发版脚本

    背景 每次到网页里手动发版有点烦,写个脚本来提高开发效率. CFG 在 jenkins 设置里获取 API TOKEN. 把 host 和账号密码拼接起来就可以通过鉴权. const token = ...

  3. java生产环境增量发版陷阱【原】

    前言 在生产环境,我们为了降低发版风险,一般都只做增量发布,不做全量发布. 除非项目只有一到两人开发,对时间线和代码脉络结构一清二楚,才可全量发布. 然而增量发布也是有一定隐藏陷阱在里面的,以下就是笔 ...

  4. CICD自动化发版系统设计简介

    第一篇. 版本迭代是每一个互联网公司必须经历的,尤其是中小型公司,相信不少人踩到过很多坑.接下来的一系列文章将介绍我设计的自动化发版系统! 很多公司没有把配置独立出去,代码的构建.发版通过一个Jenk ...

  5. 【解决方案】SpringCloud项目优雅发版、部署

    背景 SpringCloud分布式项目,部署在多个节点上.一般的发版方式是,使用Kill -15 pid,逐一地关闭.部署.重启. 但中间涉及到一个问题,当执行kill命令时,服务虽然关闭,但Eure ...

  6. CI/CD自动化发版系统设计简介

    转载自:https://www.cnblogs.com/wellful/archive/2004/01/13/10604151.html 版本迭代是每一个互联网公司必须经历的,尤其是中小型公司,相信不 ...

  7. 使用 shell 脚本自动获取发版指标数据

    问题背景 大一点的公司都会建立一套规章流程来避免低级错误,例如合入代码前必需经过同行评审:上线前必需提测且通过 QA 验证:全量前必需经过 1%.5%.10%.20%.50% 的灰度过程.尤其是最后一 ...

  8. Jenkins日常运维笔记-重启数据覆盖问题、迁移、基于java代码发版(maven构建)

    之前在公司机房部署了一套jenkins环境,现需要迁移至IDC机房服务器上,迁移过程中记录了一些细节:1)jenkins默认的主目录放在当前用户家目录路径下的.jenkins目录中.如jenkins使 ...

  9. 阿里云移动研发平台 EMAS 助力银行业打造测试中台,提升发版效能

    随着移动互联网的发展,手机银行凭借低成本.操作简单.不受时间空间约束等优势,正逐步替代传统的网银交易方式.越来越多的银行开始了“业务移动化”转型之路,“手机APP”已经成为企业价值传递和关系维护的关键 ...

随机推荐

  1. 有关于mfc webbrowser插件的使用

    最近写的东西中常常需要嵌入一些浏览器,微软提供了一个比较好的接口,可以在MFC写的程序中嵌入一个简易的浏览器,是以ActiveX插件的形式提供的接口,使用起来也比较的方便,这里我就简单记录下这个插件的 ...

  2. gis笔记 wms wfs等OGC标准

    WFS 和WMS的区别 WFS是基于地理要素级别的数据共享和数据操作,WFS规范定义了若干基于地理要素(Feature)级别的数据操作接口,并以 HTTP 作为分布式计算平台.通过 WFS服务,客户端 ...

  3. python的metaclass浅析-乾颐堂

    元类一般用于创建类.在执行类定义时,解释器必须要知道这个类的正确的元类.解释器会先寻找类属性__metaclass__,如果此属性存在,就将这个属性赋值给此类作为它的元类.如果此属性没有定义,它会向上 ...

  4. AE教程:学会这个,你做的Logo就可以单独出道了

    一.确定所需要做的动效 1.制作logo背景形状动效 2.制作U的动效 3.制作I的动效 4.制作消失动效 二.制作logo背景形状动效1.”合成 - 新建合成“ 新建一个1000*800的合成 2. ...

  5. 五步打造APP节日主题设计:以Lofter新年图标设计为例

    我们需要做有依据,有逻辑,有理念的设计,需要发散思维,整合创意,严谨输出,让设计经得起推敲 前言 ​ 2018年春节已远去,一直想把Lofter新年Logo设计思路分享给大家,直到现在才整理出来,希望 ...

  6. gdb 调试带参数程序

    在gdb中,运行程序使用r或是run命令. 程序的运行,你有可能需要设置下面四方面的事. 1.程序运行参数. set args 可指定运行时参数.(如:set args 10 20 30 40 50) ...

  7. jQuery load和unload函数使用

    实例 当用户点击链接离开本页时,弹出一个消息框: $(window).unload(function(){ alert("Goodbye!"); }); 亲自试一试 定义和用法 当 ...

  8. Find the squareroot

    https://github.com/Premiumlab/Python-for-Algorithms--Data-Structures--and-Interviews/blob/master/Moc ...

  9. Java知识系列 -- 反射

    原理 要想理解 Java 反射,首先要弄清类的加载过程. 比如这行代码 Person p = new Person();. 我们想要创建一个 Person 对象,并用 p 作为对象的引用. 在 Jav ...

  10. 15) maven dependency scope

    Dependency Scope Dependency scope is used to limit the transitivity of a dependency, and also to aff ...