【エラー経緯】
ある日自動監視ツールのマカレルでEC2を監視していたところMemoryの容量が足りないというアラートが通知されました。なのでEC2に入り【ps aux --sort rss】で最もメモリーを圧迫していたものを調べました。
するとSidekiqが最も圧迫していることを確認。Sidekiqを使うメールやCSVの機能などを調べていたところSidekiqが物理メモリーを使用後、不要になったものが解放されておらず、Memoryを圧迫していることがわかりました。
以下から解決策と手順を記載していきます。
【一時的な解決策】
Sidekiq物理メモリは一度Sidekiqを再起動をすれば物理メモリが解放されます。
再起動を行う前に自信のサイトのURLの語尾に【/sidekiq/busy】とつけてSidekiqのRSSの値を確認後、再起動を行えばRSSの値が下がっていることを確認できます。これで一旦アラートは消えるので解決はできます。
## Sidekiqの再起動コマンド
sudo systemctl restart sidekiq
【根本解決(sidekiq-worker-killer編)】
sidekiq-worker-killerはsidekiqプロセスのメモリ使用量上限値を設け、それを超えるとgarbage_colletion(GC)を実行し、sidekiqの物理メモリを解放することができるgemです。
1点注意点としては上記が実行されるとsidekiqが止まります。そして自動で再起動できるような設定はsidekiq-worker-killerではできません。本件の解決策については後ほど説明いたします。
〜sidekiq-worker-killer導入手順〜
● 以下をgemfileに記載してbundle installします。
gem "sidekiq-worker-killer"
● 自身のsidekiqの設定ファイルに以下を記述します。
※ 私の場合はsidekiq.rb
オプションについてはたくさんありますが、基本的なmax_rssのみ説明いたします。他のオプションについては以下の記事をご覧ください。「max_rss」はsidekiqプロセスのメモリ使用量上限値(MB)です。この値を超えると、sidekiq-worker-killerの処理が実行されます。
https://qiita.com/WisteriaWave/items/d0611bad1649165c3663
require 'sidekiq/worker_killer'
Sidekiq.configure_server do |config|
config.server_middleware do |chain|
chain.add Sidekiq::WorkerKiller, max_rss: 1000
end
end
● 導入が成功したか確認
自身のサービスにてsidekiqを使う機能を使用し、RSSが上記コードで設定した「max_rss」を超えるようにしてください。めんどうな場合は設定値を一時的に「200」とかに下げてテストするのが良いかもしれません。設定値を超えた場合はRSSが「0」となり、sidekiqが止まっていることを確認してください。確認できていれば導入成功です。
【根本解決(sidekiq自動復旧編)】
ここまででsidekiq-worker-killerの導入が成功し、使用していないメモリを解放することができました。しかし、このままではsidekiqが止まったままです。これを解決するためには何らかの監視ツールを使ってsidekiqを自動で再起動してあげる必要があります。本記事では、「Mackerel」を使用した方法を説明します。ちなみにMonitという監視ツールでもできるようです。
※ 本記事ではMackerel自体の導入方法について省略いたします。
● サーバーにプロセス監視のプラグインをインストール
まず、Mackerelでプロセスを監視するためのプラグインをサーバーにインストールします。サーバーが二つの場合は両方にインストールしてください。
yum install mackerel-check-plugins
● 設定ファイルに自動再起動のコードを記述
上記プラグインをインストールすると自動で【/etc/mackerel-agent/mackerel-agent.conf】ファイルが生成されます。vim開いてください。
vim /etc/mackerel-agent/mackerel-agent.conf
その後最下部に以下の設定コードを記述してください。
コードの意味はMackerelの環境変数である「$MACKEREL_STATUS」が「OK」でなかった場合sidekiqの再起動コマンドを実行するというものです。
1,2行目がMackerelでsidekiqが止まったことを知らせるためのコマンドでこれがあるとsidekiqが止まった場合にアラートを鳴らせます。3行目の「action」は1,2行目が実行された後に実行される内容となります。
[plugin.checks.check_sidekiq]
command = "check-procs --pattern sidekiq"
action = { command = "/usr/bin/bash -c '[ \"$MACKEREL_STATUS\" != \"OK\" ]' && sudo systemctl restart sidekiq" }
● Mackerelの設定ファイルの内容を反映させる
設定ファイルを変更した場合以下を実行しないと反映されないので注意してください。
service mackerel-agent restart
● 再起動設定のテスト
最後に同じ方法でsidekiqのRSSが設定値を超えるような操作を行い、sidekiqのメモリが解放されたのを確認後、sidekiqが再起動されていることを以下コマンドで確認し、activeになっていれば設定完了です。お疲れ様でした。
systemctl status sidekiq