
最近项目上线遇到一个奇怪问题:服务启动时报 ClassNotFoundException,但重启一下又好了! 一开始以为是偶然
经过排查,怀疑是 JAR包在传输过程中未完全传输完成,服务就启动了,导致java类加载失败。
为了解决这个问题,我在 Jenkins Pipeline 中加了MD5 校验机制,确保 JAR 包完整传输后才继续部署。
解决方案:在启动服务前,校验源文件与目标文件的 MD5 值是否一致,不一致就等待重试。
下面是 Jenkins Pipeline 脚本,
思路是:
stage("Jar Files Check") {
steps {
script {
def sMd5 = sh(
script: "ssh ${host} 'md5sum ${APP_SEND_PATH}/datacenter-${projectname}.jar' | awk '{print \$1}'",
returnStdout: true
).trim()
echo " 源文件 MD5: ${sMd5}"
for (tHost : HOSTS) {
stage("MD5 Check on ${tHost}") {
mRetries = 6
rCount = 0
boolean isOk = false
while (rCount < mRetries && !isOk) {
try {
def tMd5 = sh(
script: "ssh ${host} 'ssh ${tHost} md5sum ${Deploy_PATH}/datacenter-${projectname}.jar' | awk '{print \$1}'",
returnStdout: true
).trim()
echo "${tHost} 当前 MD5: ${tMd5}"
if (sMd5 == tMd5) {
echo "${tHost}: JAR 传输完成,MD5 校验通过!"
isOk = true
} else {
echo "${tHost}: JAR 传输未完成,等待 10 秒重试..."
sleep(time: 10, unit: "SECONDS")
rCount++
}
} catch (Exception e) {
echo "${tHost}: 获取 MD5 失败: ${e}"
rCount++
sleep(time: 10, unit: "SECONDS")
}
}
if (!isOk) {
error "${tHost}: JAR 校验失败,已重试 ${mRetries} 次推出"
}
}
}
}
}
}我在测试环境还真遇到过这个问题,由于是测试环境,经常资源饱和甚至不足导致 重启时服务器卡导致上一个进程未被kill掉, 新的进程起来后端口被占用未完全启动, 手动将上一次进程kill掉--问题解决