
第一步CentOS中先看问题:
total used free shared buff/cache available
Mem: 15G 14G 508M 42M 901M 716M
Swap: 0B 0B 0B
第二步解决方案:
1、检查谁在消耗内存
使用 top或 htop命令,按内存使用排序(在 top中按 Shift+M),确认占用靠前的进程,这可以帮我们锁定问题根源。
2、检查内核SLAB占用
- slabtop
- 识别 :通过
slabtop识别出占用内存最高的缓存类型。 - 分析:根据缓存类型分析其增长原因(是系统正常活动,还是特定应用行为异常)。
- 干预 :
- 优先考虑调整应用程序的行为或配置。
- 其次考虑调整内核参数 (如
vfs_cache_pressure)。 - 谨慎使用手动强制释放缓存的方法。
- 在极端情况下,重启相关服务甚至重启系统也是一种快速释放缓存的手段。
- 识别 :通过
- 发现:ext4_inode_caceh占用较高
3、快速释放内存
-
清理PageCache(不影响服务,但可能短暂影响文件读取性能)
sync; echo 1 > /proc/sys/vm/drop_caches # 仅清理页面缓存
4、启用Swap空间(临时救命)
sudo fallocate -l 4G /swapfile # 创建4G文件
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# 临时生效,重启失效
5、最后发觉可能是docker中容器占用内存过高
f70a0ea45d6c gitlab/gitlab-ce:latest "/assets/wrapper" 14 months ago Up 58 seconds (health: starting) 80/tcp, 443/tcp, 0.0.0.0:9099->9099/tcp, 0.0.0.0:8222->22/tcp gitlab-web-1
我先重启下:docker restart gitlab-web-1,毕竟我知道gitlab比较吃内存。
重启完,时发现内存是降了9.5G,随着就内存又起来,这里我发觉不对劲,排查docker在运行的容器情况。
继续排查容器占用情况:docker stats,好像gitlab也确实占内存。
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
a292763d2ab6 jms_celery 0.41% 821.9MiB / 15.51GiB 5.17% 825MB / 503MB 162GB / 16.4kB 29
96bd26d4c9f2 jms_lion 0.02% 40.88MiB / 15.51GiB 0.26% 231MB / 282MB 1.61TB / 0B 15
a336bc5de9b3 jms_koko 0.04% 23.78MiB / 15.51GiB 0.15% 3.48GB / 3.15GB 1.15TB / 0B 18
c89c31d50fc8 jms_web 0.00% 12.99MiB / 15.51GiB 0.08% 1.36GB / 3.5GB 1.24TB / 4.1kB 9
ac4c7ae9b568 jms_core 0.39% 1.429GiB / 15.51GiB 9.21% 21.9GB / 12.2GB 2.61TB / 8.19kB 45
4ad3c898712f unionid-app-1 0.00% 8.367MiB / 15.51GiB 0.05% 80.8MB / 75.1MB 37.9GB / 0B 10
9c428dda860a showdoc 0.18% 98.72MiB / 15.51GiB 0.62% 13.5MB / 126MB 936GB / 1.33MB 39
f70a0ea45d6c gitlab-web-1 50.70% 3.16GiB / 15.51GiB 20.37% 13kB / 18.3kB 3.96GB / 1.94MB 438
我先清理下docker容器可能存在的问题:
删除所有已停止的容器
docker container prune
删除所有未被任何容器引用的镜像
docker image prune
删除未被使用的卷(谨慎操作,确保卷内无重要数据):
docker volume prune
一键清理 :使用 docker system prune命令可以一次性清理所有未使用的容器、镜像、卷和网络。注意: 加上 -a参数会删除所有未被使用的镜像,包括一些中间层,请谨慎使用。
docker system prune
以上操作,但对内存影响不大,不过可以清除一些干扰:
限制内存这里我就不操作了,看容器内存占用情况还算合理:(提供下方案)
限制容器内存 :在运行容器时,使用 -m或 --memory参数来为容器设置内存使用上限,防止单个容器耗尽主机内存。
docker run -d --memory=512m --name my-container my-image
应该就是gitlab中Prometheus一直在占用内存,这里需要做下限制:
-
限制Prometheus内存使用(关键设置!),这里修改:gitlab.rb的配置
prometheus['memory_limit'] = "2048m" # 限制最大2GB内存
-
终极解决方案(如果仍不足)
# 在 gitlab.rb 中 prometheus['enable'] = false # 配置外部Prometheus gitlab_exporter['enable'] = true gitlab_exporter['listen_address'] = '0.0.0.0' gitlab_exporter['listen_port'] = 9168
6、检查内存占用情况
前20名占用情况:
ps -eo pid,user,%cpu,%mem,rss,comm --sort=-%mem | head -n 20
7、排查端口占用情况
netstat -antlp
tcp 0 0 172.18.78.108:37252 100.118.78.1:80 TIME_WAIT -
tcp 0 0 172.18.78.108:50254 47.119.219.103:3306 TIME_WAIT -
tcp 0 0 172.18.78.108:56392 47.119.219.103:3306 ESTABLISHED 4745/python3.8
tcp 0 0 172.18.78.108:48584 47.119.219.103:3306 TIME_WAIT -
tcp 0 0 172.18.78.108:49442 47.119.219.103:3306 TIME_WAIT -
tcp 0 0 172.18.78.108:48404 47.119.219.103:3306 TIME_WAIT -
tcp 0 0 172.18.78.108:50360 47.119.219.103:3306 TIME_WAIT -
- 原因 :这通常源于应用程序频繁地建立短连接。你的Python应用可能在使用数据库后没有使用连接池 ,或者设置了短时间的连接超时,导致频繁创建和断开数据库连接。HTTP服务的TIME_WAIT也是类似原因,可能是频繁请求外部HTTP接口。
- 影响 :
- 资源占用:每个TIME_WAIT连接都占用一个本地端口、少量内存和CPU资源。虽然单个连接影响小,但数量巨大时(如数万个)可能耗尽可用端口(最多65535个),导致无法建立新连接。
- 这是TCP协议保证可靠传输和防止旧连接数据包干扰新连接的正常机制,但需要优化管理。
使用命令持续监控:
# 统计各TCP状态连接数
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
# 或使用ss命令(更推荐)
ss -ant | awk 'NR>1 {++S[$1]} END {for(a in S) print a, S[a]}'
回收在文件末尾添加或修改以下参数:
# 允许将TIME-WAIT sockets重新用于新的TCP连接(对出向连接有效)
net.ipv4.tcp_tw_reuse = 1
# 修改系统默认的 FIN_WAIT_2 到 TIME_WAIT 的超时时间(单位:秒)
net.ipv4.tcp_fin_timeout = 30
# (可选) 扩大本地可用端口范围
net.ipv4.ip_local_port_range = 1024 65000
# (可选) 增加系统最大TIME_WAIT连接数容忍量
net.ipv4.tcp_max_tw_buckets = 2000000
验证配置
sysctl net.ipv4.tcp_tw_reuse
8、服务器本地有一个mysqld服务器,其实业务中都用的RDS
mysql 1731 1565 0 Jan24 ? 02:53:07 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib64/mysql/plugin --log-error=/var/log/mysqld.log --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/lib/mysql/mysql.sock
9、最后重启服务器彻底解决
- 将需要开启的物理机服务:nginx、php-fpm;以及容器化服务器依次开启即可(容器一般都可以自启动)