上线和构建时踩的几个坑

这篇记几次上线和构建时踩的坑,共同点是:看着都正常,其实不对。先交代一句,结论大多来自部署过程的记录,我没有一条条回去翻原始日志,没验证到的地方我会说明。

连接池一启动就报错

新接了一个分析型数据库的数据源,应用一起来,连接池初始化就打出一行 ERROR:testWhileIdle is true, validationQuery not set。有意思的是,用同一个库的另一条链路读数据是通的,说明库和网络都没问题,毛病出在新建的这个连接池配置上。

原因不复杂:Druid 的 testWhileIdle 默认开着,意思是空闲连接要定期检测是否有效,可检测得有条校验语句,我们这个数据源没配 validationQuery,两个设置自己打架。解决有两种,要么配一条适合这个库的校验语句,要么确认不需要空闲检测就把 testWhileIdle 关了。这次选了后者,只改了这一处配置和对应的单元测试断言,重新打包、测试都过了,重启后日志里也没再出现这条错误。

顺便提醒,新建 Druid 数据源时,testWhileIdle、testOnBorrow、validationQuery 这三个要放一起看,换了数据库,通用的校验语句不一定能用。

换了 jar,容器里还是旧的

新 jar 放到宿主机约定的目录了,容器却没用上。据部署记录的结论(我自己没单独复现),替换 jar 只是换了宿主机上的文件,Compose 配置没变,容器自然不会重建;而且是单文件挂载,文件被替换后是个新的 inode,旧容器里挂的还指着旧文件,得重建容器,挂载才会指到新文件上。

办法是换完文件后,对这个服务强制重建:docker compose up -d --force-recreate 加服务名,只动它,别的服务不碰。上线前还有两点:先把旧 jar 和配置备份好;再写个回滚判据,比如重建后 5 分钟内容器状态正常、日志没有启动失败、根路径返回 200,不满足就立刻换回备份重建,别让服务不可用地收工。

健康不等于配置对了

后来把数据库账号换成只读账号,重建了一次,健康检查通过,一切正常的样子。可我去只读核对容器里的实际环境,发现跟预期不一致,又重建一次才对上。健康检查通过只能说明服务起来了,不说明环境变量用的就是你想要的那份。所以改完配置以后,我现在直接看容器里实际的环境变量和生效配置,不拿"服务健康"当结论。

构建出来的包,把改好的东西改回去了

有个候选 JAR 要替换线上在用的版本。我把它跟已经交付的 JAR 逐个类比对,旧类 211 个,有 1 个字节不一样,是负责导出的那个类。原因是构建用的源码目录不对:这个目录里导出目录名还是旧的中文名,而我们之前已经改成了英文,改动在另一个目录里。候选 JAR 一旦替换上去,导出目录会变回中文。

当时负责构建的一方说"旧类字节都没变",但它比的是自己重新构建出来的基线,不是已经交付的那个 JAR,所以这个结论证明不了什么。两条经验:构建前确认用的是包含最新改动的那份源码;做"有没有变"的比对时,一定对着实际交付、实际在跑的产物比,别对着自己新造的基线。

git 突然报 dubious ownership

有一天 IDE 加一个本地仓库,直接报错,我自己命令行里也碰到过。一开始怀疑网络或仓库坏了,结果都不是:内网远端连得通,ls-remote 正常返回;本地分支和远端分支指向同一个提交,没差异。

真正的原因是这个仓库的 .git 目录的所有者,不是我当前登录的用户,而是之前用来跑自动化任务的另一个沙盒账户。git 发现 .git 不属于当前用户,出于安全考虑拒绝操作,报 detected dubious ownership,IDE 加仓库用的也是这个检查。解决办法是把这个目录加入 git 的安全目录:git config --global --add safe.directory 加仓库路径。这是改全局配置,我让用户自己在终端执行了一次,没替他改。之前我每条命令临时加参数绕过去,那只是治标。

小结

这几个坑有个共性:健康检查通过、文件已替换、字节没变、远端连得通,这些都只是表象。真要验证,得落到最底下的事实上:容器里实际的环境、实际在跑的包、对着交付物的比对、实际的目录所有者。

posted on 2026-11-02 10:19  因n而在  阅读(6)  评论(0)    收藏  举报

导航