エラーが表示されてほとんどアクセスできなかった「Go To Eatひょうごキャンペーン」のシステムについて考える
「Go To Eat ひょうごキャンペーン」のWebシステムがあまりに脆弱でエラーハンドリングもできてないので、現象をまとめてどのような対応ができるかを考えてみる記事です。キャンペーンサイトとはいえ、農林水産省から委託を受け、税金を使って展開してるサービスなので、しっかり考えてみましょう。
外部からの観察なので、システム構成について正確である保証はありません。また本記事を用いて事務局および日本旅行を批判するのはお控えください。よくいう「バグを憎んで人を憎まず」でお願いします。
どういうキャンペーンなのか
Go To Eatにはオンライン予約でひとり最大1,000円もらえる「オンライン飲食予約」と、事前に25%のプレミアムのついた食事券を購入して店舗で使う「プレミアム付飲食券」があります。「プレミアム付飲食券」は各都道府県別に販売事業者がおり、国からの補助を受けて飲食券の発行業務を担っています。
兵庫県は、「Go To Eat ひょうごキャンペーン事務局(農林水産省受託事業者:株式会社日本旅行)」がその業務を担っており、以下の日程でオンラインで「プレミアム付飲食券」の申込受け付けを行っています。
25%の補助率があるということで大人気で、第一期では何と販売開始から1時間で完売したそうです。当然アクセスが集中してつながりにくかったとか。どうしても予算はあるので第2期も終了が早いかもしれませんが改善して受け付けてくれてるはず!ということで、私も申込期間内にアクセスして飲食券を購入しようとしました。
バリエーションあるエラー
Twitterで「Go To Eat 兵庫」などと検索いただくと、「受付ができない」「つながらない」「メンテ中?!」と大体の状況を把握できると思います。
https://twitter.com/search?q=GoToEat%E5%85%B5%E5%BA%AB&src=typed_query
実際、受付開始日にはバリエーションあるエラーを見ることができました。2017年10月1日に終わるメンテナンス画面が表示されたり:
データベースエラーがでてきたぞっていうか、Perl5.8.9?!現行は5.32.0ですよっていうか、もうとっくにサポート期限きれてるバージョンですよ。
登録期間中(10/29)にも関わらず、第一期で代表者登録が終了されたままのページ(第二期は別ページで登録でしたが、ページは生きていました)。
明らかに「アクセス負荷に起因するエラーじゃないだろお前ら」みたいなのがでてきて目を疑うイベントでした。よくいわれる「アクセスが予想以上に集中した」は仕方ない部分もありますが、これは違うだろ。
ちなみに、食事券は「1日にひとり1回購入できる」ようになってるのですが、データベースにユニーク制限かけてなかったようで、2回3回登録されてしまったという報告もあります。アクセスが集中してアプリ側でバリデーションがろくにできないことも想像つくんだから、DB側でもロックかけておこうよ・・・。
もちろんサービスダウンも
上記以外にも「502 Bad Gateway」、「504 Gateway Time-out」が頻出し、偶然疎通しても「HTMLはレンダリングされるけど画像はダウンロードされない」ということも。
上記画像だと、左に「承認する」のボタンがでてくるのですが、画像のためサーバエラーによってダウンロードできず表示できていません。2020年にもなってこのデザインのボタンを画像化した理由って何・・・。
どういったシステムなのか
他にも「新規ユーザ登録方法がマニュアルと異なる」からはじまる罠とかあるんですが、まぁいいだしたらきりがないのでこれぐらいでいいや。さて、ではどういうシステムなのかをみていきましょう。
兵庫県のGo To Eatキャンペーンサイトは、gotoeat-hyogo.comになります。
それに対して、この申込システムは va.apollon.nta.co.jp/gotoeathyogo です。あれ、独自ドメインではない?ということでドメイン側をみてみると、リダイレクトされて以下に飛ぶようになっています。
日本旅行のイベント支援ソリューションページに飛びます。Go To Eat ひょうごキャンペーン事務局は、農林水産省受託事業者として株式会社日本旅行が担ってるので、事業者とドメインが一致しました。なるほど。
ただ、共通でドメインに入ってる appollon という名前が気になります。サーバエラーの時にも度々登場したんですが、何だこれ。と思ったところ、以下を友人が教えてくれました。
よりAppollonについて知りたい方はこちらもあわせてご覧ください。「日本旅行 Apollonシステムを2004年から稼働し、安定的なサービス提供を続けてきております」らしいです。
なるほど。日本旅行ビジネスソリューションズ株式会社の自社サービスなのか。正直なところ、予算配分がわからなかったんだけど、「自社でこういうサービスもってるので大丈夫です!」って提案してサービス落としまくってるなら、まぁ、うん・・・。
対面で紙でしか販売しない事務局(富山は郵便局でのみの販売)もあるので、「予算内でWebシステムまわして対応します」って自分たちで提案したんだろうなぁ。
システム構成
ここまでで私てっきり自社サーバやVPSなどでホスティングしてるのかなと思ったんですが、AWSでした。
で簡単に確認したところ、 va.apollon.nta.co.jp は 54.199.98.231 に割り振られているのですが、 54.199.98.231 を引くと ec2-54-199-98-231.ap-northeast-1.compute.amazonaws.com が割り振られているんですよね。
もうちょっとみていきましょう。
wget -S --spider "https://va.apollon.nta.co.jp/"
をしてみたところ、52.68.62.34 / 54.199.98.231のIPが割り振られているようです。ロードバランサは入ってるみたいです。
ロードバランサが入ってるのになぜEC2に直接アクセスできるか不明で、友人が
IP直打ちでアクセスできることについて説教したい気持ち
というぐらいには謎です。いいのこれ・・・。
あと、どうもEC2サーバがつながりにくいということないんですよね。
てっきり「Go To Eat ひょうご」はサーバ負荷で死んだと思ってたんですが、Virtualhostで割り当ててるメモリか何かが上限に達しただけで、サーバ自体は死んでなかったのではないか疑惑があります。
va.apollon.nta.co.jp/** で同居させている他のサービスに影響を与えないためにかなり絞ってるとかそういう理由かもしれません。
改善方法
ばっちり改善策を提示してやるぜ!!と書き出したのですが、ここまでみてきたところ
・ Appollonのサービス次第
みたいなところがあって、どうもいいにくいですね。私が最初に思った「オートスケーリングぐらいしろよ」はどうも的外れで、サーバ負荷はさほどあがってないままサービスが死んでるようです。一応は2つの視点からの提言をします。
改善方法:契約から考える
現在の「Go To Eat ひょうご」状況は「10回に1回もつながらない」「マニュアルと実際の運用が異なる」という状況でして、軽く探したところ農水省の委託契約書とかみつからなかったので何ですが、これは契約不適合の状況でしょう。2020年の民法改正により、以下のように定められています。
第636条 請負人が種類又は品質に関して契約の内容に適合しない仕事の目的物を注文者に引き渡したとき(その引渡しを要しない場合にあっては、仕事が終了した時に仕事の目的物が種類又は品質に関して契約の内容に適合しないとき)は、注文者は、注文者の供した材料の性質又は注文者の与えた指図によって生じた不適合を理由として、履行の追完の請求、報酬の減額の請求、損害賠償の請求及び契約の解除をすることができない。ただし、請負人がその材料又は指図が不適当であることを知りながら告げなかったときは、この限りでない。
第637条 前条本文に規定する場合において、注文者がその不適合を知った時から一年以内にその旨を請負人に通知しないときは、注文者は、その不適合を理由として、履行の追完の請求、報酬の減額の請求、損害賠償の請求及び契約の解除をすることができない。
そもそも契約にあったであろう「Webサイトによって飲食券の申し込みを受付ける」ことが動作しておらず、第一回受付でその不適合を認識しながら第二回も改善できていないので、早急に改善できなかった(履行の追完の請求)場合は、報酬減額、損害賠償の請求を行う可能性があります。
ということを盾に、まともなサーバ構成にしてもらうことですかね。スケーリング前提のサービスではなさそうな雰囲気があって、サーバ台数増やしても効果なさそうなので、根本的にどうにかしてもらうしかないですね。
私が事業者だったら、同居(VirtualHost)ではなく、せめて単独でEC2使ってフルスペック使えるようにします。
改善方法:技術から考える
Perl5.8.9であることとかは置いといて、根本的にここを直せば負荷は1/2以下になると確信しています。この前提を叩き込んでおくべきです。
バックエンド言語でHTMLを生成するのはコスト高。
WordPressのテンプレートしかり、バックエンド言語でHTMLを都度生成するのはコストが高いのです。毎回、プログラムが走って、HTMLを生成してレスポンスして。多分AppollonはCMSで文章とかは全部DBに入ってて、毎回レスポンスしてると思うんです。つまり、ページがアクセスある度にDB通信もしてる。
どうして確信できるって?
全ページヘッダにログインステータスが表示されるからですよ。つまりこのレスポンスHTMLはキャッシュすらできないわけです。なぜか?ユーザ名をここに表示して、ログインユーザメニュー提供してるからですよ💢
今回のプロジェクトには非現実的だとは思いますが、抜本的な改善策はバックエンドとフロントエンドを分けることです。バックエンドはREST APIのみ。そうしたらサーバ負荷が高まってバックエンド落ちても、フロントエンド側でエラーレスポンスのハンドリングできるわけです。
◯ キャッシュを活用しよう
現実的な路線としては、トップページのHTMLは「ログイン」「非ログイン」の2通りのテンプレートのみにしてキャッシュで返してしまいましょう。「◯◯様でログインしています」という文字さえなくせば2パターンに絞れるので、DBアクセスもHTML生成も最小で済みます。
多分、現在キャッシュ使ってないですよね・・・。せめてキャッシュを使えば改善されるはずです。
あと分散という意味だと、画像はS3においてCloudFrontに設置しましょう。現在、同一サーバにアクセスしてるため、画像リクエストがある度にサーバがレスポンスしてる状況改善するだけでも随分マシになると思います。
まとめ
自社で責任をとりきれない範囲(今回のような行政受託など)は、「ただ作れる人」ではなく、ちゃんと専門家いれることをおすすめします。第三期募集までに改善されてることをお祈りしています。
あとフロントエンドとバックエンドを分けることによって、Web技術でモバイルアプリをつくることもできるようになるので、もしWeb制作者で面白そうという方いればぜひ以下の本ご活用ください!
それではまた。