Webサーバにnginxアプリサーバにunicornという構成でRedmineを動かしているのですが、不定期でRedmineが停止するという現象に見舞われました。調べたところRedmineが停止するというよりはunicronのプロセスが落ちてました。

unicornのログ


下記のような感じでunicornのプロセスが落ちてました。

1
E, [2017-09-20T09:21:54.254196 #158] ERROR -- : worker=0 PID:2990 timeout (61s > 60s), killing
E, [2017-09-20T09:21:54.907181 #158] ERROR -- : reaped #<Process::Status: pid 2990 SIGKILL (signal 9)> worker=0
I, [2017-09-20T09:22:00.290465 #4979]  INFO -- : worker=0 ready

ちなみに、この時サーバ自体もかなり重くなってました。

unicornのワーカープロセスは再起動してくれないらしい


下記の記事に書いてあるのですが、unicornのワーカープロセスは再起動の仕組みがないらしいです。えっ!!マジか。という気持ちになった。unicorn-worker-killerというgemで対応するのがわりとメジャーみたいです。

unicorn-worker-killerが便利だった件

unicorn-worker-killerの説明とか使い方は上記の記事が詳しいのでそちらにお任せします。

unicorn-worker-killer更新されてないんですけど…


最終更新が約2年前なので、大丈夫かな?と思ったのですがGitLabでも使われているようなので、大丈夫だと思います。

設定方法


congfig.ruに記述します。設定の詳細は前述の記事にお任せして、環境変数から設定できるようにしてみました。なぜ、環境変数から設定できるようにしたかというと、このRedmineはdockerで動かしており、設定は全てdocker-compose.ymlに集約したかったからです。

というわけで、下記のように書いてみました。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
require ::File.expand_path('../config/environment',  __FILE__)

require 'unicorn'
require 'unicorn/worker_killer'

if defined?(Unicorn)

min = (ENV['UNICORN_WOKER_KILLER_MEMORY_MIN'] || 192 ).to_i
max = (ENV['UNICORN_WOKER_KILLER_MEMORY_MAX'] || 256 ).to_i
cycle = (ENV['UNICORN_WOKER_KILLER_CHECK_CYCLE'] || 16 ).to_i

case ENV['UNICORN_WOKER_KILLER_VERBOSE']
when 1, "1"
verbose = true
else
verbose = false
end

use Unicorn::WorkerKiller::Oom, (min*(1024**2)), (max*(1024**2)), cycle, verbose
end

run RedmineApp::Application

一行目と最終行はもともとのRedmineのconfig.ruに記載してあったものです。unicornのワーカープロセスがMINとMAXの閾値の間になると(MAXを超えると必ず)再起動されます。

それぞれの環境変数に値が設定されていない場合はデフォルト値を設定するようにしました。ここに書いてる値はunicorn-worker-killerのREADMEに書いてあった値そのままなので、実運用ではもうちっとチューニングがいるかと思います。verbosetrueにするとログが出力されますが、この判定を1で行っているのはyamlbooleanが指定できなかった(これはyamlの仕様らしい)からです。

verbosetrueにしているとunicorn.rbstderr_pathに下記のような感じでログ出力されます。

1
I, [2017-09-25T11:36:47.547187 #117]  INFO -- : #<Unicorn::HttpServer:0x00560337511ce8>: worker (pid: 117) using 201035776 bytes.
I, [2017-09-25T11:37:18.229787 #117]  INFO -- : #<Unicorn::HttpServer:0x00560337511ce8>: worker (pid: 117) using 218845184 bytes.
I, [2017-09-25T11:38:14.490038 #117]  INFO -- : #<Unicorn::HttpServer:0x00560337511ce8>: worker (pid: 117) using 252358656 bytes.
W, [2017-09-25T11:38:14.490125 #117]  WARN -- : #<Unicorn::HttpServer:0x00560337511ce8>: worker (pid: 117) exceeds memory limit (252358656 bytes > 244980411 bytes)
W, [2017-09-25T11:38:14.490192 #117]  WARN -- : Unicorn::WorkerKiller send SIGQUIT (pid: 117) alive: 758 sec (trial 1)
I, [2017-09-25T11:38:14.566252 #115]  INFO -- : reaped #<Process::Status: pid 117 exit 0> worker=0
I, [2017-09-25T11:38:14.570168 #127]  INFO -- : worker=0 ready

以上です。