记一次生产发版时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 ; }
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服务停用启用的问题的更多相关文章
- vs 发版时,在发版的文件夹中,找不到应该有的某个文件
检查:VS中,这个文件右击属性,查看生成操作.如果是“无”,改为“内容”.再重新发布就没问题了. 想看发版出来的内容包括哪些,可以从“发布”--“应用程序文件”查看
- 用node.js写一个jenkins发版脚本
背景 每次到网页里手动发版有点烦,写个脚本来提高开发效率. CFG 在 jenkins 设置里获取 API TOKEN. 把 host 和账号密码拼接起来就可以通过鉴权. const token = ...
- java生产环境增量发版陷阱【原】
前言 在生产环境,我们为了降低发版风险,一般都只做增量发布,不做全量发布. 除非项目只有一到两人开发,对时间线和代码脉络结构一清二楚,才可全量发布. 然而增量发布也是有一定隐藏陷阱在里面的,以下就是笔 ...
- CICD自动化发版系统设计简介
第一篇. 版本迭代是每一个互联网公司必须经历的,尤其是中小型公司,相信不少人踩到过很多坑.接下来的一系列文章将介绍我设计的自动化发版系统! 很多公司没有把配置独立出去,代码的构建.发版通过一个Jenk ...
- 【解决方案】SpringCloud项目优雅发版、部署
背景 SpringCloud分布式项目,部署在多个节点上.一般的发版方式是,使用Kill -15 pid,逐一地关闭.部署.重启. 但中间涉及到一个问题,当执行kill命令时,服务虽然关闭,但Eure ...
- CI/CD自动化发版系统设计简介
转载自:https://www.cnblogs.com/wellful/archive/2004/01/13/10604151.html 版本迭代是每一个互联网公司必须经历的,尤其是中小型公司,相信不 ...
- 使用 shell 脚本自动获取发版指标数据
问题背景 大一点的公司都会建立一套规章流程来避免低级错误,例如合入代码前必需经过同行评审:上线前必需提测且通过 QA 验证:全量前必需经过 1%.5%.10%.20%.50% 的灰度过程.尤其是最后一 ...
- Jenkins日常运维笔记-重启数据覆盖问题、迁移、基于java代码发版(maven构建)
之前在公司机房部署了一套jenkins环境,现需要迁移至IDC机房服务器上,迁移过程中记录了一些细节:1)jenkins默认的主目录放在当前用户家目录路径下的.jenkins目录中.如jenkins使 ...
- 阿里云移动研发平台 EMAS 助力银行业打造测试中台,提升发版效能
随着移动互联网的发展,手机银行凭借低成本.操作简单.不受时间空间约束等优势,正逐步替代传统的网银交易方式.越来越多的银行开始了“业务移动化”转型之路,“手机APP”已经成为企业价值传递和关系维护的关键 ...
随机推荐
- web 批量打印
批量打印,同时打印多个页面,有两种思路: 第一种思路,将所有的页面内容加载到一个页面中,然后再打印.这种打印方式有几个弊端,页面的样式会丢失,页面太多同时加载到一个页面中,数据量太大,响应时间很长,消 ...
- 微信分享 apicloud方式 中遇到的坎
1 appid填错了. 2 图片地址没写对,可能因为拼写问题,图片不存在 3 图片大小有限制.不能太大.
- 创建一个子进程---vfork
子.父进程共享数据段与堆栈段 函数原型:pid_t vfork(void) 返回值:子进程中返回0,父进程中返回子进程ID,出错返回-1. 注意: vfork创建的进程是按先子进程后父进程的顺序执行的 ...
- 负值之美:负margin在页面布局中的应用
本文转载自:http://www.topcss.org/?p=94,有修改. 负数给人总是一种消极.否定.拒绝之感,不过有时利用负margin可以达到奇妙的效果,今天就表一表负值在页面布局中的应用.这 ...
- using directive 使用指令,与using declaration使用声明。
使用指令是把名字空间中的所有名字引入到当前作用域,而使用声明是把名字空间的某个名字引入到当前作用域中 语法如下 //test.cpp #include<iostream> //using ...
- 2018.09.25 bzoj2286: [Sdoi2011]消耗战(虚树+树形dp)
传送门 又一道虚树入门题. 这个dp更简单啊. 直接记录每个点到1的距离,简单转移就行了. 代码: #include<bits/stdc++.h> #define N 250005 #de ...
- 着重基础之—Java 8 Comparator: How to Sort a List (List排序)
着重基础之—Java 8 Comparator: How to Sort a List (List排序) 首先申明,这篇博客的内容不是我自己的知识,我是从国外网站搬来的,原因有二:1是因为大天朝对网络 ...
- android apk签名原理
//这个md5跟腾讯的对应 public Signature getPackageSignature( ){ Context context=getContext(); String packageN ...
- js数组合并(一个数组添加到另一个数组里面)方法
js定义两个数组. var arrA=[1,2,3]; var arrB=[4,5,6]; 要实现[1,2,3,4,5,6],如果直接arrA.push(arrB); 则arrB只会作为了arrA的一 ...
- 用Git将项目发布在GitHub里
转载自http://blog.csdn.net/u011572517/article/details/50537407,个人加了一些注意事项和解释. githud是一个程序员以后成长都会使用到的,先不 ...