# Understanding Unicorn and unicorn-worker-killer

> 原文：[https://docs.gitlab.com/ee/administration/operations/unicorn.html](https://docs.gitlab.com/ee/administration/operations/unicorn.html)

*   [Unicorn](#unicorn)
    *   [Tunable options](#tunable-options)
*   [unicorn-worker-killer](#unicorn-worker-killer)

# Understanding Unicorn and unicorn-worker-killer[](#understanding-unicorn-and-unicorn-worker-killer "Permalink")

**注意：**从 GitLab 13.0 开始，Puma 是基于 GitLab 多合一软件包的安装以及 GitLab Helm 图表部署中使用的默认 Web 服务器.

## Unicorn[](#unicorn "Permalink")

GitLab uses [Unicorn](https://yhbt.net/unicorn/), a pre-forking Ruby web server, to handle web requests (web browsers and Git HTTP clients). Unicorn is a daemon written in Ruby and C that can load and run a Ruby on Rails application; in our case the Rails application is GitLab Community Edition or GitLab Enterprise Edition.

Unicorn 具有多进程架构，可以更好地利用可用的 CPU 内核（进程可以在不同的内核上运行），并具有更强的容错能力（大多数故障仅隔离在一个进程中，无法完全关闭 GitLab）. 启动时，Unicorn 的"主"进程使用 GitLab 应用程序代码加载一个干净的 Ruby 环境，然后生成继承此干净的初始环境的"工人". "主人"从不处理任何留给工人的请求. 操作系统网络堆栈将传入的请求排队，并在工作进程之间分配它们.

在一个理想的世界中，主服务器将生成一个工人池，然后工人依次处理传入的 Web 请求，直到时间结束. 实际上，工作进程可能崩溃或超时：如果主服务器注意到工作时间过长，无法处理请求，它将以 SIGKILL（" kill -9"）终止工作进程. 无论工作进程如何结束，主进程都将再次用新的"干净"进程替换它. Unicorn 的设计宗旨是能够替换"崩溃的"工人，而无需放弃用户的要求.

这就是`unicorn_stderr.log`的 Unicorn worker 超时. 主过程具有下面的 PID 56227.

```
[2015-06-05T10:58:08.660325 #56227] ERROR -- : worker=10 PID:53009 timeout (61s > 60s), killing
[2015-06-05T10:58:08.699360 #56227] ERROR -- : reaped #<Process::Status: pid 53009 SIGKILL (signal 9)> worker=10
[2015-06-05T10:58:08.708141 #62538]  INFO -- : worker=10 spawned pid=62538
[2015-06-05T10:58:08.708824 #62538]  INFO -- : worker=10 ready 
```

### Tunable options[](#tunable-options "Permalink")

Unicorn 的主要可调选项是工作进程数和请求超时，之后 Unicorn 主服务器终止工作进程. 如果要调整这些设置，请参见[Omnibus GitLab Unicorn 设置文档](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/unicorn.html) .

## unicorn-worker-killer[](#unicorn-worker-killer "Permalink")

GitLab 内存泄漏. 这些内存泄漏在长时间运行的进程（例如 Unicorn 工作者）中表现出来. （不知道 Unicorn 主进程会泄漏内存，可能是因为它无法处理用户请求.）

为了使这些内存泄漏易于管理，GitLab 随附了[unicorn-worker-killer gem](https://github.com/kzk/unicorn-worker-killer) . 每隔 16 个请求，这只宝石[猴就会](https://en.wikipedia.org/wiki/Monkey_patch)给独角兽工人打[补丁](https://en.wikipedia.org/wiki/Monkey_patch)以进行内存自检. 如果 Unicorn worker 的内存超过预设限制，则退出 worker 进程. 然后，Unicorn 主服务器自动替换工作进程.

这是处理内存泄漏的可靠方法：Unicorn 旨在处理"崩溃"的工作程序，因此不会丢弃任何用户请求. unicorn-worker-killer gem 被设计为仅*在请求之间*终止工作进程，因此不会影响用户请求. 您可以通过设置以下值`/etc/gitlab/gitlab.rb`来设置 Unicorn worker killer 的最小和最大内存阈值（以字节为单位）：

*   对于 GitLab **12.7**及更高版本：

    ```
    unicorn['worker_memory_limit_min'] = "1024 * 1 << 20"
    unicorn['worker_memory_limit_max'] = "1280 * 1 << 20" 
    ```

*   对于 GitLab **12.6**及更高版本：

    ```
    unicorn['worker_memory_limit_min'] = "400 * 1 << 20"
    unicorn['worker_memory_limit_max'] = "650 * 1 << 20" 
    ```

否则，您可以设置`GITLAB_UNICORN_MEMORY_MIN`和`GITLAB_UNICORN_MEMORY_MAX` [环境变量](../environment_variables.html) .

这就是 Unicorn_stderr.log 中的 Unicorn 工作程序内存重新启动的样子. 您看到工作程序 4（PID 125918）正在检查自己并决定退出. 内存阈值是 254802235 字节，大约 250MB. 对于 GitLab，此阈值是 200 到 250 MB 之间的随机值. 然后，主进程（PID 117565）接收工作进程，并生成具有 PID 127549 的新"工作进程 4".

```
[2015-06-05T12:07:41.828374 #125918]  WARN -- : #<Unicorn::HttpServer:0x00000002734770>: worker (pid: 125918) exceeds memory limit (256413696 bytes > 254802235 bytes)
[2015-06-05T12:07:41.828472 #125918]  WARN -- : Unicorn::WorkerKiller send SIGQUIT (pid: 125918) alive: 23 sec (trial 1)
[2015-06-05T12:07:42.025916 #117565]  INFO -- : reaped #<Process::Status: pid 125918 exit 0> worker=4
[2015-06-05T12:07:42.034527 #127549]  INFO -- : worker=4 spawned pid=127549
[2015-06-05T12:07:42.035217 #127549]  INFO -- : worker=4 ready 
```

从 GitLab.com 上摘录的另一段日志摘要是，" worker 4"仅在 23 秒内处理请求. 对于我们当前的 GitLab.com 设置和流量，这是正常值.

在某些 GitLab 网站上，独角兽内存重新启动的频率很高，可能会使管理员感到困惑. 通常他们是[红鲱鱼](https://en.wikipedia.org/wiki/Red_herring) .