- 月間2億訪問者規模の上位1000位圏内のWebサイトでも、HTMLだけを見ると約30TB/月、平均11MB/秒の転送量であり、単一サーバーで対応できる規模
- 計算はBusiness Insiderを基準に、訪問者あたり2ページ、月間4億HTML文書、圧縮HTML約75KBとし、JS・CSS・画像はCDNに任せる前提から出発している
- エッジ実行にはユーザーに近いサーバーという利点があるが、レンダリング中にデータベース往復が発生すると、レイテンシは元のDBの場所に引き戻される
- コスト差も大きい:Hetznerは16コア・64GB RAM・NVMeサーバーを**$0.34/時間**、20TBの無料転送後は$1.5/TBで提供するが、AWSとVercelは帯域単価がはるかに高い
- 特にクラウドが必要な作業でなければ、単一サーバー+SQLite+Litestream+CDN構成のほうが単純で安価であり、不要な水平スケーリングを避けられる
11MB/秒から見る上位Webサイトの実際の規模
- 上位1000位圏内のWebサイト例としてBusiness Insiderを使用
- SimilarWeb基準で世界587位、月間訪問者は約2億人
- 訪問者あたり平均2ページを見ると、月間4億件のHTML文書を提供する必要がある
- サンプル記事基準で標準HTML文書は圧縮後に約75KB
- これを掛け合わせると、HTMLだけで約30TB/月の帯域幅が必要
- 30TB/月は平均に換算すると約11MB/秒
- Business Insiderのケースでは約150 requests/sec程度
- HTMLにCDNを使わないという前提であり、JS・CSS・画像はCDNで提供できる
- 圧縮HTML 75KBは大きめなので、実装によってHTMLサイズを減らしたりリクエスト数を増やしたりする調整も可能
- 現代のハードウェアでは、アプリケーションコードが11MB/秒のHTMLを生成することは低いハードル
- 最新のAMDサーバープロセッサは64コア・128スレッドを提供する
- Zen 5 Turinサーバープロセッサは192コアと噂されており、デュアルソケットサーバーでは400コア近い構成と768スレッドまで言及されている
- この観点では、Docker、サーバーレス、水平スケーリングが常に必要な選択肢とは限らない
エッジ実行が常にレイテンシを減らすわけではない
- 地球の反対側との往復レイテンシの物理的下限は、光速基準で約200ms
- 実際には地球の反対側にある良好なデータセンターまで、おおむね300msかかることが多い
- JS・CSS・メディアをCDNで提供するなら、初期レンダリングでサーバー処理時間を300ms削減することだけでも、サーバーをユーザーの近くへ移すのと似た効果になる
- 第2世代のサーバーレス技術は、かつてコールドブートが300msのレイテンシ予算を簡単に食いつぶしていた問題を大きく減らしたが、データベース往復は依然として残っている
- ページレンダリングにデータベースクエリが1つでも必要なら、エッジサーバーは元のデータベースがあるus-east-1のような場所へ再び往復しなければならない
- レイテンシがユーザー-オリジンサーバー間から、エッジサーバー-オリジンサーバー間へ移る
- 複雑なページでは、レンダリングに5個以上のデータベースクエリが必要な場合が多い
- 多くのWebフレームワークは単一スレッド方式でクエリを逐次実行するため、データセンター間の往復が複数回発生すると、一度オリジンへ行くより遅くなることがある
- データセンター間通信はデータセンター内通信より10倍遅く、データセンター内通信は同じ装置内通信より10倍遅い、という経験則がある
- この文脈で、ローカルのSQLiteがレイテンシ削減に有利な選択肢として浮上する
Hetzner、AWS、Vercelのコスト差
- Hetznerの16コアサーバーは64GB RAMとNVMeドライブを含めて**$0.34/時間**
- 類似のx86サーバーとして比較されたAWS EC2 m5a.4xlargeは**$0.68/時間**
- 帯域幅の価格差はさらに大きい
- Hetznerは20TBの転送量を無料で提供し、その後は**$1.5/TB**を課金する
- AWSは100GBを無料で提供し、その後は**$90/TB**を課金する
- Vercelは最初の1TB無料の後に**$200/TB**を課金する例として言及されている
- クラウドベンダーの無料枠は初期参入を容易にするが、規模が大きくなると高いコストとして返ってくる可能性がある
単一サーバー構成でシンプルに運用する
- 動画トランスコーディング、独自AIモデルの実行、システムに実際に大きな負荷をかける作業のような特定のクラウド利用例がなければ、WebサイトやSaaSは単一サーバーで実行可能
- バージニアにサーバーを置けば、英語圏ユーザーに100ms未満のレイテンシを提供できる
- 推奨構成は、サーバー1台を中心にシンプルにまとめる
- データベースは同じマシンのSQLiteを使う
- LitestreamでSQLiteを継続的にバックアップする
- CSS、JS、画像はCDNでキャッシュする
- SQLiteに近い場所でサーバーレンダリングし、往復を減らして性能を高める
- デプロイも複雑にする必要はない
- CIがコードをサーバーへSCPすればよい
- NGINXは無停止デプロイをサポートする
- Dockerと仮想化は、コード実行とCI/CDを遅くする要素として扱われている
水平スケーリングが必要な場合と不要な場合
- 水平スケーリングが必要だという話は、ほとんどの場合誇張されている
- サーバー性能はインターネットの成長よりも速く向上している、という前提がある
- レイテンシが本当に重要なら、ドイツとカリフォルニアにサーバーを追加する構成が可能
- 書き込みはprimaryへルーティングする
- 読み取りはローカルのread replicaを使う
- このような構成は十分にスケール可能で、管理の複雑さが低く、コストもかなり安い
- 11MB/秒規模のHTML提供を、不必要に難しくする必要はない
1件のコメント
Hacker Newsの意見
昔やっていた小さなホスティング事業は、まさにこの点で浮き沈みを経験したが、当時は何が起きているのか分かっていなかった
2000年代初頭に成長していた頃、大きな売上の多くは複雑なスタックから生まれており、冗長化されたロードバランサーやファイアウォールのように、顧客にとって実際には必要以上の構成も多かったが、顧客はそれを望んでいた
フェイルオーバーは、意図した形でサーバーが落ちたときに得られる利点よりも、運用の複雑さのコストの方が大きいことがしばしばあり、AWSに対抗してAPIベースのクラウドホスティングプラットフォームも作ったが、売上は2012年にピークを迎えた
顧客はAWSを一部または全部使う、より複雑なソリューションを求めていたのに対し、私たちはハードウェアが10年前よりはるかに強力になったのだから、大口顧客もより少数でシンプルなサーバーを求めるはずだと考えていた
しかしそれは賢さを売るのではなく、価格を売る仕事だったし、そのような転換に必要な財務的野心を理解していなかった。安い単一サーバーは誰にも信用されず、2台買ってもスケーラビリティへの答えとしては不十分だった
結局、売上は持ちこたえたものの、Amazonより速くマネージドサービスのスタックとソフトウェアエコシステムを作ることはできず、新しい技術的挑戦が枯渇した後、2018年に会社を売却した
ブートストラップで育ったため、上限のないホスティング請求書は狂気じみたリスクに感じられ、製品設計もそうした考え方から出てきたものだったが、後になって皆がそのリスクを取っているのだと分かった
AWSが根付いた理由は、VCが高価な製品を可能にしたからだけではなく、彼ら特有の賢さが一世代のソフトウェア開発者に組み込まれたからでもある。ただ、いつクラウドが不要なのか、代替手段は何なのかを知る知識は、今ではかなりニッチになったように感じる
数字にはいくつか問題がある
第一に、トラフィックは均等には分散しない。記事の月間4億ページロードという数字には再帰的な80/20の法則を適用でき、そのように見ると5.8時間の間に約2億500万リクエストが集中し、秒間約9.7千リクエストになる
単一システムでも可能ではあるが、もはや些細ではなく、読み取りレプリカのない単一DBまで求めるなら特にそうだ。総トラフィックは同じでも、ピーク負荷に必要な帯域幅の上限は、楽観的に平均した11MB/sよりはるかに高くなる
第二に、一方向のエンドツーエンド遅延はストリーミングデータにしか当てはまらない。現実のコールドスタートでは、HTTP/3がなければTCP接続に3往復、TLS接続に少なくとも2往復が必要で、その後ようやくHTTPリクエストとレスポンスが行き来する
実際の人間にサービスするには、観測可能なすべてのことが1秒未満で起きなければならず、それを過ぎると、ユーザーがシステムが壊れたと判断してタブを閉じる割合が急激に増える
以前、ベッティング取引所の運営を手伝ったことがあるが、トラフィックは極端に跳ね、遅延要件は厳しく、取引量はイベント全体のごく短い区間に集中していた。リアルタイム取引では、ユーザーが操作を始めた瞬間から100ms以内に画面へ結果が表示される必要があり、ネットワーク往復遅延がイベント処理の予算を削っていた
参考: https://www.nngroup.com/articles/response-times-3-important-...
そうした負荷も大きな単一サーバー構成で処理することはできるが、その場合はもはや単純なWebサーバーではなく、組み込みWebサーバー付きのかなり強力なフロントエンドロードバランサーを作っているようなものになる
AWSは高額ではあるが、ロードバランサーとネットワークインフラには膨大なエンジニアリングが注ぎ込まれており、そのおかげで残りの人たちは、そのスタック領域全体の専門家にならずに済む
実際に世界中への到達性が必要なサービスがどれほどあるだろうか。複数言語対応まで一緒に作ったのだろうか。
米国やEU内でサービスするなら、まともな中央サーバー1台でもその地域全体に30ms以下の遅延を提供できる
本当にグローバルな要件があり、グローバルデータベースまで管理しなければならない場合でなければ、エッジは過大評価されがちだ
500 Internal Server Errorが出ているところを見ると、筆者は11MB/sを超えるトラフィックを受けているようだ。アーカイブはこちら: https://archive.is/UVpg0PR_END_OF_FILE_ERRORは初めて見た。いくつかのWebサイトではプロキシ、VPN、DNS-over-HTTPSが原因だとされているが、私の場合は当てはまらないこの記事は見方が間違っているように思う
より良いアプローチは、早すぎるスケールをしないことだ
必要な分だけ作ればよく、ほとんどの場合はCDNですら不要なコストだ。ただし、クラウドプロバイダーの過大な帯域幅税を払わないという前提ではある
性能問題が見え始めたら、そのとき対処すればいい。平凡な働き馬が突然みんなの欲しがるユニコーンになるなら、それは抱えたい問題だ
製品が良ければ、ユーザーは1時間後にもう一度試すのであって、すぐ競合に乗り換えたりはしない。スケーラビリティの問題が出たら、リソース集約的な部分だけをスケール可能なハイブリッドモデルにすればいい
それでも最初からWebスケール、数十個のマイクロサービス、その間で爆発する障害状態、最初の顧客が来る前のAWS請求書でVCの金を燃やしたいなら、好きにすればいい
物理サーバーを自前で運用するのは後の問題であって、今の問題ではない。AWSの100万ドルの請求書と大きな単一サーバーのどちらかを選ばなければならない頃には、ブログ記事を見て決めるのではなく、自分でテストを回しているはずだ
AWSを使うということは、スケープゴートも一緒に買うようなものだ。大手クラウドサービスの障害は上司や投資家に説明しやすいが、チームの人為ミスで同じ累積ダウンタイムが発生したと説明するのはずっと難しい
だとすれば、クラウドがスケープゴートだという解釈とどうかみ合うのか気になる
垂直スケールを狙うなら、なぜ SQLite なのか? 同じサーバー上でアプリと一緒にセルフホストの Postgres や Supabase を動かすことを妨げるものはなく、設定の手間が増えること以外に欠点はあまり思い浮かばない。
DB なしで進め、グローバル状態全体を大きなサーバー1台の実メモリに置き、Redis との往復なしにプロセス内オブジェクトとして保持し、ときどきメモリをディスクにスナップショットし、コンパイルされるマルチスレッド言語を使うなら、1Gbit 以上の NIC を飽和させながら1台の箱で全世界にサービスできる。
そういうアーキテクチャを使う実例があればいいのに、という気もする。
標準的なリレーショナル永続化パターンの外では機能差が大きく、Postgres のほうがよい場合もあるが、ある種のアーキテクチャパターンでは SQLite が勝ることもある。
BusinessInsider のようなコンテンツ中心のアプリケーションでは、SQLite ベースの Baked Data パターンのほうがコストとレイテンシの面で優れている可能性がある。
simonw(datasette)は、コンテンツ中心またはデータが豊富な Web サイトで SQLite を本番環境に使うためのツールや記事を数多く作っている: https://simonwillison.net/2021/Jul/28/baked-data/
SQLite はプロセス内で動き、シリアライズが不要なので納得できる。さらに、処理を直列化できるという追加の利点もあり、テスト、推論、キャッシュ層の構築がずっと簡単になる。
Unix ソケットを使わなければネットワークのオーバーヘッドもあるが、同じサーバーという前提なので補足にとどめる。実際には分離のために Postgres を別マシンに置くことは非常に一般的で、それはネットワーク DB の主要な利点の1つでもある。
必要な機能はそろっており、シンプルさと速度も優れている。SQLite はテラバイト級のデータ、複数の読み取り、リアルタイムのストリーミングバックアップを扱え、全体としてかなりバランスの取れた SQL 実装だ。
単一ボックスの垂直スケールを超えるときだけ、Postgres/MySQL を検討すると思う。
https://blog.cloudflare.com/introducing-d1
多くの人は、筆者がレイテンシ、帯域幅、コストに焦点を当てたため、可用性と信頼性を理由に現状を擁護しなければならないと感じているようだ。
私の結論は、トレードオフを前にしてクラウドの利点を否定しようというものではなく、今やどこにでもあるクラウドアーキテクチャパターンとそれに伴う依存が本当に必須なのか、という方向だ。
これ対あれという対比は代替案を紹介するための修辞的な仕掛けであり、どの解法が正しいかは用途ごとの数多くの要因に左右される。まさにそうした要因があるからこそ、エンジニアに仕事が生まれるのでもある。
ただし、筆者が提案したパターンの中でも SRE の懸念は解消できる。「サーバー1台が死んだら可用性はどうするのか?」というのは、私たちが慣れ親しんだシステムとは別のやり方で可用性を解決できるという点で、ストローマン攻撃に近く、解決策は実際に重要なものに合わせるべきだ。
倹約した予算で、1段階だけ足すことでずっと多くのものを得る方法がある。API と SQLite DBを同居させることだ。
理想的には、API はオーバーヘッドの低いバイナリシリアライズ形式と持続接続を使い、Web 配信は資金を燃やす VC 支援のエッジサービスの無料枠を活用すればよい。今のところ Cloudflare Workers はかなり寛大で、送信トラフィックも無料だ。
核心は、SQLite が単一スレッドでも膨大なクエリ毎秒を処理できる点にある。多くの処理を直列に流し込めるため推論しやすく、API 側のメモリキャッシュと無効化も単純になる。
Web サービングを分離しておけば、ハンドシェイクのエッジ性能を享受でき、静的ページでは DB を完全に迂回できる。記事は往復時間の問題を過小評価していたが、実際のアプリは思ったより多くの往復を必要とするので、この問題はかなり現実的だ。
DB 外の CPU 使用量の大半は、パース、デシリアライズ、データコピー、TLS から来るため、大きな塊を取り除けば、普及価格帯のマシンでも毎秒数万件の書き込みを簡単に得られ、読み取りはさらに速い。
それでも典型的なボトルネック、特に I/O は常にベンチマークしてみる価値がある。プロバイダーは誇張したり誤解を招いたりすることが多いので、無料枠で自分で動かしてみるべきだ。乗り換えが必要になったときに備えて、統合テストとベンチも用意しておくとよい。
結果が大きい場合はかなりよいが、PostgreSQL 自体が大きなデータセットを JSON にする過程でボトルネックにならないことを願っている。
人々はエッジに置くべきだ、ユーザーの近くに置くべきだ、レイテンシを下げるべきだと言う。
実際のところ、レイテンシはどれほど大きな問題なのだろうか。
ドイツのサーバーで運営している本の推薦プロジェクト Gnooks が例になる: https://www.gnooks.com
誰かにとって遅すぎると感じられるのか気になる。
ここ数年、このプロジェクトではユーザーから数千件の提案を受け取ったが、記憶する限りレイテンシを話題にした人はいなかった。最大のユーザー層は米国なのに、それでもそうだった。
そのため、ロジックの大半をフロントエンドに実装して、必要なデータを取得するためにバックエンドへ複数のクエリを送る最近の PWA より、レイテンシの問題をはるかに受けにくい。
それでもサイト自体は問題ない。すでに遅いサイトなら、そのとき問題になる。
欧州でそうすると、オーストラリアのユーザーが見るレイテンシの約2倍になり、最悪の体験を見積もる助けになる。
良い点は、これを信頼性高くテストして、本当に重要か確認できることだ。そうすれば具体的な答えが出る。
記事は 可用性 をまったく扱っていない。単一の箱で動くサービスには、計画停止と予期しない停止の両方が発生する。
RPO/RTO も考える必要がある。箱が壊れるとき、いや壊れた場合に、復旧にどれだけかかり、データをどれだけ失うかを見るべきだ。
ページレンダリングにデータベースクエリが1つでもあれば us-east-1 の DB に戻らなければならない、という文については、こうした選択肢もある:
https://aws.amazon.com/rds/aurora/global-database/
https://aws.amazon.com/dynamodb/global-tables/
https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Conce...
https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/...
似たようなものは他にも多く、同じことを自分で寄せ集めで作ろうとすると苦労するだろう。
10〜20年前なら同意しただろう。インターネットは新しく、サイトが落ちると人々はサイトを責め、状況はすぐに険悪になった。しかし今では、まずインターネットプロバイダーを責めるか、後で再試行する可能性の方が高い。
誰もが Google というわけでもなく、より単純なシステムはそもそも失敗する可能性も低い。バックアップを維持し、本当に心配なら DB をコールドの災害復旧サイトへレプリケートすればよい。FAANG ではない大半の企業と状況には十分だ。
データさえ失わなければ、多くの企業にとっては短い瞬断で終わる。広報がうまく、非常にまれな出来事なら、数日の停止にも耐えられるし、場合によってはデータ損失にも耐えられる。
信頼性の 9 を1つ追加するたびにコストは倍になる、という話があったが、ROI を考えるときは必ず反映すべきだ。ビジネスが実際にどれほどの信頼性を必要とするかはターゲット市場次第であり、IT のデフォルト回答である自動的な 100% は間違っていると思う。
単一サーバーまたは二重サーバーモデルは複雑性もはるかに低く、そのため LetsEncrypt のような運用チームも、世界規模のサービスをウェブスケールで動かすために、この 二重物理サーバーアーキテクチャ を選んでいる: https://letsencrypt.org/2021/01/21/next-gen-database-servers...
サーバー内 DB やすぐ隣の DB の非常に低い内部レイテンシのおかげで、ソフトウェアは DB クエリを桁違いに高速に実行し、ユーザーあたりのリソースも少なくて済み、実際のマネージド DB サービスよりもきびきびしたユーザー体験を提供できる。
複雑性はそれ自体の落とし穴を作り、これを一度も失敗したことのないウェブサービスはないと思う。AWS 自体がインシデントを起こす場合もある。
VPS がここでより悪いとは言えない。