线上问题排查——磁盘满

现象

群里反馈管理后台登录不上了,我一访问,整个界面空白,没有提示,打开 F12,发现控制台提示 js、css 等静态资源报 net::ERR_HTTP2_PROTOCOL_ERROR,客户端可以下载到服务端资源,第一次碰到这个,StackOverflow 走起

net::ERR_HTTP2_PROTOCOL_ERROR 是关于什么的?

可能出现的问题非常多,包括磁盘满、nginx 配置问题、请求头问题、浏览器问题、cdn 问题。因为这个服务没有更新过,也没人动过配置,所以不太可能是 nginx、服务的问题,另外每次下载 js 文件,似乎都不是完整的,虽然服务器都有做出响应。

所以初步判断是服务器出了问题,但是没有配置 ssh,登录阿里云后台的手机也在公司,没办法看到服务器监控。

此时发现多刷新几次,利用浏览器的本地缓存,首页还是能访问出来的,但是登录功能无法响应,如果填了错误的验证码,可以立马返回错误信息。说明 MySQL 写受到了影响,基本上可以是断定服务器的磁盘、内存问题。

第二天到了公司看控制台监控,好家伙磁盘占用 99%

刷新了一下管理后台,响应非常非常的慢;先清理空间再验证是否这个问题

解决

列出所有挂载的文件系统,并显示每个文件系统的总空间、已用空间、可用空间和使用率。

shell 复制代码
df -h

#Filesystem      Size  Used Avail Use% Mounted on
#udev             16G     0   16G   0% /dev
#tmpfs           3.1G  724K  3.1G   1% /run
#/dev/vda1        99G   94G  343M 100% /
#tmpfs            16G     0   16G   0% /dev/shm
#tmpfs           5.0M     0  5.0M   0% /run/lock
#tmpfs            16G     0   16G   0% /sys/fs/cgroup
#tmpfs           3.1G     0  3.1G   0% /run/user/0

这时候要注意了,如果直接从根目录递归查找,会消耗大量的 CPU 和 IO 资源,可能会导致服务器变得非常慢,甚至暂时无法响应,所以要一层一层来

shell 复制代码
# /* 换成对应的目录即可
du -sh /* | sort -rh | head -n 10

最终找出了两个目录,nacos 的 access 日志 和 MySQL binlog 日志,总计 80G 空间,其中大部分都是七天前的,可处理

对于 nacos 的日志,直接删了之前的就好。而 MySQL 的 binlog 文件,建议从控制台执行命令

mysql 复制代码
# 删除 七天前的 binlog
PURGE BINARY LOGS BEFORE NOW() - INTERVAL 7 DAY;

最终,处理了 40% 的空间

验证

多次强制刷新前端页面,静态资源和接口的响应速度也变快了。

接下来看一下昨天的日志,MySQL 除了写数据时获取不到锁,没有其他报错

包括 nginx 日志, /var/log/syslog 系统日志,/var/log/mysql/error.log 提示空间不足

log 复制代码
2024-08-13T02:27:02.537301Z 1256492 [ERROR] [MY-000035] [Server] Disk is full writing './binlog.000556' (OS errno 28 - No space left on device). Waiting for someone to free space... Retry in 60 secs. Message reprinted in 600 secs.
2024-08-13T02:37:02.571302Z 1256492 [ERROR] [MY-000035] [Server] Disk is full writing './binlog.000556' (OS errno 28 - No space left on device). Waiting for someone to free space... Retry in 60 secs. Message reprinted in 600 secs.
2024-08-13T02:47:02.605275Z 1256492 [ERROR] [MY-000035] [Server] Disk is full writing './binlog.000556' (OS errno 28 - No space left on device). Waiting for someone to free space... Retry in 60 secs. Message reprinted in 600 secs.
2024-08-13T02:57:02.640862Z 1256492 [ERROR] [MY-000035] [Server] Disk is full writing './binlog.000556' (OS errno 28 - No space left on device). Waiting for someone to free space... Retry in 60 secs. Message reprinted in 600 secs.
2024-08-13T03:07:02.674508Z 1256492 [ERROR] [MY-000035] [Server] Disk is full writing './binlog.000556' (OS errno 28 - No space left on device). Waiting for someone to free space... Retry in 60 secs. Message reprinted in 600 secs.
2024-08-13T03:17:02.710238Z 1256492 [ERROR] [MY-000035] [Server] Disk is full writing './binlog.000556' (OS errno 28 - No space left on device). Waiting for someone to free space... Retry in 60 secs. Message reprinted in 600 secs.

除了页面实际上变快了,没有其他日志信息进一步确认

后续工作

由于日志问题导致磁盘空间不足,需要启用定时器或者自带工具进行定时清理

nacos access 日志

对于 nacos 没有提供对 access log 没有提供大小、分割配置,只有开关,而线上不建议关闭,所以需要编写 shell 脚本,加入定时器中

生产环境编写定时任务Crontab, 将脚本放到/etc/cron.daily 目录,赋予可执行权限

shell 复制代码
#!/bin/bash

logFile="/data/nacos/bin/logs/nacos_del_access.log"
# 保留14天日志
date=`date -d "$date -14 day" +"%Y-%m-%d"`
# 具体位置可调整
delFilePath="/data/nacos/bin/logs/access_log.${date}.log"

if [ ! -f "${logFile}" ];then
	echo 'access log文件打印日志频繁. /etc/cron.daily/nacosDelAccessLogs.sh 会定时删除access日志文件' >>${logFile}
fi
# 日志文件存在, 则删除
if [  -f "${delFilePath}" ];then
	rm -rf ${delFilePath}
	curDate=`date --date='0 days ago' "+%Y-%m-%d %H:%M:%S"`
	echo '['${curDate}'] 删除文件'${delFilePath} >>${logFile}
fi

MySQL binlog

建议保留七天或十四天,使用 MySQL 自带配置即可

mysql 复制代码
# 我的默认配置三十天
# -- binlog_expire_logs_seconds	2592000
# SHOW VARIABLES LIKE 'binlog_expire_logs_seconds';
SET GLOBAL binlog_expire_logs_seconds = 604800;

show VARIABLES like 'expire_logs_days';

set global expire_logs_days = 7;

之前是使用这两个命令,新版 MySQL 被废弃了

永久生效,my.conf,需要重启

conf 复制代码
[mysqld]
binlog_expire_logs_seconds = 604800

后面添加日志,需要进行管理和轮换日志文件,可以考虑使用 logrotate

参考:

  1. https://stackoverflow.com/questions/58215104/whats-the-neterr-http2-protocol-error-about
  2. https://blog.csdn.net/wtzvae/article/details/107212870
  3. https://blog.51cto.com/haibo0668/5486115
  4. https://blog.csdn.net/mr_wanter/article/details/112515814
js 复制代码
这是一段防爬代码块,我不介意文章被爬取,但请注明出处
console.log("作者主页:https://www.cnblogs.com/Go-Solo");
console.log("原文地址:https://www.cnblogs.com/Go-Solo/p/18358836");