1 ポイント 投稿者 GN⁺ 2024-07-28 | 1件のコメント | WhatsAppで共有

6億5,000万個のチェックボックスをチェックする: 想定外の人気への対処

2024年6月26日、One Million Checkboxes (OMCB) のWebサイトを公開
  • 100万個のグローバルなチェックボックスを持つサイトで、チェックボックスをオンにするとすべてのユーザーに即座に反映される
  • 公開から30分で数千人のユーザーが数百万個のチェックボックスをチェックした
  • Hacker News、/r/InternetIsBeautiful、Mastodon、Twitter などから流入した
  • Washington Post と New York Times でも紹介された
  • 初日に5,000万個以上のチェックボックスがチェックされた
  • 2週間後にサイトを終了するまでに、6億5,000万個以上のチェックボックスがチェックされた

当初のアーキテクチャ

  • チェックボックスの状態は100万ビット(125KB)で保存される
  • クライアントはビットセットを使ってチェックボックスをレンダリングし、サーバーにチェック状態を通知する
  • サーバーは Redis を使ってビットを更新し、すべてのクライアントへブロードキャストする
  • nginx を通じて静的コンテンツを配信し、Flask サーバーでビットセットの状態と WebSocket 接続を処理する
  • Redis は状態保存とメッセージキューの役割を担う

スケーリングの原則

  • コスト制限: サーバーレスで拡張して破産しないよう、コストを数学的に計算した
  • 短期的な解決策を受け入れる: サイトの人気は一時的だと想定し、素早い解決策を選んだ
  • シンプルでセルフホスト可能な技術を使う: 自分でサーバーを運用し、デバッグできる技術だけを追加した
  • 楽しさを追求: お金よりも楽しさを優先した
  • グローバル性の維持: すべてのユーザーが即座に変化を見られるよう、グローバルな状態を維持した

初日: 爆発的な人気

  • 30分でサーバー負荷が急増した
  • 追加のサーバーを立ち上げて負荷を分散した
  • Redis 接続の問題を解決するため、バッチ更新を導入した
  • Digital Ocean のマネージド Redis インスタンスをアップグレードした

一晩で計画する余裕はなかった

  • ITP キャンプで顔認識 Pacman ゲームを展示するための予定があった
  • iPad を持ち込み、サーバーを立ち上げた
  • サーバー命名規則を発展させながら、8台のワーカー VM を運用した
  • Flask プロセス数を減らし、更新バッチサイズを増やして負荷を下げた

帯域幅の問題

  • Digital Ocean の帯域幅料金を考慮していなかった
  • 状態スナップショットの頻度を下げ、更新サイズを縮小した
  • tc ユーティリティを使って、1秒あたりの送信データ量を制限した

2日目: さらに成長

  • 入力バリデーションが不十分で、サイトがダウンした
  • Redis レプリカを追加して負荷を分散した
  • Flask プロセスが継続的にクラッシュしたため、自動再起動スクリプトを書いた

古い更新の問題

  • クライアントが古い更新を適用してしまい、状態が誤って表示される問題が発生した
  • タイムスタンプを追加して更新順序を保証した

Go への書き直し

  • パフォーマンスエンジニアの友人と一緒にバックエンドを Go で書き直した
  • パフォーマンスは大きく向上した
  • CloudFlare を通じて DDoS 攻撃を防御した

サイト終了

  • チェックボックスが素早くチェック解除されないと凍結されるよう変更した
  • Redis を使って凍結状態を管理した
  • 2週間後にサイトを終了した

学んだこと

  • 「本物の」バックエンドを持つサーバーを公開インターネットにデプロイしたのはこれが2回目だった
  • 短期的な解決策を選んだことは良い判断だった
  • Redis と nginx の強力さをあらためて確認した
  • 人々が匿名で相互作用できるサイトを求めていることを確認した

GN⁺ のまとめ

  • この記事は、Webサイトの想定外の人気によって発生した技術的問題と、その解決過程を扱っている
  • Redis と nginx を使ったシンプルなアーキテクチャでも、大規模トラフィックを処理できることを示している
  • 短期的な解決策によって素早く問題を解決し、サイトを安定化させる方法を説明している
  • Go への書き直しや CloudFlare による DDoS 防御など、さまざまな技術的課題を扱っている
  • 類似の機能を持つプロジェクトとしては、Reddit の /r/Place のような大規模コラボレーション型プロジェクトがある

1件のコメント

 
GN⁺ 2024-07-28
Hacker Newsのコメント
  • 多くの教訓と歴史的知見を学べた

    • あらゆる種類の中断や障害ポイントを扱っていたが、ストレージの問題には触れられていない
    • RedisでLuaが使えることを知らなかったので、これを代替状態として使うことに興味が湧いた
    • クラウドサービスの帯域幅の問題は、課金超過を避けるためのハードリミットがない点で最大級の不満の1つだ
  • 素晴らしい記事だった!サイトの完成もおめでたいが、記事そのものこそ最も誇るべき部分だ

  • 2日でサイトを構築したのは良い判断だった

    • キャリア初期のエンジニアが学ぶべき重要な教訓だ
    • スケーリングの問題は、実際に問題になるまでは問題ではない
    • そしてその時点では良い問題であり、思ったより解決は難しくない
  • 最近の関連プロジェクト:

    • "One Million Checkboxes" - リンク - 2024年6月(コメント305件)
  • 面白いプロジェクトだ

    • 6年前にAndroidでPixmapという共同ピクセル編集アプリを公開した
    • キューを使って各イベントをPNG画像に適用し、クライアントは接続時に初期PNGを読み込む
    • 各ピクセル描画イベントは小さなオブジェクトとしてクライアントに送信される
    • 初期ロードでは画像圧縮を活用でき、変更セットは非常に小さい
    • 各イベントはログに保存されるので、画像を"巻き戻す"ことができる
    • デモリンク
  • 素晴らしい記事だった — どれくらいコストがかかったのか気になる

  • 人々は制限された匿名の相互作用を渇望している、という考えが裏付けられた

  • バックエンド初心者として、このプロジェクトにもっとシンプルな代替アーキテクチャがあるのか気になる

    • 100万個の状態をホスティングし、クライアントと同期するもっと簡単な方法があってほしい
    • 記事中のいくつかの解決策は理解しにくかった
    • 著者に賛辞を送りたい — プロジェクトは素晴らしい
  • すごい!

    • 次の記事はチェックボックスの統計分析になるのだろうか
    • 自分が選んだチェックボックスがほぼ即座に外されて悲しかったのを覚えている
  • ゲームがまだ稼働中なのか気になる

    • One Million Checkboxes にアクセスしたとき、何もチェックされておらず、JSコンソールには次のようなメッセージしか表示されなかった
    • {"total":0,"totalGold":0,"totalRed":0,"totalGreen":0,"totalPurple":0,"totalOrange":0,"recentlyChecked":false}