おまえにオートスケールは必要ない
タイトルはYou Don't Need Next.jsより拝借しました。すてきな資料なのでぜひご覧ください。
円安で苦しむ中、いろんな情報を見たり話したりして、オートスケールと呼ばれるものは案外いらないんじゃないかという話を書きます。
前提:
現在コンテナベースのFaaS/PaaSで運用している、あまり大規模ではないWebサービス。
そもそもここでいうオートスケールとは
数秒~数分オーダーでクラウドのリソースを増減させてトラフィックやリソース使用に応じたぶんだけ立ち上げることにより効率的なコンピューティングリソースを使うことができます。
また、あなたが旅行中や寝ている間など数時間以上PCに触ることができなくても負荷をいい感じでいなしてくれるので問題なく過ごすことができる魔法の技術です。
が、そもそもそんなのいらないんじゃないの?という話です。ただし全くいらないのではなく、数時間~1営業日程度でスケールするならいいんじゃない?という話になります。
オートスケールの壁1 データベースにRDBMSを使っている
MySQLとかPostgreSQLを使っていて、ギリギリのスペックで運用している場合、コンテナやFaaSを活用してもDBがボトルネックでスケールしません。
Firestoreなどマネージドでスケールするものだったら別ですが、事前に容量やスペックを決めてプロビジョニングするものがあるとき、そこがボトルネックになりコンピューティングを増やしても解決することはありません。
オートスケールの壁2 お財布がオートスケールしない
たとえDBが増強できたあるいはオートスケールだったとしましょう。しかしあなたのお財布(予算)は自動でスケールしません。アクセス数に応じて広告料などがリニアに追従する場合を除き、いきなりクラウド費用が3倍になったら困る人が大半だと思います。
先日Vercel高すぎ問題がバズりましたね。
とくにNext.jsをはじめとするSSRのようなBFF費用は結構バカにならないんじゃないかと思います。
オートスケールじゃなく管理してスケールさせよう
それで、これらの影響を考えるに、もっと合理的なプランが僕たちにはあるんじゃないかと思います。手動スケールアップや、ちゃんとコードを書いてモニタリングトリガーで自分たちで管理して台数をスケールさせるやり方です。古き良き、とも言えますね。
そもそもReadトラフィックはCDNでキャッシュしよう
昔と違ってだれでも無料からCDNを導入できるいま、テレビを見たとかの突発的なアクセス増はCDNがあれば十分さばけます。ログインが必要なコンテンツであったとしても、急にアクセスに着たユーザの大半は見るだけで離脱していきます。そういうRead系のトラフィックをキャッシュしてもらえればWriteのトラフィックの増加は緩やかになるんじゃないでしょうか。
1アクセス事にDBに書き込むような仕組みはやめよう
RDBMSでセッションをDBストレージにしているとか、アクセスカウンターをDBに書き込んでいるとか、そういうRDBMSが死にやすいアーキテクチャをやめるだけで、突発的な負荷の悩みから解放されます。セッションストレージはRedisをたてる、JWTですませる。
アクセス解析はサーバを分けて最悪死んでもいいようにするか、そこだけDBまで含めてサーバレスでスケールさせましょう。
ドクセルでもアクセス解析だけはアクセス数の増減がでかい(時間帯により30倍くらい)ので、Cloudfunction→Pubsub→BigQueryという構成をとっていますが、本体のCloudrunのインスタンス数はせいぜい早朝とピーク時間帯でも2,3台の差となります。1024MBの小さなインスタンスで2,3台の差であれば最初から8~16GBくらいのマシンを固定したほうが安定する可能性もあります。
AWSにおけるFargateではなくEC2運用を選んだNewsPicksのスライドが参考になります。
Vercelもそうですが、マネージドサービスはCPUなどのスペック単価が仮想マシンそのまま使う場合と計算方式が異なる可能性があるので、注意が必要です。
では管理してスケールさせるとは?
身もふたもないですが、以下のような方法です。
パフォーマンス管理ツールを入れよう
そりゃそうだよね。負荷が上がってるか便利に知れたほうがいいですから。最近Cloudflareに買収されて無料になったBaselimeほか、Sentry, Datadog, NewRelicなどスモールスタートできるツールはたくさんあります。
負荷が上がったらSlackに通知するようにしましょう。負荷が上がる前にDBのスロークエリとかのボトルネックを解消しておきましょう。
手動でポチポチスケールアップしよう
トラフィックが少ない小規模サービスはこれで充分です。クラウドの管理画面をブラウザで開いて、負荷が高まっている4GBとか8GBのインスタンスを16GBにあげるなど、1,2段階上のサイズにしておけばだいたい解決します。一晩たって落ち着いたらまた下げましょう。
これができるためには無停止でスケールアップ・ダウンできるサービスなのか事前に確認しておきましょう。
CDNレイヤーのロードバランサもあるよ
FaaSをやめて固定インスタンスにする場合、自前でインスタンス群のスケールアウトの管理が必要になります。つまり同じドメインでアクセスしたときにインスタンスを振り分けるロードバランサーを活用するということですね。
サーバが属するクラウド自身が用意しているロードバランサーでも構いませんが、CDNのロードバランサーを利用することも出来ます。
CloudflareのCDNは、月額$5~でロードバランシングを提供してくれます。これを利用してマルチクラウド構成をすることも可能ですし、1台切り離してスケールアップさせてから再参加させるなど柔軟な運用ができます。Fastlyほか様々なCDNベンダーが対応しているので、お使いのクラウドのロードバランサーがいま一つ使いづらい場合はぜひ検討してみてください。
ルールベースでコードを書いてインスタンスを増やそう
先のあんどうさんのスライドにもありますが、Push通知を送るとき、お昼時などアクセスが集中する時間帯、負荷が高まった時などだけ増やすというコードを書くとよいでしょう。
これをするためには、手動でデプロイするのではなく、各クラウドが用意しているSDKを使って、デプロイする仕組みを作る必要があります。また、仮想マシンに関してもインスタンスグループといったダウンしたら既定の台数まで既定の設定で立ち上げるといった仕組みも昔からあるので活用できそうですね。
新規サービスはFaaS/PaaSを活用しよう
と、ここまで書きましたが、ドラスティックにユーザ数や機能が変わるし、キャッシュの制御などパフォーマンスチューニングに時間を割くくらいならどんどん開発したい!というフェーズのプロダクトはFaaS/PaaSを活用しましょう。
アクセスがなかったら0円枠で運用できるものも多いですしね!ただし0円運用にこだわりすぎると、先日のPlanetScaleが無料プランを廃止したときのように大変な目に合うので気をつけましょう。
1年くらい運用して、だいたいのアクセスパターンが落ち着いてきたり成長角度がわかってきたら、こういう構成も検討してもいいんじゃないでしょうか。