ツールド東北2018先着順エントリー@JTBスポーツステーションの問題点をウェブアプリケーションプログラマー視点で考えてみる
5月26日(土)20時からツールド東北2018一般参加者のための先着順エントリーが開始され、まさかの状態になりました。
その時のTwitterの状況は #ツールド東北 を検索しただけのまとめを作っておいたのでそちらで見ていただけます。
まさかの状態とは?
ざっくりいうと、アクセス集中によるサーバー負荷高等のため、ユーザーがエントリーをうまく進めることができない状態(=不具合がある状態)が続きました。
5月26日22時現在、参加エントリーページにアクセスしづらい状況が続いておりご迷惑をおかけし大変申し訳ありません。サイトに接続しづらい状態、一部のお客様のエントリーが完了できない状態が続いております。大変恐れ入りますが、しばらく時間をおいてアクセスいただきますようお願い申し上げます。
— ツール・ド・東北 (@tourdetohoku) May 26, 2018
ツールド東北事務局(≒Yahoo Japan)のお詫びによると、不具合が5時間ほど続きました。
ちなみにシステム的に当事者に当たるJTBスポーツステーションがお詫びを出したのは2日たった5月28日(月)。
このエントリーでは謝罪が遅いとかうんぬんとかそういう話には触れません。
ウェブアプリケーションプログラマー的に今回の問題を考えてみる
自分はウェブアプリケーションのプログラマーです。
ウェブアプリケーションプログラマーとして、今回のツールド東北2018@JTBスポーツステーションの問題を考えてみます。
サーバーをあらかじめ増やしておくべき、みたいな話は出しません。そもそも今回のトラフィックが結局どのくらいあったのかもわかりません。
問題点を以下の3点で整理してみます。
- 申し込みステップが多すぎる。
- 一部のサーバー負荷がシステム全体をダウンさせてしまう。
- JavaScriptによるフォームコントロールの存在によってUIが期待しないエラー状態になってしまう。
申し込みステップが多すぎる
今回のツールド東北2018@JTBスポーツステーションの申込みは、ステップをまとめると以下のようになっていました。(覚えている範囲です。)
- JTBスポーツステーションログイン
- イベントページ
- 申し込みコースの選択をするページ
- 申し込み内容の入力をするページ
- 申し込み内容の確認をするページ
- 申込みの確認、というページ
- 支払い方法の選択をするページ
- 申込み内容の確定ページ
支払い方法でクレジットカード決済を選択すると、更にステップが増えます。
- マイページから未決済イベントを選択。
- 支払いの注意事項の確認をするページ。
- 支払い方法の入力をするページ。
- 決済完了ページ。
覚えているだけで12ページあります。12ページのページ遷移全てでアクセスエラーになる可能性があります。
エントリーは大事な内容を入力していますし、決済方法も大事な入力をしています。簡単にページ数を減らすことがいいとは言いづらいですが、ちょっと過剰です。
申込み内容の入力は、連絡先の入力と緊急連絡先の入力をしています。事前でも事後でも入力できる内容=イベントとは本来直接関係しない入力内容です。
申込みの確認、というページは、「申込み内容の入力ができました」「次は支払い方法を選択します」ということを言っているだけで、何も情報がありません。申込みの途中なので、仮受付状態になっている、みたいな話でもありません。
じゃあ、どうするの?
より前工程の申込みステップをシンプルに省略することができれば、それだけアクセスを削れます。
丁寧な確認ステップを進ませたいのであれば、それだけインフラコストへ投資する必要がある、という言い方もできるかもしれません。
一部のサーバー負荷がシステム全体をダウンさせてしまう
JTBスポーツステーションは、システム全体が単一サーバー群で構成されていたような雰囲気があります。
ツールド東北2018のエントリーが始まると同時に、JTBスポーツステーション自体へのアクセスや、JTBスポーツステーションへのログイン処理もアクセスエラーになり始めました。またクレジットカード決済についても同様に、アクセスエラーが何度も発生しました。
おそらくアクセス集中していたのは、ツールド東北2018イベントページ〜申し込み内容の入力あたりまでです。(すくなくとも、クレジットカード決済にアクセス集中していたことは考えづらいです。)
つまり、一部の機能へのアクセス集中によって、システム全体がダウンしてしまっていた、という状態が考えられます。
で、どうするの?
クリティカルな機能をサーバー負荷から切り分けられるような構成をすることを検討できます。
- イベント申し込み機能
- クレジットカード決済機能
- その他の機能
イベント申し込みは、先着順のような申込みの場合、一気にアクセスが集中する傾向があります。イベント申し込みにアクセス集中したとしても、クレジットカード決済には影響させない、というような切り分けを考えておくとよさそうです。アクセス集中する場合には、イベントの規模に合わせて、サーバーを増強しておくことができます。
クレジットカード決済を切り分けるといいのは、お金のやりとりが発生する部分だから、です。決済方法を入力したあとにアクセスエラーが発生すると、決済ができたかどうかが不安になります。多重決済をしてしまった場合、ユーザークレーム〜補填をする必要もでてきます。
アクセスするサーバー群を整理できたら、ボトルネックがデータベースに移るはず。
JavaScriptによるフォームコントロールの存在によってUIが期待しないエラー状態になってしまう
JTBスポーツステーションの申込みフォームのいくつかは、JavaScriptによってコントロールされていました。
そのJavaScriptは、別ファイルで追加リソースとして読み込まれる内容に記述されていました。
とはいえ、ここまではよくある話。
問題は、アクセス集中によってサーバーへのアクセスがし辛い状態の中で、同じサーバーからJavaScriptを読み込もうとしていたのです。つまり、UIにはみえないところで、JavaScriptの読み込みがエラーしていました。
JavaScriptの読み込みがエラーしたことで、申込みフォームを動かすためのJavaScriptコードが存在しないため、申込みフォームが反応しない、ということが発生していました。
ちなみにですが、JTBスポーツステーションは、JavaScript以外にも画像やCSSもアプリケーションサーバーから配信しているように見えます。
んで、どうする?
3つくらい方法があります。
- ミッションクリティカルなフォームのコントロールにJavaScriptを使わない。
- ミッションクリティカルなフォームコントロールするJavaScriptはHTMLの中に書いてしまう。
- JavaScriptのような静的ファイルはCDNを使って配信し、アプリケーションサーバーへアクセスさせない。
1つ目の方法は最も簡単な方法ですが、申込みフォームの入力内容チェックなどができなくなります。
2つ目の方法はありがちですが、JavaScriptライブラリに依存し始めた途端に実現が難しくなるかもしれません。単純にHTMLのファイルサイズが大きくなるだけなので、読み込みが遅くなることも予想されます。
3つ目の方法はコストがかかる方法になりますが、JavaScriptに依存したUIをつくることが当たり前のようになっている今なら、最も現実的な方法だろうと考えます。