gitlab宕机问题、资源不足、OOM、cpu过高
侧边栏壁纸
博主昵称
yuc

  • 累计撰写 291 篇文章
  • 累计收到 0 条评论

gitlab宕机问题、资源不足、OOM、cpu过高

yuc
yuc
2024-11-25 / 最后修改: 2024-11-25 02:36 / 0 评论 / 6 阅读 / 正在检测是否收录...
现象

gitlab多次宕机,页面由nginx显示502

第一次排查

通过排查 messages 和 dmesg 再配合监控,发现存在 OOM 情况,操作系统内存、SWAP使用殆尽,其中 oom-kill 的是 puma 进程 以及 页面 502 所以合理怀疑是web宕机

解决办法:每天凌晨重启gitlab,并且修改 `/etc/gitlab/gitlab.rb` 修改 puma 单进程为集群模式,增加每个工作节点的内存

第二次排查

第二次宕机,发现内存使用率并没有达到较高的水平,且仍然有剩余内存,messsages 和 dmesg 没有任何关于 OOM 的信息,所以这次应该不是内存不足导致的宕机,但观察机器其他性能指标,发现其CPU较高,通过nginx的日志,发现在较高的时刻,以及研发反馈的时候,其日志内有大量的请求以及大量的 502 错误

继续排查,发现客户端在此时有大量的请求,大概 12 秒有 2700 个请求,并且此时其他请求非常少,说明此请求由同一个客户端发送出来

"http_user_agent":"vs-code-gitlab-workflow/5.18.1 VSCode/1.95.1 Node.js/20.18.0 (win32; x64)"

通过此 user-agent 确定是 vscode 的插件,同时发现了gitlab文档内关于puma cpu 达到 100%会出现502的问题,综合考虑猜测是vscode某插件请求量太高导致高负载异常,以下是参考文档:

https://docs.gitlab.com/17.4/ee/administration/operations/puma.html#502-gateway-timeout-after-puma-spins-at-100-cpu

发现其他用户也存在请求较大而CPU过高的问题,参考文档

https://forum.gitlab.com/t/high-cpu-usage-by-puma-workers/115315/5

解决办法: 既然确定了高并发导致 puma 过载,无法继续响应请求,所以找到了用户、并发较高的请求,以及插件:

/api/v4/projects/
/api/v4/version
/api/graphql

先判断了几个请求的类型,发现 version 是 GET 请求,并且获取的内容是 gitlab 版本信息,所以可以考虑把此请求内容缓存,减轻 puma 的部分压力,另外两个请求都是 POST,并且内容不固定,基本都是 gitlab 支持的查询请求,无法作为缓存

跟vscode用户进行了沟通,确定该插件无法通过配置来限制并发量,所以仍然只能通过服务端来解决,计划通过限流来解决,限流的思路一共有几种:

  1. 通过客户端ip+uri
  2. 通过 user-agent+uri
  3. 通过 客户端会话+uri 最后通过权衡选择了方案3,原因是客户端ip基本都是公司出口,这里难以区分,再就是 user-agent 也可能存在多数人使用插件的情况,不能几个人一访问就直接到达并发量,所以最后计划通过用户的会话来判断单个用户是否达到限流
nginx限流

nginx限流方案配置:

  1. 修改配置文件 nginx.conf
map $cookie__gitlab_session $limit_req_key {
    default default;
    "" default;
    ~.+ $cookie__gitlab_session;
}
proxy_cache_path /data/nginx/nginx_cache levels=1:2 keys_zone=cache_zone:64m max_size=100m inactive=60m;
limit_req_zone $limit_req_key zone=api_zone_v1:64m rate=15r/s;
limit_req_zone $limit_req_key zone=api_zone_v2:64m rate=15r/s;
limit_req_zone $limit_req_key zone=api_zone_test:64m rate=3r/s;
  1. 修改配置文件 gitlab.conf 其中对POST接口做了限流,对于 GET 请求的 version 做了缓存
location /api/graphql {
    limit_req zone=api_zone_v1 burst=15 nodelay;
    proxy_pass https://127.0.0.1:18092;
}
location /api/v4/projects {
    limit_req zone=api_zone_v2 burst=15 nodelay;
    proxy_pass https://127.0.0.1:18092;
}
location = /api/v4/version {
    proxy_ignore_headers Cache-Control;
    proxy_cache cache_zone;
    proxy_cache_valid 200 7d;
    proxy_cache_key "$uri";
    proxy_pass https://127.0.0.1:18092;
    expires 7d;
}

PS. 上面配置中通过 map 拿到了请求中 cookie 的其中一个变量(可以代表不同会话),以实现不同会话的限流,如果请求中没有会话字段、或者字段内容为空,那么就会设置 default 值,这些请求会归类到一个限流中,看起来是可能存在问题,如果整体的 default 的并发较高,那么很多用户会被限制,其实不是这样的,因为这两个请求都是 POST,那么对于没有会话的请求来说,它是不合法的,必须需要会话才能够请求,所以这里是无需担心的。

gitlab优化

对于 gitlab.rb 中关于 puma 的优化配置

puma['enable']
puma['worker_timeout'] = 60
# Reduce the number of running workers to the minimum in order to reduce memory usage
# 设置0关闭集群模式,实验性功能,官方还不明确推荐于生产环境 --- 20240912 目前发现设置为0只有一个进程,当内存使用过高重启会导致无法访问  https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/8477 // https://docs.gitlab.com/ee/administration/operations/puma.html
puma['worker_processes'] = 2
puma['preload_app'] = true
puma['min_threads'] = 2
puma['max_threads'] = 2
# 设置每个 worker 进程最大内存使用,如果 worker_processes 为 0,则参数失效
puma['per_worker_max_memory_mb'] = 1536 # 1GB
# 上面这个参数会直接杀死进程,有可能对请求有影响,增加 preload_app 和 max_requests 参数,使得puma工作进程能够在内存不足之前优雅重启
puma['max_requests'] = 1000
puma['port'] = 8052
puma['log_level'] = 'info'
puma['worker_log'] = '/var/log/gitlab/puma/puma_worker.log'
最终解决方案

以上方法对体验有影响、且高峰使用时间仍然不能很好解决,所以除了对GET请求做缓存外,增加了服务器的配置来彻底解决

0

评论

博主关闭了当前页面的评论