本文目录导读:

服务器卡顿是一个综合性问题,可能由硬件瓶颈、软件配置、网络延迟、代码逻辑或攻击导致,以下是一套系统化的排查与优化步骤,你可以按照“监控-诊断-优化”的流程来操作。
第一阶段:快速定位瓶颈(先判断是哪里慢)
当感觉服务器卡顿时,不要立即重启,先快速判断是服务器自身的问题,还是网络/客户端的问题。
-
本地Ping测试:
- 在自己电脑上
ping 服务器IP。 - 如果延时高或丢包:说明是网络问题(运营商、机房带宽、防火墙限流)。
- 如果延时正常:说明网络通畅,问题在服务器内部。
- 在自己电脑上
-
登录服务器查看负载:
- 执行
top或htop命令。 - 关注点:
load average是否超过CPU核心数(例如4核CPU负载超过4)? -> CPU或IO瓶颈%wa(I/O Wait)是否过高(>10%)? -> 磁盘读写太慢- 内存使用率是否接近100%,Swap使用率是否高? -> 内存不足
- 执行
第二阶段:按资源类型深入排查
根据第一阶段的发现,针对性地检查四种常见瓶颈。
CPU瓶颈(导致计算慢、响应延迟)
- 排查工具:
top-> 按P键按CPU占用率排序;ps aux --sort=-%cpu | head -10 - 常见原因:
- 死循环代码(例:
while(true){}) - 密集计算任务(视频处理、大数据排序)
- 被挖矿病毒占用
- 死循环代码(例:
- 优化方案:
- 代码层面:分析最耗CPU的函数(使用火焰图Profiling工具如
async-profiler),优化算法(如减少不必要的循环,使用缓存)。 - 进程层面:如果是不重要的后台进程,
kill掉,如果是合法进程,考虑水平扩展(加服务器)或升级CPU。
- 代码层面:分析最耗CPU的函数(使用火焰图Profiling工具如
内存瓶颈(导致系统用Swap,产生卡顿)
- 排查工具:
free -h,top(查看RES/VIRT列),vmstat 1 5(查看swap in/out) - 常见原因:
- Java/Python程序内存泄漏(对象一直不释放,GC频繁)
- 数据库吃掉大量内存
- 缓存设置过大(Redis峰值)
- 优化方案:
- 释放内存:使用
echo 3 > /proc/sys/vm/drop_caches(仅清理缓存,非必要不轻易用)。 - 代码调试:检查GC日志(如Java的
-XX:+PrintGCDetails),分析堆转储文件(heap dump)找到谁占用了内存。 - 配置调整:降低缓存TTL,限制单个进程最大内存(
ulimit或容器限制)。
- 释放内存:使用
磁盘I/O瓶颈(导致响应超时、操作卡顿)
- 排查工具:
iostat -x 1(查看%util和await),iotop(查看哪个进程在疯狂写盘) - 常见原因:
- 数据库慢查询(SQL全表扫描、大量临时表)
- 日志写得太频繁(
debug级别日志输出到控制台) - 系统Swap导致磁盘成为内存的替罪羊
- 优化方案:
- 数据库:检查慢查询日志(
slow_query_log),加索引或优化SQL。 - 日志:降低日志级别(改为
WARN),使用异步日志框架(如Logback AsyncAppender)。 - 硬件:机械硬盘(HDD)换成固态硬盘(SSD)是性价比很高的方案。
- 数据库:检查慢查询日志(
网络瓶颈(链接性差、带宽不够)
- 排查工具:
iftop(查看实时带宽),nethogs(按进程查看流量),netstat -anp(查看连接数),ss -s(查看socket统计) - 常见原因:
- 并发连接数耗尽(
TIME_WAIT过多) - 带宽被大文件下载或CC攻击占满
- 并发连接数耗尽(
- 优化方案:
- 系统参数(Linux内核优化):
- 修改
/etc/sysctl.conf:# 加快TIME_WAIT回收 net.ipv4.tcp_fin_timeout = 30 net.ipv4.tcp_tw_reuse = 1 # 增加队列长度 net.core.somaxconn = 1024
- 执行
sysctl -p立即生效。
- 修改
- 应用层面:开启连接池(如数据库连接池Druid);使用Nginx做反向代理+负载均衡;开启HTTP/2或长连接(Keep-Alive)。
- 系统参数(Linux内核优化):
第三阶段:特定场景的优化策略
如果上述通用资源排查都没问题,需结合具体场景:
Web服务器(Nginx/Apache)卡顿
- 排查:查看错误日志(
/var/log/nginx/error.log),检查worker_processes、worker_connections配置是否合理。 - 优化:
- 开启
gzip压缩(减少传输量)。 - 配置缓存(
proxy_cache或静态文件缓存)。 - 如果访问量巨大,加CDN是缓解服务器压力的最有效方式。
- 开启
数据库(MySQL/PostgreSQL)卡顿
- 排查:
show processlist;查看哪些查询在“Waiting”。 - 优化:
- 索引:对高频查询的列加索引。
- 慢查询:开启
slow_query_log,设置long_query_time = 2。 - 配置:增大
innodb_buffer_pool_size(MySQL中建议设为物理内存的60-70%)。 - 读写分离:主库写,从库读。
应用代码(Java/Python/Node.js)卡顿
- 排查:查看应用日志(是否有大量Warning/Error),使用APM工具(如SkyWalking, Pinpoint, New Relic)监控。
- 优化:
- 减少阻塞操作:用异步框架(如Node.js用async/await, Java用CompletableFuture)。
- 缓存热点数据:使用Redis或本地缓存(Caffeine)。
- 避免N+1查询:ORM框架(如EntityFramework, Hibernate)常见问题,记得批量加载。
第四阶段:预防与长期监控
卡顿往往发生在高峰期,等出问题再查就比较被动,建议部署监控系统。
- 基础监控:Zabbix / Prometheus + Grafana(监控CPU、内存、磁盘、网络)。
- 应用链路监控:SkyWalking / Pinpoint(监控一次请求在微服务间消耗的时间)。
- 告警设置:当CPU连续5分钟超过80%、磁盘占用超过90%时,发微信/邮件通知。
应急速查清单
如果现在服务器已经卡死,你只有1分钟时间:
- 第一步:
top看一眼,如果是Java进程占满CPU,用top -H -p [PID]找出具体线程,再转成16进制,去日志里查。 - 第二步:
free -m看一眼,如果Swap占用高,优先处理内存泄漏。 - 第三步:
dmesg | tail -20看一眼,如果出现Out of memory: Kill process或软锁,说明系统正在崩溃边缘。 - 第四步:如果都不行,且是生产环境,建议重启服务(如
systemctl restart nginx)或回滚代码,先恢复服务,再慢慢分析。
核心思路:不要凭感觉猜,用数据说话(CPU% 、IOWait、内存使用率、网络延迟),希望这套流程能帮你解决实际问题。