Rails で使われているアプリケーションサーバ、Unicorn。
Master Process から fork して Worker Process が実際の処理を行う。
Unicorn Worker Killer
一定回数以上リクエストがくるか、一定量以上のメモリを使用した場合、Worker Process を再起動する君。
設定
config/unicorn.rb
- worker_processes: Worker Process の数
- timeout: timeoutの秒数
prometheus_exporter
Metrics を取得するため、prometheus_exporter を読み込んでいる。
同僚の takeyama さんの記事
コードをみてみる。
prometheus_exporter/lib/prometheus_exporter/instrumentation/unicorn.rb
指定された frequency で pid_file から pid を取得して unicorn_collector.collect
で metrics を取得して json で返す。
collect_unicorn_stats
でとっているのは以下3つ。
- metric[:active_workers_total] = stats.active
- metric[:request_backlog_total] = stats.queued
- metric[:workers_total] = worker_process_count
worker_process_count
は直後の private method で定義されている通りで、単純に pgrep で取ってきている。
result = `pgrep -P #{pid} -f unicorn -a` result.lines.count
stats
というのがどこからくるかというと listener_address_stats
という private method からきていて、tcp であれば Raindrops::Linux.tcp_listener_stats([@listener_address])[@listener_address]
を返している。
Raindrops
はてさて Raindrops
とは何か。
raindrops is a real-time stats toolkit to show statistics for Rack HTTP servers. It is designed for preforking servers such as unicorn, but should support any Rack HTTP server on platforms supporting POSIX shared memory. It may also be used as a generic scoreboard for sharing atomic counters across multiple processes.
ほー。
というわけで
Prometheus Exporter で取れる 3つの Metrics は以下
- workers_total: 'Number of unicorn workers.',
- active_workers_total: 'Number of active unicorn workers',
- request_backlog_total: 'Number of requests waiting to be processed by a unicorn worker.'
active ってのは実際に処理をしているってことなのかな?queued は unicorn に処理されるのを待っているリクエストの数。
request_backlog_total
が高い状態が続いた場合、Timeout となってしまいそうだ。
どう解決すればいいのか
Horizontal Pod Autoscaler の Custom Metrics でいけないかな?と思ってググったけどたどり着けず。
その他の Metrics
内製の gem が送っているやつがあるようだ。
/proc/pid/stats の cpu time をもってきて、毎秒比較し、それが変化していなければ idle と判定しており、そのほかの metrics はそれに基づいて計算している。 その結果をDatadog に送るもの。
おわりに
request_backlog_total がしばしば増えていて、それによって エラーも出ているようなのでまずは Metrics の理解が大事だと思ったのでいろいろみてみた。勉強になった。さてどうしよう。