ボクココ

サービス開発を成功させるまでの歩み

Heroku で本番運用を続けていくために必要なこと

ども、@kimihom です。この記事は Heroku Advent Calendar 2017 の 20日目です。明日以降が豪華メンツで今から楽しみですね。

f:id:cevid_cpp:20170929233715p:plain

さて、今回は Heroku で本番運用を続けていくって方のための情報をシェアしたいと思う。自社サービスで Heroku を使い続けている事例ってのがあまり出て来ないので、積極的に開示していきたいと思う。

※ 本記事は、今年書いた Heroku に関する記事のまとめ的な立ち位置として読んでいただけたら幸いだ。

Heroku で本番運用の実績

私は Heroku で 2年間以上、本番環境でサービスを動かし続けて来た。その間、Heroku 起因でトラブルに遭ったことは1日くらいで、他は安定的に動き続けてくれた。その1日も、いつもよりレスポンスが遅くなっていた程度で、なんとかなったので助かった。

さて、私がなぜ Heroku にこだわり続けているのかというと 顧客の価値にダイレクトに影響を与えるプログラミングに集中したいからである。サーバーのミドルウェアの管理だとか、障害検知、運用の効率化などで時間をかけている暇があったら、サービス改善をしていたい。そうした裏側の運用は全てプロフェッショナルが管理するベストプラクティスな環境下で運営してもらった方が確実に効率がいいのだ。どうしても自分たちで運用しなければならないところだけに集中すれば、他サービスと差別化しつつも、他は安定的に動くプラットフォームに乗ることが可能になる。優秀なインフラエンジニアを雇いたいとも思っていないので,今後も Heroku を使い続けていく予定だ。

規模が大きくなってくると、Heroku からの請求を気にする方がいるが恐れる必要はない。むしろ人を雇って人件費を捻出し、どんどんとシステムやサービスが複雑になっていくことの方を恐れるべきだ。そしてそれらにかかる時間やお金の方がよっぽど高額になる。流行に流されながらシステムの裏側をバンバン変えていくより、サービスそのものを改善していくことの方が重要だ。

私は Heroku Private Spaces を使っていないので、リージョンは東京ではない。そんな関係で、よくあるレイテンシに関して聞かれることがある。しかし、実際のところレイテンシ起因でお客様から問い合わせが来たことは一度もない。爆速なサイトで話題の dev.to が Heroku / Rails 構成でできていることを知っている方も多いことだろう。"Heroku のレイテンシが〜" と言う人は、自分のサイトが遅いことの言い訳の1つとして Heroku のレイテンシを取り上げているに過ぎないことを覚えておいてほしい。同じようなことを取り上げてくれている Advent Calendar の記事があるので、こちらも紹介しておこう。

Herokuって本当に遅いんですか?

Heroku で本番運用を続けていくことは問題がなくて、むしろメリットの方が多い。

現在の構成

現在の構成を伝えるのにHeroku Elements の内容を記すのが最も手軽なので、まずはバッと挙げる。

  • Heroku Standard 1x (min: web x 2, max: web x 5)
  • Heroku Postgres Premium 0 $200
  • Heroku Redis Premium 0 $15
  • Fastly Quick $25.0
  • Papertrail Ludvig $15
  • Process Scheduler Pet Project
  • Scout Chair Lift
  • SendGrid Starter

自分のサービスはピーク帯がユーザーが仕事している時間と決まっているので、ピーク帯を簡単に予想することができる。そのため、オートスケールの仕組みを利用せず、Process Scheduler でスケジュールを立てて Dyno 数を上げるようにしている。上げる基準は 定期的に Heroku メトリクスを見て、タイムアウトが発生している頻度やアクセス数、平均レスポンスタイムを考慮した上で決定している。もちろん、サービス自体をもっと早く効率化していくことも大事だけども、それでも Heroku で解決できる部分はお金を払って安心を得るようにしている。

Worker Dyno を一切使ってないってのは一つの特徴かもしれない。負荷のかかる処理は Heroku Scheduler か、AWS Lambda 側で処理するかのどちらかで対応している。バックグラウンドジョブってのは割とプロセス周りでトラブルになって苦戦することが多く、使わなくていいのであれば使わないで良いに越したことはない。そのためにもできる限り負荷をかけさせないようなサービス設計を Biz な方と調整していくことも求められる。

CDN の Fastly を使い始めたのは実は最近の話だ。今までは Asset Sync を使って S3 に直接リソースを上げて参照するようにしていたけど、非推奨になったことから Faslty へ移ってきた。てな訳で Faslty は純粋に自分のアプリの JavaScript/CSS/Image をキャッシュするためだけに使っている。その場合は $25 のプランで余裕で賄えるので、お得に速くそして Heroku に負荷をかけることもなくなるので便利だ。

www.bokukoko.info

