一台新服务器上线 Java 服务,我会检查这 20 项
JDK装好了,JAR也能启动。
这台服务器就可以上生产了吗?
不一定。
很多线上事故和业务代码没有关系:
服务用root运行 服务器重启后应用没有自动启动 时区错误导致定时任务提前执行 文件句柄太小导致无法建立新连接 日志没有轮转写满磁盘 Heap Dump目录没有写权限 DNS配置错误导致偶发请求超时 回滚时才发现旧版本已经被覆盖下面这20项,是我接手一台新Linux服务器、准备部署Java服务时会做的基础检查。
它和“Spring Boot应用上线检查”不完全相同。
这篇重点看的是:
服务器本身,是否具备长期、稳定、安全地运行Java服务的条件。
说明:命令以常见Linux发行版为例,不同系统的包管理器、服务名称和安全策略可能不同。涉及防火墙、内核参数、用户权限和时间同步的修改,应先经过测试与变更审批。
一、账号与基础环境
1. 不要长期使用root运行Java服务
先确认进程准备使用哪个账号:
idorderapp如果没有专用账号,可以按团队规范创建系统用户:
sudouseradd--system\--home/opt/order-service\--shell/usr/sbin/nologin\orderapp业务应用一旦存在命令执行、文件写入或依赖漏洞,root权限会把影响范围放大到整台服务器。
专用用户至少要做到:
不能交互登录 只拥有应用所需目录权限 不能随意读取其他服务配置 不能直接修改系统文件2. 固定部署、配置和日志目录
建议把目录职责分开:
/opt/order-service/releases/ 版本目录 /opt/order-service/current 当前版本软链接 /etc/order-service/ 配置目录 /var/log/order-service/ 日志目录 /var/lib/order-service/ 持久化工作数据检查:
namei-l/opt/order-service/current namei-l/var/log/order-service不要把JAR、配置、上传文件、日志和Heap Dump全部堆在同一个临时目录。
目录清晰,才能回答:
哪个文件可以覆盖? 哪个目录需要备份? 哪个目录允许应用写入? 磁盘满了应该清理哪里?3. 检查目录所有者和写入权限
sudo-uorderapp\test-r/opt/order-service/current/app.jar\&&echo"jar readable"sudo-uorderapp\test-w/var/log/order-service\&&echo"log writable"还要验证:
临时目录 上传目录 导出目录 Heap Dump目录 日志目录最常见的问题不是“没有权限”,而是部分目录由root在发布时创建,应用运行几天后才在某个异常分支写入失败。
4. 确认时区和时间同步
timedatectl重点看:
Time zone System clock synchronized NTP service服务器、JVM、数据库和日志平台的时间需要能够对齐。
时钟错误会影响:
定时任务 订单过期 Token有效期 证书校验 分布式锁 故障时间线 HikariCP定时行为不要只依赖虚拟化平台“顺便同步”,应确认操作系统里的时间同步服务实际工作。
5. 检查主机名和DNS解析
hostnamectlcat/etc/resolv.conf getent hosts db.internal.example确认:
主机名符合资产规范 DNS服务器正确 内部域名能稳定解析 正向解析不会偶发超时有些“数据库偶发连接超时”,最后并不是数据库问题,而是内部DNS响应不稳定。
如果使用/etc/hosts临时绑定地址,要记录原因和维护责任,避免目标IP变化后长期指向旧节点。
二、CPU、内存与磁盘
6. 确认CPU和系统负载基线
lscpu nprocuptime记录:
逻辑CPU数量 NUMA情况 虚拟化类型 上线前Load Average不要拿到“8核服务器”就直接给所有业务线程池配成64。
还要考虑:
同机其他进程 数据库连接数 容器CPU限制 任务是否CPU密集7. 确认物理内存、Swap和JVM预算
free-hswapon--show内存预算不能只计算-Xmx。
Java进程还会使用:
Metaspace 线程栈 直接内存 Code Cache GC结构 JIT Agent 本地库 文件页缓存例如一台8GB服务器,不应该因为:
-Xmx8g看起来正好,就把全部内存交给Java堆。
Swap是否启用、如何使用要结合业务延迟要求和团队规范决定,但必须提前知道当前状态,而不是发生长时间卡顿后才发现机器一直在换页。
8. 检查磁盘容量、文件系统和inode
df-hTdf-ilsblk-f确认:
应用目录在哪个分区 日志目录在哪个分区 Heap Dump可能写到哪里 剩余空间和inode是否充足 文件系统类型是否符合要求Heap Dump大小可能接近Java堆的实际占用。
如果-Xmx4g,但Dump目录只剩2GB,真正OOM时可能连诊断文件都写不出来。
还要给日志、发布包、临时文件和旧版本保留空间。
9. 检查磁盘性能基线
iostat-xz15新服务器“磁盘有500GB”不代表磁盘性能一定正常。
上线前至少记录:
await 队列长度 读写吞吐 设备忙碌程度云盘规格、共享存储、突发额度和挂载方式都可能影响延迟。
有了空载基线,线上出现I/O告警时才知道偏离了多少。
10. 检查文件句柄和进程限制
当前Shell限制:
ulimit-nulimit-usystemd服务的实际限制:
systemctl show order-service\-pLimitNOFILE\-pLimitNPROC需要注意:
登录Shell里的
ulimit,不一定等于systemd服务实际拿到的限制。
Java服务会使用文件句柄承载:
Socket连接 日志文件 JAR和类文件 临时文件 监控Agent限制过低时可能报:
Too many open files具体数值要结合并发连接和系统容量评估,不要盲目全部改成无限。
这20项更适合在发布前逐项核对。可以先收藏,等真正上服务器时照着检查;后面的网络、进程托管、日志和回滚,才最容易在事故里暴露问题。
三、网络与运行时
11. 检查端口占用和监听地址
ss-lntp发布前确认目标端口未被占用:
ss-lntp|grep':8080'启动后确认:
监听端口正确 监听进程正确 监听地址符合网络拓扑127.0.0.1:8080和0.0.0.0:8080的含义不同。
如果Nginx和应用不在同一网络空间,监听地址错误会造成“本机能访问,网关一直502”。
12. 检查防火墙和安全组
根据发行版查看:
sudofirewall-cmd --list-all或者:
sudonft list ruleset云服务器还要检查云平台安全组。
原则是:
只开放必要端口 管理端口只允许受控来源 数据库和Redis不直接暴露公网 Actuator不全量暴露公网不要为了快速联调临时开放全部端口,然后忘记收回。
13. 验证关键依赖的网络连通性
例如:
nc-vzdb.internal.example3306nc-vzredis.internal.example6379curl-fsShttps://config.internal.example/health至少覆盖:
数据库 Redis 配置中心 注册中心 消息队列 对象存储 外部HTTP服务能建立TCP连接不代表业务一定可用,但可以先排除:
路由 端口 防火墙 DNS不要等应用启动失败后,再逐个猜依赖。
14. 固定并验证JDK版本
java-versionreadlink-f"$(command-vjava)"确认:
JDK主版本 具体补丁版本 安装路径 systemd使用的Java路径交互式Shell里执行的java,可能来自PATH。
systemd里的ExecStart最好使用明确的绝对路径:
ExecStart=/usr/lib/jvm/java-17/bin/java ...否则服务器升级、PATH变化或多版本共存时,应用可能在重启后使用另一个JDK。
15. 明确JVM参数和诊断文件路径
至少检查:
Xms与Xmx GC选择 GC日志 Heap Dump 时区 编码 应用ProfileJDK 17示例:
-Xms1g-Xmx1g-XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=/var/lib/order-service/dump -Xlog:gc*,safepoint:/var/log/order-service/gc.log:time,uptime,level,tags:filecount=10,filesize=100M重点不是复制参数,而是验证:
目录可写 日志会轮转 磁盘装得下 参数与服务器资源匹配启动后用:
jcmd<PID>VM.command_line确认实际生效参数,不要只看发布脚本。
四、服务托管与发布保障
16. 使用服务管理器托管进程
单机生产环境建议使用systemd等服务管理方式,而不是只依赖后台Shell命令。
检查:
systemctl status order-service --no-pager systemctl is-enabled order-service至少明确:
运行用户 工作目录 启动命令 异常重启策略 停止信号 停止超时 环境配置来源服务异常退出、服务器重启和人工停止时,行为都应该是可预测的。
17. 检查配置和密钥的存放方式
重点排查:
数据库密码 Redis密码 对象存储密钥 JWT密钥 支付和短信Token 第三方API凭证不要把密钥写入:
Git仓库 JAR包 启动命令行 所有人可读的环境文件 日志如果使用配置文件:
ls-l/etc/order-service/确认所有者和权限。
具备条件时使用专门的Secret或密钥管理服务,并建立轮换与审计流程。
18. 确认日志轮转和保留策略
如果使用应用文件日志,检查Logback或Log4j2滚动策略:
单文件最大大小 保留天数 总容量上限 压缩策略 异常日志是否单独保存如果使用journald:
journalctl --disk-usage同时确认journald自身的容量限制。
日志系统至少要防住两件事:
单条异常无限刷屏 日志长期不清理写满磁盘还要对日志增长速度设置监控,而不是只监控当前磁盘使用率。
19. 准备版本回滚,而不是覆盖旧JAR
推荐使用版本目录:
/opt/order-service/releases/20260801-0850/ /opt/order-service/releases/20260725-0900/ /opt/order-service/current检查当前链接:
readlink-f/opt/order-service/current发布前要回答:
当前运行版本是什么? 上一个稳定版本在哪里? 配置是否兼容回滚? 数据库变更能否回退? 回滚需要多久?只有旧JAR还在,不代表具备真正的回滚能力。
数据库结构、缓存格式和消息协议同样需要兼容。
20. 做一次重启、验收和告警演练
最后不要只执行一次:
systemctl start order-service至少完成:
主动停止并确认优雅退出 重新启动并确认服务恢复 模拟进程异常退出并观察拉起 条件允许时验证服务器重启后自动启动 执行健康检查和核心只读接口 确认监控能够发现服务停止 确认告警能到达值班人员验收命令示例:
systemctl is-active order-service ss-lntp|grep':8080'curl-fsShttp://127.0.0.1:8080/actuator/health没有经过演练的自动重启、回滚和告警,只是配置文件里的愿望。
五、上线前的最终记录
建议把结果留成一张表:
| 检查项 | 结果 | 证据 |
|---|---|---|
| 专用用户 | 通过 | orderapp |
| 目录权限 | 通过 | JAR可读、日志可写 |
| 时间同步 | 通过 | NTP已同步 |
| DNS与依赖 | 通过 | 关键域名和端口可达 |
| CPU与内存 | 通过 | 已记录基线 |
| 磁盘与inode | 通过 | 低于告警线 |
| 文件句柄 | 通过 | systemd限制符合容量 |
| JDK与JVM参数 | 通过 | 已核对实际命令行 |
| 日志轮转 | 通过 | 已验证容量和保留 |
| systemd托管 | 通过 | enabled、active |
| 回滚 | 通过 | 已确认上一版本 |
| 重启与告警 | 通过 | 演练完成 |
不要在群里只留一句:
新服务器部署完成。以后出了问题,没有人知道当时检查过什么。
写在最后
一台服务器能把JAR跑起来,只能证明:
它现在可以启动。能够用于生产,还要证明:
权限可控 资源有余量 网络可达 日志不会失控 进程有人托管 故障能够告警 发布能够回滚 重启以后可以恢复本文归入「生产环境保命清单」系列,后续会继续整理Java服务部署、验收和故障演练清单。
你的生产上线清单里,哪一项最容易被忽略?或者你认为还应该补上“第21项”?欢迎在留言区补充。
系列导航
- 上一篇:《Nginx报upstream timed out:3个timeout到底该改哪个?》
- 系列起点:《HikariCP可用连接从30掉到0:一次连接泄漏的完整排查》
关注云技纵横,回复关键词保命,获取「生产环境保命清单」全部文章。
我会继续整理Java服务部署、验收和故障排查清单。也可以把脱敏后的服务器环境、部署方式和错误现象发来,我会尽量帮你判断还缺哪些检查。请务必隐藏密码、Token、IP、域名和客户数据。