[每周一更]-(第161期):分析服务器中内存即将爆满过程

第一步CentOS中先看问题:

复制代码
total        used        free      shared  buff/cache   available
Mem:            15G         14G        508M         42M        901M        716M
Swap:            0B          0B          0B

第二步解决方案:

1、检查谁在消耗内存

使用 tophtop命令,按内存使用排序(在 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;以及容器化服务器依次开启即可(容器一般都可以自启动)
相关推荐
热爱学习的小怪兽1 小时前
docker的一些常用指令
运维·docker·容器
s***4532 小时前
Linux 下安装 Golang环境
linux·运维·golang
JobDocLS2 小时前
Ubuntu22.04的安装方法
运维
丸子哥哥3 小时前
同一个域名,如何添加多个网站?
服务器·前端·nginx·微服务
豆豆的java之旅3 小时前
深入浅出Activity工作流:从理论到实践,让业务流转自动化
java·运维·自动化·activity·工作流
4***17543 小时前
Linux 下安装 Golang环境
linux·运维·golang
Lenyiin4 小时前
《 Linux 修炼全景指南: 七 》 指尖下的利刃:深入理解 Vim 的高效世界
linux·运维·服务器·vim·lenyiin
sulikey6 小时前
Linux基础指令与权限管理深度解析:从入门到精通
linux·运维·服务器·ubuntu·centos·linux命令·linux权限
qq_2153978976 小时前
docker 安装 opengauss 高斯数据库
运维·docker·容器