Help us learn about your current experience with the documentation. Take the survey.

减少内存使用

Sidekiq 内存杀手会自动管理那些消耗过多内存的后台作业进程。此功能会监控工作进程,并在 Linux 内存杀手介入之前重启它们,从而允许后台作业在优雅关闭前运行完成。通过记录这些事件,我们可以更轻松地识别出导致高内存使用的作业。

我们如何监控 Sidekiq 内存

GitLab 默认仅对 Linux 包或 Docker 安装监控可用的 RSS 限制。原因是 GitLab 依赖 runit 在因内存问题导致关闭后重启 Sidekiq,而自编译和 Helm chart 安装不使用 runit 或等效工具。

在默认设置下,Sidekiq 的重启频率不超过每 15 分钟一次,每次重启会给新进入的后台作业带来大约一分钟的延迟。

一些后台作业依赖于长时间运行的外部进程。为确保在 Sidekiq 重启时这些进程能够被干净地终止,每个 Sidekiq 进程都应作为进程组领导者运行(例如,使用 chpst -P)。如果使用 Linux 包安装,或在安装了 runit 的情况下使用 bin/background_jobs 脚本,系统会自动为您处理这一点。

配置限制

Sidekiq 内存限制通过环境变量进行控制

  • SIDEKIQ_MEMORY_KILLER_MAX_RSS (KB):定义了 Sidekiq 进程允许的 RSS 软限制。如果 Sidekiq 进程的 RSS(以千字节为单位)超过 SIDEKIQ_MEMORY_KILLER_MAX_RSS,并且持续时间超过 SIDEKIQ_MEMORY_KILLER_GRACE_TIME,则会触发优雅重启。如果未设置 SIDEKIQ_MEMORY_KILLER_MAX_RSS 或其值设置为 0,则不会监控软限制。SIDEKIQ_MEMORY_KILLER_MAX_RSS 默认为 2000000

  • SIDEKIQ_MEMORY_KILLER_GRACE_TIME:定义了宽限期(以秒为单位),在此期间,允许 Sidekiq 进程的 RSS 超过软限制运行。如果 Sidekiq 进程在 SIDEKIQ_MEMORY_KILLER_GRACE_TIME 时间内回落到允许的 RSS(软限制)以下,则重启操作将被中止。默认值为 900 秒(15 分钟)。

  • SIDEKIQ_MEMORY_KILLER_HARD_LIMIT_RSS (KB):定义了 Sidekiq 进程允许的 RSS 硬限制。如果 Sidekiq 进程的 RSS(以千字节为单位)超过 SIDEKIQ_MEMORY_KILLER_HARD_LIMIT_RSS,则会立即触发 Sidekiq 的优雅重启。如果未设置此值或设置为 0,则不会监控硬限制。

  • SIDEKIQ_MEMORY_KILLER_CHECK_INTERVAL:定义了检查进程 RSS 的频率。默认为 3 秒。

  • SIDEKIQ_MEMORY_KILLER_SHUTDOWN_WAIT:定义了所有 Sidekiq 作业完成所允许的最长时间。在此期间不接受新的作业。默认为 30 秒。

    如果 Sidekiq 未执行进程重启,Sidekiq 进程将在 Sidekiq 关闭超时时间(默认为 25 秒)+ 2 秒后被强制终止。如果作业在此期间未能完成,所有当前正在运行的作业将通过向 Sidekiq 进程发送 SIGTERM 信号来中断。

  • GITLAB_MEMORY_WATCHDOG_ENABLED:默认启用。将 GITLAB_MEMORY_WATCHDOG_ENABLED 设置为 false,可以禁用 Watchdog 的运行。

监控工作进程重启

如果工作进程因内存使用过高而被重启,GitLab 会发出日志事件。

以下是其中一个日志事件的示例,位于 /var/log/gitlab/gitlab-rails/sidekiq_client.log 中:

{
  "severity": "WARN",
  "time": "2023-02-04T09:45:16.173Z",
  "correlation_id": null,
  "pid": 2725,
  "worker_id": "sidekiq_1",
  "memwd_handler_class": "Gitlab::Memory::Watchdog::SidekiqHandler",
  "memwd_sleep_time_s": 3,
  "memwd_rss_bytes": 1079683247,
  "memwd_max_rss_bytes": 629145600,
  "memwd_max_strikes": 5,
  "memwd_cur_strikes": 6,
  "message": "rss memory limit exceeded",
  "running_jobs": [
    {
      jid: "83efb701c59547ee42ff7068",
      worker_class: "Ci::DeleteObjectsWorker"
    },
    {
      jid: "c3a74503dc2637f8f9445dd3",
      worker_class: "Ci::ArchiveTraceWorker"
    }
  ]
}

其中:

  • memwd_rss_bytes 是实际消耗的内存量。
  • memwd_max_rss_bytes 是通过 per_worker_max_memory_mb 设置的 RSS 限制。
  • running jobs 列出了在进程超过 RSS 限制并开始优雅重启的时刻,正在运行的作业。