问题描述
在编写一篇文章并查看网站关于CloudKit文章时,发现服务器突然打不开。
并且网站报错为:Error establishing a database connection。
在尝试刷新页面后,网站直接显示nginx错误!
紧接着,我开始检查云服务器的状态,打开腾讯云页面,发现公网的带宽很高。
让我想起,上一次也是发现带宽很高的问题,那就是《服务器公网带宽达到上限排查问题》,当时也是很快的恢复了问题,没有检查到具体的报错原因,当时估计是某一个ip访问频率过高,爬虫或其他问题,导致的带宽达到上限,因此考虑封锁掉这一ip来解决问题,但排查的过程中,发现问题自动解决了,因此没有深入检查。
接着,我登陆到服务器,使用top命令,查看服务器的CPU、内存的状态。
这里,按M键隐藏/显示内存信息,按Shift + M键按内存排序。
截图中,可以看到服务器负载很高,特别是内存方面,下面。
KiB Mem : 2046504 total, 65564 free, 1746560 used, 234380 buff/cache
总内存为2046504KiB(约2GB),可用内存仅64MB,系统主要依赖于228MB的缓冲和缓存,因为没有启用Swap空间,导致内存耗尽时服务崩溃。
注:KiB和MB的计算方式,可以通过KiB / 1024进行计算,例如2046504KiB / 1024 = 1998.53MB,所以是2GB的内存。
快速解决方案
在定位到问题为内存后,首先启用Swap:
sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
启用Swap后,使用free -m命令,检查是否启用成功:
free -m
持久化到系统启动:
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
接着需要释放内存:
sudo sync; sudo sysctl -w vm.drop_caches=3
当启用Swap后,重新访问页面,发现问题已经得到解决。
检查腾讯云的监控系统,也可以看到内存已经逐渐恢复到正常的使用区间,而刚才出现问题时,内容使用量在监控是1.7GB。
返回到服务器上,使用top命令,检查内存使用情况:
内存已经恢复正常,现在Swap交换内存没有使用,同时内存也有470MB,缓冲和缓存是389MB。
问题原因
问题恢复后,我通过查看Shynet监控系统发现,当时有一个用户在访问我的文章时,出现了多次请求的情况,仅在Shyenet中,就出现了127次。因此,可能这个用户的网络环境不稳定,导致在访问同一个页面时,出现重复请求的情况。
最后,问题的定位就是这个用户在访问页面时,出现重复请求的情况,导致服务器的内存不足,从而引发WordPress和Nginx的崩溃。
总结
从复盘的角度来看,主要还是当前云服务器的2GB内存不足,无法满足现有的网站访问,一旦出现类似的重新请求问题,大概率就会直接挂掉。从硬件的角度考虑,后期有条件会自己搭建服务器并提高服务器的整体配置,目前的配置已经不足以满足网站的使用。
另一点就是,当存在重复访问的情况时,可以考虑阻止异常IP,例如通过下面的检查命令,来阻止异常IP:
网络连接检查
高负载可能来自外部流量。
netstat -ant | grep ESTABLISHED | wc -l
如果连接数异常高,进一步分析来源:
netstat -anp | grep :80
阻止异常 IP:
sudo iptables -A INPUT -s <IP地址> -j DROP
配置 Nginx/Apache 速率限制:
limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
如果有类似的监控系统,可以检查到异常IP,并添加到iptables中,暂时阻止其访问。如果你也是在Docker上部署的WordPress,可能无法从netstat上查看外部流量,因为只能查看到自身的ip。
这里,我使用了一个netstat命令检查外部连接到80端口的IP,但实际上只有自己的ip。
下面是这个检查命令:
netstat -anp | grep :80 | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr
扩展知识
为什么启用Swap有帮助?
启用 Swap 的主要目的是在物理内存不足时,为系统提供额外的虚拟内存,避免因内存耗尽导致的进程被杀死(例如 OOM Killer)。但是,Swap 只是一种补救措施,性能远不如物理内存,因此需要优先排查和优化内存消耗的原因。
1、防止系统崩溃:
当内存不足时,Swap 允许系统将部分不活跃的内存页(例如后台任务或缓存)移动到硬盘,释放物理内存给活跃的进程。
2、减少 OOM 风险:
如果没有 Swap,当内存耗尽时,系统可能直接终止某些重要进程(通常由 OOM Killer 决定)。
3、优化性能:
即使性能会有所下降,启用 Swap 能暂时缓解高负载场景,提供时间进行修复。
命令解析
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
sudo sync; sudo sysctl -w vm.drop_caches=3
在前面提到两个命令,一个是持久化Swap,另一个是清除内存中的缓存命令。
1、echo ‘/swapfile none swap sw 0 0’ | sudo tee -a /etc/fstab
作用:
将一个用于启用 Swap 的配置行写入 /etc/fstab 文件中,从而让系统在每次启动时自动加载该 Swap 文件。
分解解释:
echo ‘/swapfile none swap sw 0 0’
将字符串 ‘/swapfile none swap sw 0 0’ 输出到标准输出(通常是终端)。
这是一行 fstab 文件的配置,含义如下:
/swapfile: 指定 Swap 文件的路径。
none: 文件系统类型(Swap 文件没有挂载点,因此为 none)。
swap: 指定该条目用于 Swap 分区。
sw: 挂载选项,表示启用 Swap。
0 0: 不需要备份或检查该文件。
sudo tee -a /etc/fstab
tee 将输入内容(即 echo 输出的内容)同时写入文件 /etc/fstab。
-a 选项表示追加内容(append),不会覆盖文件中的现有内容。
sudo 提供管理员权限,因为 /etc/fstab 文件通常需要特权才能修改。
结果:
修改后的 /etc/fstab 文件包含一行配置,用于在系统启动时自动加载 /swapfile 作为 Swap 空间。
2、sudo sync; sudo sysctl -w vm.drop_caches=3
作用:
用于手动释放内存中的缓存,释放结果不会影响当前运行的程序。
分解解释:
sudo sync
同步数据到磁盘。
将文件系统的所有挂起写操作(如写缓冲)立即写入硬盘,确保数据已保存到持久存储。
这是在清除缓存前的安全操作,避免因清理缓存导致数据丢失。
sudo sysctl -w vm.drop_caches=3
修改内核参数,手动清理内存中的缓存。
vm.drop_caches 是 Linux 内核的一个参数,用于释放不同类型的内存缓存:
1: 释放页面缓存(page cache)。
2: 释放目录项和 inode 缓存(dentry 和 inode cache)。
3: 同时释放页面缓存、目录项和 inode 缓存。
注意事项:
清理缓存不会影响当前运行的程序,但可能会导致程序在下一次访问数据时性能下降(因为数据需要重新加载到缓存中)。
这是一个临时操作,缓存会在需要时重新增长。
结果:
执行完后,系统的可用内存会暂时增加,因为缓存被释放掉了。这在排查内存问题或需要腾出内存时有用。