スケーラビリティとユーザービリティの話
2008.09.24
先日のPhotoShareのスケーラビリティのエントリーに関しては、さまざまなご意見をいただき、とても良い勉強になっている。ただし、少し分かりにくかった部分があると思うのでそこに関して補足しておく。
サーバーのスケーラビリティに関してはすでに色々なところに書かれているが、今回の私が注目しているのは、どうやってサーバーのキャパシティを増やすか、という話ではなく、サーバーのキャパシティを超えたトラフィックが来てしまった際にどんな挙動をするように設計しておくのが良いか、という話である。
限られた資源を使って数万人・数十万人の人たちにサービスを提供するかぎり、予想外の急激なトラフィック増加でサーバーに過負荷がかかったりすることはどうしてもあるわけで、そこで問題となるのは、その手の過負荷をどうさばくか。
たとえば写真に付いたコメントを表示させる場合、「最新の情報をすぐに」表示するのが良いのが当たり前だが、それが過負荷のためにどうしても不可能になった場合に、
・表示するまで15秒かかる
・表示はすぐにするが、それは15秒前の状態(投稿されたコメントが反映されるまで15秒かかる)
のどちらがユーザーから見てストレスが少ないか、どちらの状況になるように設計しておくべきか、という部分が私は重要だと考えている。
また、通常ピーク時に3秒で処理出来ているところに、通常の倍のトラフィックが来てしまった時に、それを倍の6秒で処理出来るように作ってあるか、倍以上の9秒かかってしまうように設計してあるか、というのが「リニアにスケールするかどうか」という部分である。HTTP Requestに対するレスポンスが遅くなると、それに応じて同時アクセス数が増えてしまい、ペンディング中のスレッドが増えてしまう、そのためにさらにレスポンスタイムが遅くなる、という悪循環は、マルチスレッド型のHTTPを使ったアーキテクチャの根本的な弱点。安易にマルチスレッドに頼ったプログラミングは良くない理由はこの辺りにもある。
そしてもちろん、もっとも大切なのは、トラフィックがキャパシティを超えて来てしまった時に、サーバーが落ちてしまうのか、単に処理速度がそれに応じて遅くなるだけなのか、という点。
これらの点を考慮した上で、PhotoShareのようなCGMサービスの場合、「トラフィックがキャパシティを超えて増えてしまうとレスポンスが幾何級数的に遅くなり、しまいにはサーバーが落ちてしまう」という同期型のアーキテクチャではなく、「トラフィックがキャパシティを超えて増えてしまっても、レスポンス時間は常に一定で、単にユーザーの変更がサーバーに反映される時間がリニアに遅くなるだけで、サーバーが落ちることもない」という非同期型のアーキテクチャの方が適しているのではないか、というのが今回の話である。
ユーザに制御戻しちゃうとリロードによる輻輳から結局アクセス増加してえらいことになったりもします。結局の所どこまでを想定して設計するかで、その想定を超えても動き続けるシステムというのは無いのではないでしょうか。
蛇足ですが…。HTTPサーバ、ちゃんとしたのだとListen用とExeceute用でスレッドプールを分けた実装が多いと思います。
異常系の想定・設計が大事というのは同意ですが、スレッドを絡めてする話なのかなぁとちょっと疑問が(w
Posted by: ryu | 2008.09.24 at 18:05
スレッドを絡める話ではないですよね。マルチスレッドでなくても、待ち行列によって応答時間が遅くなっていく現象は発生しますし。
とは言え、WEB素行調査のようにユーザからのリクエストを処理する待ち時間を「ただ今、依頼の急増により、探偵が全員出払っております!ただ今のご依頼は22分後に調査完了する予定です。大変お手数ですが、このURLに再度、22分後にアクセスくださいませ。」のように見せて楽しませるのも、ユーザビリティの1つなのかも。
参考:http://detective.kayac.com/
Posted by: Ibushi | 2008.09.24 at 18:25
データ鮮度のリアルタイム性要求が絶対ではなく、かつ不特定多数からのアクセスを受け付けるサービスでは、同期型より非同期型が向いていることには激しく同意です。
ただ、サーバの能力一定の前提下で処理要求がどれだけ来るか分からない以上、いずれはレスポンス悪化の上限が来るか、サーバOSが不安定になるか、どちらかに行き着くでしょう。
一定以上の混雑が発生したら、処理要求を堰き止める流入制御でシステムを守るしかなく、その場合、時間をおいた再試行をどれだけスマートにお伝えできるかとか、ユーザレベルによって優先割り込みをかけるとか、とりあえず要求だけは全て受け付けて処理完了をメールで伝えるとか、そんな試みが必要ではないでしょうか。
Posted by: Coolmoment | 2008.09.24 at 22:05
クライアント側でサーバのヘルスチェックして、
キャッシュを優先させるか、画像を取りにいくか
判断させればいいんでないかと・・・
(HTTPレスポンスにサーバヘルス状態をヘッダに仕込む)
例えば「3秒後に取りに行く」とかで随分状況は変わります
DB書き込みの方が厳しくなるんで、シーケンシャル書き込み
で圧倒的早さを追求。DB断片化には書き込みの少ない時間帯にデフラグ。MySQLでさえ遅いので自分で作る
Posted by: BlueNote | 2008.09.24 at 22:17
問題は「スタックする場所」なので、「人間」に待って
もらう為に「猫メソッド」がもっとも有効です。
⇒かわいい動物系の画像をランダムで表示するだけの
サーバを用意しておき、そっちにトラフィックを流し
つつ、一時的な過負荷状態を処理させ凌ぐ。
(人気画像とかでもいいですね)
経済は心理学です。
Posted by: BlueNote | 2008.09.24 at 22:36
私はユーザー目線しか言えないですけど、リアルタイム性は全く必要ないですよねー。ほんとに重要ならメールで送るし。
送った後10分後位にあがってればそれで全く問題ないです。
Posted by: Hiro-p | 2008.09.24 at 22:40
レストランで言うと、
料理人とウエイトレスが
どう、対応するかという
スタンスの問題じゃないでしょうか?
リアルタイム性を要求する人、場面
例外的にありそうです。
しかも、多人数。
アップして、すぐ、電話して、
「いま、アップしたから、見てよ」という人。
年配に多いです。
iPhoneだから、即効で、電話できちゃうし。
Posted by: higekuma3 | 2008.09.25 at 04:25
「CRUDのうちR(Read)以外は全部キューイングする」のを検討することになるかと思うのですが・・・。
具体的に検討可能なモジュールというと、AP4R、Q4M、Gearmanあたりでしょうか。検証されるようでしたらぜひ結果を公開していただきたく。
Posted by: kawaguti | 2008.09.25 at 04:43
このエントリーを読んで、ようやく理解できた気がします。
この考えなら負荷でDBが落ちることはないだろうし、
サービスダウン回避を最優先事項と考えたら、
こういう設計がいいかもしれませんね。
あとは、アクセス量に応じてDB更新プロセスが
並列で動作したりするようになってれば、
負荷の多いときは細々と、小さい時はレスボンスよく、
なんてことも可能になるかも?と思いました。
見当違いならスミマセン(^^;;
Posted by: moto_maka | 2008.09.25 at 16:59
糸井
そうです。つまり、宮本さんによれば、
「アイデアというのは
複数の問題を一気に解決するものである」
岩田
「多かったら少なくしよう」
「足りなかったら増やそう」というふうに、
いま起こってる事象をそのまま
しらみつぶしに解決していくのは、
誰でもできることだし、工夫もいらない。
たとえば、ある料理店で、お客さんが
出てきた料理について「多い」と言ってる。
そのときに、「多い」と言ってる人は、
なぜ「多い」と言ってるのか。
その根っこにあるものは、
じつは「多い」ことが問題じゃなくて、
「まずい」ことが問題だったりするんです。
Posted by: You'll stealing from as? | 2008.09.27 at 02:31
まじめにやって解決できる(できそう)ならばそれをしたらいいのですが
待ち時間をまったく別のことで楽しませて待たせるという対応もあります。
レストランが空いてなければウェイティングバーで待ってもらえばいいのです。
Posted by: just a reader | 2008.09.27 at 04:33
最近更新が少ないですね。
Posted by: Halion | 2008.09.29 at 09:07