Puma

Puma 是一个用于 Ruby 应用程序的简单、快速、多线程和高度并发的 HTTP 1.1 服务器。自 13.0 以来,它是默认的 GitLab Web 服务器,并已取代 Unicorn。从 14.0 开始,不再支持 Unicorn。

note从 13.0 开始,Puma 是默认的 Web 服务器,Unicorn 已被禁用。在 14.0 中,Unicorn 从 Linux 包中删除,只有 Puma 可用。

配置 Puma

要配置 puma:

  1. 确定合适的 Puma worker 和 thread 设置
  2. 如果您要从 Unicorn 切换,将任何自定义设置转换为 Puma
  3. 对于多节点部署,将负载均衡器配置为使用可读性检查。
  4. 重新配置极狐GitLab 使上述更改生效:

    sudo gitlab-ctl reconfigure
    

对于基于 Helm 的部署,请参阅 webservice chart 文档

关于 Puma 配置的更多详细信息,请参阅 Puma 文档

Puma Worker Killer

Puma fork worker 进程作为减少内存使用策略的一部分。

每次创建 worker 时,它都会与主进程共享内存,并且仅在对其内存页面进行更改或添加时才使用额外的内存。

因此,worker 使用的内存会随着时间的推移而增加,而 Puma Worker Killer 是恢复此内存的机制。

默认情况下:

要更改内存限制设置:

  1. 编辑 /etc/gitlab/gitlab.rb

    puma['per_worker_max_memory_mb'] = 1024
    
  2. 重新配置极狐GitLab 使更改生效:

    sudo gitlab-ctl reconfigure
    

杀死和替换 worker 会产生相关成本,包括降低运行极狐GitLab 的能力,以及重新启动 worker 所消耗的 CPU。如果 worker killer 更换 worker 太频繁,per_worker_max_memory_mb 应该设置为更高的值。

worker 数量是根据 CPU 内核计算的,因此如果 worker 频繁重启,每分钟一次或多次,具有 4-8 名 worker 的小型部署可能会遇到性能问题,这太频繁了。

如果服务器有空闲内存,则更高的值 1200 或更多将是有益的。

Worker killer 每 20 秒检查一次,可以使用 Puma 日志 /var/log/gitlab/puma/puma_stdout.log 进行监控。例如:

PumaWorkerKiller: Out of memory. 4 workers consuming total: 4871.23828125 MB
out of max: 4798.08 MB. Sending TERM to pid 26668 consuming 1001.00390625 MB.

从这个输出:

  • 计算最大内存值的公式导致 worker 在达到 per_worker_max_memory_mb 值之前被杀死。
  • 13.5 版本之前的公式,primary 的默认值是 550MB,per_worker_max_memory_mb 为每个 worker 指定 850MB。
  • 从 13.5 版本开始的值,primary:800MB,worker:1024MB。
  • worker 被杀死的阈值设置为限制的 98%:

    0.98 * ( 800 + ( worker_processes * 1024MB ) )
    
  • 在上面的日志输出中,0.98 * ( 800 + ( 4 * 1024 ) ) 返回了 max: 4798.08 MB 值。

例如,将最大值增加到 1200 会设置一个 max: 5488 MB 值。

Worker 在共享内存之上使用额外的内存,多少取决于站点对极狐GitLab 的使用。

Worker 超时

启用 Puma 时使用 60 秒超时

note与 Unicorn 不同的是,puma['worker_timeout'] 设置没有设置最大请求持续时间。

要更改 worker 超时为 600 秒:

  1. 编辑 /etc/gitlab/gitlab.rb

    gitlab_rails['env'] = {
       'GITLAB_RAILS_RACK_TIMEOUT' => 600
     }
    
  2. 重新配置极狐GitLab 使更改生效:

    sudo gitlab-ctl reconfigure
    

内存受限的环境

在可用 RAM 少于 4GB 的内存受限环境中,请考虑禁用 Puma 集群模式

通过将 workers 的数量设置为 0 来配置 Puma 可以减少数百 MB 的内存使用量。有关 Puma worker 和 thread 设置的详细信息,请参阅 Puma 要求

与默认设置的集群模式不同,只有一个 Puma 进程将为应用程序提供服务。

使用这种配置运行 Puma 的缺点是吞吐量降低,这可以被视为内存受限环境中的权衡。

在单节点模式下运行 Puma 时,不支持某些功能:

  • 分阶段重启
  • Puma Worker Killer

将 Unicorn 设置转换为 Puma

note从 13.0 开始,Puma 是默认的 Web 服务器,Unicorn 已默认禁用。在 14.0 中,Unicorn 从 Linux 包中删除,只有 Puma 可用。

Puma 具有多线程架构,比 Unicorn 等多进程应用服务器使用更少的内存。大多数 Rails 应用程序请求通常包括一部分 I/O 等待时间。

在 I/O 等待期间,MRI Ruby 将 GVL(全局 VM 锁)释放给其他线程。因此,多线程 Puma 仍然可以处理比单个进程更多的请求。

切换到 Puma 时,由于两个应用程序服务器之间的差异,任何 Unicorn 服务器配置都 不会 自动转移。

下表总结了使用 Linux 软件包时,哪些 Unicorn 配置键与 Puma 中的对应,哪些没有对应项。

Unicorn Puma
unicorn['enable'] puma['enable']
unicorn['worker_timeout'] puma['worker_timeout']
unicorn['worker_processes'] puma['worker_processes']
n/a puma['ha']
n/a puma['min_threads']
n/a puma['max_threads']
unicorn['listen'] puma['listen']
unicorn['port'] puma['port']
unicorn['socket'] puma['socket']
unicorn['pidfile'] puma['pidfile']
unicorn['tcp_nopush'] n/a
unicorn['backlog_socket'] n/a
unicorn['somaxconn'] puma['somaxconn']
n/a puma['state_path']
unicorn['log_directory'] puma['log_directory']
unicorn['worker_memory_limit_min'] n/a
unicorn['worker_memory_limit_max'] puma['per_worker_max_memory_mb']
unicorn['exporter_enabled'] puma['exporter_enabled']
unicorn['exporter_address'] puma['exporter_address']
unicorn['exporter_port'] puma['exporter_port']

Puma exporter

您可以使用 Puma exporter 来衡量各种 Puma 指标。