在 Linux 服务器上部署 Java Web 应用,核心目标是高并发下的稳定性、资源利用率的最大化以及故障的可观测性。国内主流云厂商(如阿里云、腾讯云、华为云等)提供的 ECS/CVM 实例通常基于 CentOS、Ubuntu 或 Alibaba Cloud Linux,底层内核优化逻辑相似。
以下是从操作系统内核参数、Java 虚拟机调优、网络配置到安全合规的完整配置指南:
一、 操作系统内核参数优化(sysctl)
Linux 默认的内核参数是为通用场景设计的,对于高负载的 Java Web 服务(尤其是 Nginx + Tomcat/Spring Boot 架构),需要调整以下关键参数:
1. 文件描述符限制
Java 应用和 Nginx 在高并发下会打开大量文件句柄(Socket、日志文件等)。
# /etc/security/limits.conf
* soft nofile 65535
* hard nofile 65535
root soft nofile 65535
root hard nofile 65535
注意:修改后需重新登录生效。
2. 内核网络栈优化
# /etc/sysctl.conf
# 增加本地端口范围,避免短连接耗尽端口
net.ipv4.ip_local_port_range = 10000 65535
# 启用 TCP 快速回收,TIME_WAIT 状态复用
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 0 # 注意:NAT 环境下建议关闭 tw_recycle,可能导致连接问题
# 增加 backlog 队列长度,应对突发流量
net.core.somaxconn = 1024
net.ipv4.tcp_max_syn_backlog = 1024
# 禁用 ICMP 重定向,防止路由欺骗
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
# 启用 SYN Cookies 防御 SYN Flood
net.ipv4.tcp_syncookies = 1
# 增加最大监听队列
net.core.netdev_max_backlog = 5000
# 禁用时间戳(可选,视具体场景而定,有时有助于减少 CPU 开销)
net.ipv4.tcp_timestamps = 0
执行 sysctl -p 使配置生效。
二、 Java 虚拟机(JVM)调优
JVM 是 Java 应用的“心脏”,配置不当会导致 Full GC 频繁、OOM(内存溢出)或 CPU 飙升。
1. 基础参数模板(以 Spring Boot 为例)
java -server
-Xms2g -Xmx2g # 堆初始大小和最大值设为一致,避免动态扩容带来的性能抖动
-XX:MetaspaceSize=256m # 元空间初始值
-XX:MaxMetaspaceSize=256m # 元空间最大值
-Xss256k # 每个线程栈大小,根据并发线程数调整,过小易 StackOverflow,过大浪费内存
-XX:+UseG1GC # 使用 G1 垃圾收集器(适合大内存、低延迟场景)
-XX:MaxGCPauseMillis=200 # 期望的最大 GC 停顿时间
-XX:+HeapDumpOnOutOfMemoryError # OOM 时生成堆转储
-XX:HeapDumpPath=/data/logs/java.hprof # 堆转储路径
-Djava.security.egd=file:/dev/./urandom # 解决 Random 初始化慢的问题
-jar app.jar
2. 关键注意事项
- 堆内存设置:
-Xms和-Xmx必须相等,防止 JVM 在运行时动态调整堆大小导致停顿。 - G1 收集器:对于现代 JDK(8u191+ / 11+),G1 是默认且推荐的选择。若使用 JDK 17+,可考虑 ZGC(需配合相应参数)。
- 监控集成:务必暴露 Actuator 指标或使用 Prometheus Node Exporter + JMX Exporter,以便实时观察 Heap、GC 次数、CPU 使用率。
三、 时间与字符集统一
1. 时区设置
确保服务器时区与应用预期一致,避免日志时间混乱。
timedatectl set-timezone Asia/Shanghai
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
2. 字符集编码
防止中文乱码,特别是涉及数据库交互和日志输出时。
# /etc/locale.gen
zh_CN.UTF-8 UTF-8
locale-gen zh_CN.UTF-8
export LANG=zh_CN.UTF-8
export LC_ALL=zh_CN.UTF-8
在 /etc/profile 或用户环境变量中永久生效。
四、 系统资源与进程管理
1. Swap 交换分区策略
对于 Java 应用,Swap 通常是敌人。当物理内存不足时,Swap 会导致严重的 I/O 等待和响应延迟。
# 查看当前 swappiness
cat /proc/sys/vm/swappiness
# 建议设置为 1 或 0,优先触发 OOM 而非 Swap
echo "vm.swappiness=1" >> /etc/sysctl.conf
sysctl -p
注:某些云厂商默认开启 Swap,建议手动调整或关闭。
2. 进程守护
使用 systemd 替代简单的 shell 启动脚本,实现自动重启和日志管理。
# /etc/systemd/system/myapp.service
[Unit]
Description=My Java Web App
After=network.target
[Service]
Type=simple
User=www-data
ExecStart=/usr/bin/java -jar /opt/app/app.jar
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
五、 安全与合规配置(国内环境重点)
1. 最小权限原则
- 不要以 root 身份运行 Java 应用。创建专用用户(如
appuser),仅赋予必要目录的执行权限。 - 使用非特权端口(>1024)反向X_X至后端,前端由 Nginx 绑定 80/443。
2. 防火墙与云安全组
- 云厂商控制台:配置安全组(Security Group),仅开放必要端口(如 80, 443, SSH 仅限特定 IP)。
- 主机防火墙:推荐使用
firewalld或iptables,但需注意与云安全组的协同,避免双重规则冲突。
3. 防暴力破解
安装 fail2ban 或类似工具,限制 SSH 登录失败次数。
4. 日志审计
- 保留至少 6 个月的访问日志和操作日志,满足《网络安全法》要求。
- 日志轮转:使用
logrotate管理应用日志,防止磁盘写满。
六、 常见坑点与排查建议
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 连接超时 | 防火墙/安全组未放行 | 检查云控制台安全组和主机 iptables |
| 内存泄漏 | 对象未释放、静态集合无限增长 | 使用 MAT/JProfiler 分析 heap dump |
| CPU 100% | 死循环、正则回溯、Full GC 频繁 | 抓取线程快照(jstack),定位热点代码 |
| 响应慢 | 数据库连接池耗尽、DNS 解析慢 | 检查 HikariCP 配置,启用 DNS 缓存 |
| 中文乱码 | 编码不一致 | 统一 JVM、DB、OS、浏览器编码为 UTF-8 |
总结
在 Linux 上运行 Java Web 应用,不是简单地 java -jar,而是一个系统工程:
- 内核层:调整文件句柄、TCP 栈参数,提升并发能力。
- JVM 层:合理设置堆内存、GC 策略,平衡吞吐与延迟。
- 运维层:使用 systemd 管理生命周期,自动化日志轮转,监控告警前置。
- 安全层:最小权限、安全组隔离、合规日志留存。
建议结合 Prometheus + Grafana + ELK(或阿里云 SLS、腾讯云 CLS)构建完整的可观测性体系,做到“事前预防、事中监控、事后追溯”。
CLOUD云枢