ども、@kimihom です。
今回は Heroku の Dyno を時間でスケールさせる実装を自前でしたので共有する。
Heroku の Dyno
Heroku には実行環境の Dyno と呼ばれる単位で管理されている。Web Dyno はもちろん、バックグラウンドで走る Worker Dyno や heroku run console
で動く on-off Dyno など色々な種類がある。
んで、大事なのはこの Dyno の単位で Heroku へ課金額が決まるという点だ。例えば負荷のかかるピーク時は 5 Dyno, 夜間などは 2 Dyno などと変えることで、毎月かかる金額を調整することができる。
この点の実装を簡単にしてくれる Heroku Add-ons がいくつか存在する。ページ左のカテゴリより Dynos を選ぶと、その一覧を見ることができる。
大きく分けて、Dyno 管理の Add-ons は、「スケジュール」か「オートスケール」の2つに分類される。スケジュール系の Add-ons は「Process Scheduler」「FlightFormation」、オートスケール系の Add-ons は「Adapt Scale」「Rails Autoscale」がある。なお、Heroku のお高いプランを契約すると、Heroku の提供するオートスケール を利用することも可能だ。
リクエストが急激に増える時間帯を予測できない場合には、「オートスケール」系のアドオンが活躍することだろう。その反対にリクエスト数は大体予測できて、その分、時間帯によってしっかりとサーバー台数を決め打ちで起動させたければ「スケジュール」系の Add-ons が役に立つ。
基本的には上記 Add-ons を使うだけで解決するんだけど、今回は自前で実装することにしたので以下に記す。
スケジュール スケールの自前実装
今回は時間帯による「スケジュール」タイプのスケールを実装したので、それに関して記す。
Heroku の提供する API を使うことで、案外簡単に実装することが可能だ。Ruby の rake
タスクとして実装しよう。Application Formation という API を利用する。
Platform API Reference | Heroku Dev Center
# gem 'platform-api' namespace :heroku do desc 'Dyno サイズの変更' task :update_dyno_number => :environment do # $ heroku plugins:install heroku-cli-oauth # $ heroku authorizations:create -d "Platform API example token" # => HEROKU_API_TOKEN # HEROKU_API_TARGET: heroku app name heroku = PlatformAPI.connect_oauth(ENV['HEROKU_API_TOKEN']) period = { 7 => 3, 8 => 4, 9 => 5, 19 => 4, 21 => 3, 22 => 2 } dyno_size = period[DateTime.now.hour] if dyno_size heroku.formation.update(ENV['HEROKU_API_TARGET'], 'web', {quantity: dyno_size}) end end end
今の時間帯にマッチする Dyno 数が見つかれば、その Dyno 数へアップデートする、というなんとも簡単なプログラムである。実を言うと、これだけでスケールのプログラムが書けてしまう。あとは Heroku Scheduler に 1時間に1回 この処理を実行させれば完了である。
自前で書くと、例えば土日や日本の祝日の Dyno 数を調整したり、月初は増やすとかのイレギュラーパターンも簡単に実装できるってのが利点だ。そのほかに、10分に1回実行にして、何かのリクエスト数に応じて Dyno 数を動的に変えたりするといったことも不可能ではない。
Dyno 数を変える Add-ons にお金を払うくらいなら自前でやってやるという選択も悪くはないだろう。
終わりに
今回は Heroku の Dyno スケールに関して記述した。ここはお金周りの絡むシビアな部分であるので、念入りに設計して実装したいところである。
初めて Heroku の Platfrom API を触ってみたのだけど、さすがは Heroku、よくできている。他にも大量の API が提供されているので、機会があれば見てみよう。