问题背景
最近在维护一个在线文档处理服务时,频繁收到用户反馈文件上传和处理速度过慢的投诉。通过监控系统发现,服务器的CPU和内存使用率都处于合理范围内,但磁盘I/O等待时间却经常飙升到90%以上。这种典型的I/O瓶颈问题在数据密集型应用中很常见,今天就来分享我是如何定位和解决这个问题的。
初步诊断:识别I/O瓶颈
首先使用iostat命令查看磁盘I/O状况:
# 每2秒刷新一次,显示扩展统计信息
iostat -x 2
输出结果显示:
%util持续在95%以上await(平均I/O等待时间)高达150ms以上svctm(服务时间)相对正常
这表明磁盘已经严重过载,I/O请求在队列中等待时间过长。
深入分析:找出罪魁祸首
1. 使用iotop定位高I/O进程
iotop -o -P
发现主要问题是nginx和php-fpm进程在处理大文件上传时产生了大量临时文件写入操作。
2. 检查文件系统日志
dmesg | grep -i "error\|warning\|i/o"
发现了大量关于"I/O error"和"buffer I/O"的警告信息。
解决方案实施
优化文件系统挂载参数
原来的挂载参数比较简单:
/dev/sdb1 /data ext4 defaults 0 0
优化后的挂载选项:
/dev/sdb1 /data ext4 defaults,noatime,nodiratime,data=writeback 0 0
关键参数说明:
noatime和nodiratime:减少访问时间更新带来的I/O开销data=writeback:提高写入性能,但需要确保有可靠的UPS
调整I/O调度器
检查当前调度器:
cat /sys/block/sdb/queue/scheduler
将调度器从默认的cfq改为更适合SSD的deadline:
echo deadline > /sys/block/sdb/queue/scheduler
优化nginx临时文件配置
在nginx配置中增加缓冲优化:
client_body_buffer_size 1M;
client_max_body_size 10M;
client_body_temp_path /dev/shm/nginx_temp 1 2;
proxy_temp_path /dev/shm/nginx_proxy_temp;
这里的关键是把临时文件目录指向/dev/shm(内存文件系统),大幅减少磁盘I/O。
调整内核I/O参数
在/etc/sysctl.conf中添加:
# 增加脏页回写阈值
vm.dirty_ratio = 40
vm.dirty_background_ratio = 10
# 调整I/O队列深度
block.queue_depth = 256
# 优化虚拟内存参数
vm.swappiness = 10
vm.vfs_cache_pressure = 50
应用配置:
sysctl -p
监控与验证
优化后再次使用iostat监控:
iostat -x 2
关键指标改善:
%util从95%+降至40%-60%await从150ms+降至20ms左右- 用户响应时间改善明显
经验总结
- 监控先行:没有监控就谈不上优化,iostat、iotop是基础工具
- 分层排查:从应用层到系统层再到硬件层,逐层排查
- 权衡利弊:每个优化都有代价,比如data=writeback提高了性能但牺牲了数据安全性
- 持续观察:优化后要持续监控,确保没有引入新问题
这次调优让我深刻体会到,很多时候性能问题不是单一因素造成的,而是多个小问题的累积效应。通过系统性的分析和针对性的优化,往往能用较小的代价获得显著的性能提升。
暂无评论