他は特別にやっているようなことは特にない至って標準的な構成だ。しかし、それで良いのだ!私が本当にしなければならないのは、Heroku に時間を使うことではなく、サービスそのものを改善していくことなのだ。これで変に Heroku で尖ったことをする方が間違っているかもしれないと考えた方がいいだろう。

合計すると毎月 $400 ほどの出費となる。Standard 1x で 5 Dyno を使う規模のサービスを1人で運営しているにも関わらず、サービスの本質の部分の開発に集中できるようになっている。

運用上のテクニック

特に重要な2つの運用テクニックについてご紹介する。

Heroku メトリクスの見方

Heroku メトリクスはサービスを安定稼働させるために常にチェックしておかないといけない項目だ。でも、最初にパッと色々なメトリクスを見させられて、何に注目すれば良いのかわからないことが多いかと思う。私も最初はそうだったけど、実際にメトリクスとサービス側の関連を運用で経験していくことで、なんとなくわかったことベースにお伝えしたいと思う。

基本的に、それぞれのメトリクス項目の関連を見ながら分析していくことをお勧めする。私が遭遇した以下の2パターンを例にイメージしていただければ幸いだ。

Case1. H27 が頻発する H27 とは、Heroku のエラーコードの一つで、クライアントサイド側でリクエストを途中で中断した際に発生するアラートだ。例えば SPA の JavaScript でアプリを開発している場合、リクエストを送る際にタイムアウトをかけることが多い。指定秒立ってもレスポンスが返ってこなかった場合には、「サーバーが混みあってます。しばらくしてから再度お試しください」的なメッセージを出すケースがあることだろう。

f:id:cevid_cpp:20171217134327p:plain

この場合、Heroku メトリクスの何を見るべきかというと、Events と Throughput だ。Throughput が高くなった時だけ、この H27 が頻発する場合には、基本的に1つのサーバー で処理できる能力を超えていることを表す。そのため、この場合には Dyno を増やすことで対応ができることだろう。Throughput 関係なしに H27 が頻発する場合には、ソースコード側を疑う必要がある。ここで NewRelic 等のメトリクス詳細が見られるアドオンが役に立つ。ソースコードレベルでどのアクションでどのくらいレスポンス速度を返しているのか一瞬で把握することが可能だ。地道にどうやって効率的な処理にできないか、エンジニアの腕の見せ所として頑張ってほしい。

フロントエンド側でタイムアウトの仕組みを導入していない場合には、レスポンスタイムがその分 Throughput と連動して大きくなっているはずなので、その関連を見るようにしていきたい。

Case2. Memory Usage が急上昇することがある

Memory Usage は Heroku Metrics の中でも特に注視すべき項目だ。メモリが 100% を超えた時点で、極端にレスポンス速度が遅くなる(スワッピング R14)が発生してしまう。これをできるだけ防ぐことが運用で求められる。

んで Memory Usage が 100% を超える場合ってのは大抵何かしらのタイミングで急上昇したことが原因で起きる。その処理が一体なんなのか、これまた NewRelic や Scout 等で確認する必要が出てくるだろう。問題のコードはバックグラウンドジョブに移すなり、AWS Lambda 側に任せるなり、Scheduler で定期ジョブ化するなりで対応していこう。

www.bokukoko.info

サーバー再起動した時点で、既に80%を超えているような場合も注意が必要だ。そもそも起動時にメモリを使いすぎているパターンなので、ソースコードを改善するなり、Dyno のプランを上げるなりして対応しなければならない。 Heroku は1日1回勝手に再起動するので、その再起動の範囲で100%を超えない(理想は最高でも80%)くらいをキープできるようなメモリ利用を目指すと良いだろう。

Papertrail の活用

Papertrail は単にログを見れるツールってだけだと勘違いしてはいけない。アラート機能を活用することで、サービス運営の大切なイベントをキャッチして好きなアクションを実行することができる。

例えば会員登録や退会等のサービス内の重要なアクションがあった際にすぐに Slack へ通知するようにしよう。そうすれば、顧客に対して迅速なサポートを提供することが可能になる。ユーザー登録があった時点で、CRM に自動で登録されるようにしよう。そうすれば顧客の行動履歴を全て CRM 側で管理できるようになる。様々な分析も CRM 側で自由自在だ。こうしたように、ログから新しい顧客インサイトを取得するって意味で Papertrail は必ず活用すべきだと考えている。運用の改善を地道にやっておくと、2,3年後、確実にその情報は財産となる。

以下は Papertrail 顧客登録イベント -> API Gateway -> Lambda -> CRM なフローを構築した際の例だ。

www.bokukoko.info

終わりに

今回は Heroku で本番運用を続けている私の立場から、これから Heroku で本番運用を続けるために必要なことを記した。 今後とも、Heroku でサービスを作り運営し続けられるエンジニアであり続けたいと思う。

Japan Heroku User Group | Doorkeeper

HerokuではじめるRailsプログラミング入門

HerokuではじめるRailsプログラミング入門