【研修資料公開】 Webアプリケーションアーキテクチャ設計
ラクーンホールディングス技術戦略部では新卒入社後のフォローアップ研修として、2,3,4年次に研修を行っています。その一環の、Webアプリケーションアーキテクチャ設計のテキストになります。
研修のゴール
- 「アーキテクチャ」についてイメージを持つ
- コンピュータサイエンスで言うアーキテクチャにも、ソフトウェアのアーキテクチャとハードウェアのアーキテクチャなど、種類があることを知る
- アーキテクチャ特性を網羅的に覚える
- Webアプリケーションの代表的なアーキテクチャパターンを知る
- 簡単なWebアプリケーションアーキテクチャをすぐに設計できるようになる
はじめに
この研修では、基礎的な知識ばかりが登場します。4年次、つまり丸3年以上実務経験を積んだ人にとっては既に知っている内容が多いかと思います。
Webアプリケーションアーキテクチャの設計には、全てのバランスを取る必要があります。全てのバランスを取るためには、全ての観点を知っておかなければなりません。全て必要で、1つでも考慮漏れすると、大きな災いを呼ぶ場合があります。0から100%身につけるのは大変ですが、90%身についている状態であれば容易に習得できるはずです。
この研修で残りの10%が見つかれば大成功です。
try
この研修ではワークをいくつか行います。
5分間でブログサービスをフルスクラッチするときのアーキテクチャ図をかいてみましょう。
(最後にも同じワークを行います)
広義のアーキテクチャ
アーキテクチャという言葉は元々の意味は建築学、建築様式を表します。
建築では目的のために土地・空間を有効に活用するために、機能や美しさ、持続可能性などを考慮しながら、構造や設計を行っていきます。
例えば、同じ100坪の土地があったとします。この土地を有効に活用するために、どんな建物を建築するでしょうか?
もし会社でオフィスとして使用するなら、容積いっぱいまで6階建て程度の鉄筋コンクリート造の建物を建て、広い執務室とたくさんのトイレ、いくつかの会議室がある間取りをイメージするのではないでしょうか。50名程度のメンバーが快適に仕事できる空間になりそうです。
これが一戸建ての住宅として考えると、10畳程度の部屋が4つ程度あり、キッチン、バス、トイレを1つずつ備え、余ったスペースは庭やガレージとすると思います。このときは木造になりそうです。4,5人の家族が楽しい生活を送れそうです。
- 鉄筋コンクリート造
木造と比べて値段が高いが、耐震性、耐火性が高く、防音効果や高い気密性がある。気密性、遮音性に優れている。
- 木造
比較的低価格だが、耐火性や気密性や遮音性が低い。自由度が高く、高級な木材を使用したり、メンテナンス可能な構造にすることで、数百年持つような高性能にすることもできる。
構造の選択によって、こういった特徴を持ちます。土地・空間というリソースは同じでも、構造を変化させることで、得られるものが変わります。仕事できるか寝泊まりできるかといった目的や、使用できる人数、土地の広さなどの状況に応じて、適切な構造を設計し、よりリソースを使いやすくする人がアーキテクトです。
Webアプリケーションアーキテクチャ
元の意味では建築を表しますが、今回のテーマであるWebアプリケーションの構造設計のこともアーキテクチャと呼びますし、CPUやネットワークなどの構造設計のこともアーキテクチャと呼びます。どの場合も、限られたリソースがあり、目的があり、それに対しての構造と設計のことをアーキテクチャと呼びます。
今回の研修では、まずWebアプリケーションによく使用するミドルウェア等のソフトウェアアーキテクチャを知り、ソフトウェアアーキテクチャ的な特性を考えながらWebアプリケーションアーキテクチャの設計を学んでいきます。
Webアプリケーションでよく使うミドルウェア
Webアプリケーションを構築するためのソフトウェアであるミドルウェアのアーキテクチャについて考えてみましょう。
クライアント
ブラウザ
HTML・CSSをパースし、jsを実行できるソフトウェアです。
ブラウザだけクライアント側にあり、このあと説明するものはサーバ側のソフトウェアです。
Webサーバ
HTTPプロトコルを使用して、ブラウザにコンテンツを配信するサーバです。用途ごとにいくつかの種類に別れます。
HTTPサーバ
HTTPプロトコルを使用して、CSSやjs、画像、固定のHTMLなど、静的ファイルの配信に使います。様々なユースケースに対応した機能が内蔵されていたり、モジュールとして組み込めます。configを書くだけでセキュリティ機能や、後述するリバースプロキシ、ロードバランサとして利用できます。
Webアプリケーションサーバ
HTTPプロトコルを使用して、動的にコンテンツ生成した結果を返します。動的なコンテンツ生成するために、テンプレートエンジンや作成したプログラムを組み込むことができます。
リバースプロキシ
機能ごとにサーバが別れている場合に、適切な機能を持ったサーバにリクエストを振り分けます。パスを見て振り分ける場合が多いです。例えばパスが.css
で終わる場合は静的コンテンツを配信するHTTPサーバ、/api/
から始まる場合はAPIのWebアプリケーションサーバといった感じです。
ロードバランサ(LB)
複数のHTTPサーバやWebアプリケーションサーバを動かすとき、負荷を分散させてバランスを取ります。
a,b,cという3台のサーバがあったとき、a,b,cと順番に割り振るラウンドロビンや一番接続数が少ないサーバを探して割り振るリーストコネクション、IPアドレスやcookieごとに固定したセッション永続性機能などのルールがあります。
データストア
Webアプリケーションサーバから、データを保存するデータ層の機能を切り出したプロダクトを指します。
RDB(リレーショナルデータベース)
Webアプリケーションを開発している方にはおなじみのあいつです。
複数人で使用しても整合性を保ったままデータを保存できます。またリレーショナルという名前の通り、関連するデータをまとめて取得・変更する機能が優れています。
後述する一貫性と可用性を持っていますが、やや遅いです。
KVS(キーバリューストア)
RDBの次に登場することが多い、シンプルなデータストアです。
アーキテクチャ的には速度のために一貫性や長期保存性を持つか持たないか選択できるのが特徴です。一貫性を持たせる場合はRDBを選択する場合が多いので、速度を優先させたいときに採用する場合が多いです。
メールサーバ
SMTPサーバ
メールを送信するサーバです。
SMTPプロトコルで受け付けてSMTPプロトコルで送信するサーバが基本ですが、HTTPプロトコルで受け付けてSMTPプロトコルで送信するサーバも一般的です。
IMAP / POP3サーバ
SMTPプロトコルで受信したメールを保存しておくサーバです。
IMAPプロトコルやPOP3プロトコルで保存したメールを読み出すのが一般的ですが、こちらもHTTPプロトコルで読み出せるサーバも一般的になってきています。
メッセージキューイング
順番に処理したいときに、順番を管理してくれるソフトウェアです。
名前の通りキューなので、先に入れたものから順番に渡してくれます。
順序が重要なタスクや、重い処理を行い順番待ちするとき、同時に複数の処理を行うとパフォーマンス的な問題が発生する場合に使用します。
ジョブ管理システム
メッセージキューイングでは順番だけ管理してくれますが、受け取ったあと正常に完了したかどうか管理したり、定時実行したい場合に使用します。
色々できる代わりに、ほとんどのジョブ管理システムは複雑なソフトウェアアーキテクチャとなっています。
製品ごとに機能が異なり、オーバースペックな機能を持つものもの多いため、採用はよく検討しましょう。
ソフトウェアアーキテクチャ的な特性を知っておく
このように、Webアプリケーションでは様々なソフトウェアを使用します。なぜ様々なソフトウェアを使用するか考えておきましょう。
極端なことを言えば、Webアプリケーションサーバのみがあり、全て自分でプログラムを書いてしまえば解決します。流行っているプログラミング言語ならライブラリも充実しているため、比較的簡単に実現できてしまいます。
専用のミドルウェアのプロダクトには、それぞれライブラリを使うより良いソフトウェアのアーキテクチャ的な特性があります。Webアプリケーションのアーキテクトは、Webアプリケーションで使われるミドルウェアのソフトウェアアーキテクチャ的な特性を知った上で、ミドルウェアを組み合わせてWebアプリケーションアーキテクチャを構築します。
「ソフトウェアアーキテクチャ的な特性」と一言で言ってしまいましたが、たくさんの観点があります。次にあげるのは、その一部です。
信頼性(reliability)
JIS-Z8115:2000 「アイテムが与えられた条件で規定の期間中、要求された機能を果たすことができる性質」
平均故障間隔(MTBF)等で表される、プロダクトがどれくらい故障しないか表します。
ソフトウェアはわりと短い期間で故障するプロダクトは多いです。PCの調子が悪くなったときに「とりあえず再起動」と言ったことがある方も多いのではないかと思いますが、再起動で直るのはソフトウェアを長時間稼働させて機能不全になった場合、つまり信頼性が低いプロダクトを使った場合です。
ミドルウェアを選択する場合は、ソフトウェア起因で長期間稼働させても機能不全が起きないようなプロダクトを選択します。
可用性(availability)
JIS X 0014:1999「必要となる外部資源が与えられたときに、ある時点において、又はある一定の期間、機能単位が決められた条件のもとで要求された機能を果たせる状態にある能力。」
信頼性はプロダクトがどれくらい機能不全になるかを表すのに対し、可用性は利用者がどれくらい機能を利用できるかを表します。
ここで言う利用者は、HTTPサーバのようにエンドユーザがアクセスする場合はエンドユーザですが、RDBやSMTPサーバにとってはWebアプリケーションサーバになります。
可用性は重要な指標ですが、複数の要因の影響を受ける複雑な指標です。
一貫性(consistency)
主にストレージ系で使う指標で、「誰かがデータを更新したら、必ず更新された後のデータを読み出せるかどうか」です。
例えばこのあいだ鎌倉幕府が成立したとされる年が1192年から1185年に更新されましたが、そのへんの人に聞くと1192年と答えが帰ってくる場合があると思いますし、今年度の日本史の教科書には必ず1185年と書いてあります。人が覚えている情報は更新されたからと言って必ず更新された後のデータが読み出せるわけではないので一貫性が無く、教科書には一貫性があると言えます。
ソフトウェアでもそんなコトある?と思うかもしれませんが、複数台構成にしたりキャッシュを使用すると、一貫性が損なわれる場合があります。
ネットワーク分断耐性 (partition tolerance)
複数台で分散させて動作させたとき、独立して動作できるかを表す指標です。
ネットワーク分散耐性を持たせて、複数台で分散させて動作させるアーキテクチャを採用する場合、一貫性が損なわれる場合が多いです。別のサーバで更新した情報をリアルタイムで取り込むには、かなりコストが掛かるためです。
パフォーマンス
ターンアラウンドタイム、ラウンドトリップタイム(RTT)
処理をリクエストしてから実行完了するまでの1回あたりの時間です。
ターンアラウンドタイムはコンピュータが計算を始めて完了するまでの時間、ラウンドトリップタイムはネットワークでよく使う言葉で通信にかかる時間を含めたものになります。
スループット(throughput)
単位時間あたりに実行できる処理の数です。
RTTが短ければスループットも多いんじゃないかと思うかもしれませんが、そういう場合も多く、そうでない場合も多いです。
例えば伊勢うどんという料理は、先にうどんを30分以上茹でておいて、注文があったら茹でてあるうどんを使って提供します。事前に茹でてあるのですぐ出せ、注文から提供までのRTTは非常に短いです。一方で茹でてあるうどんがなくなると提供できなくなるので、また30分以上かけて茹でなければなりません。鍋を専有している時間も長く、スループットには限界があります。
並行性(concurrency)
同時にいくつ処理できるかを表します。
並行性を高めることで、RTTは長くてもスループットは高めることができます。例えばカップラーメンを1個ずつ順番に作っていくと、1個目は3分後に提供、2個目は6分後に提供・・となっていきますが、同時に2個作り始めれば3分後に2個提供できます。お湯さえ大量に用意できれば、3個でも5個でも約3分後に提供できます。
並行性が高くてもスループットが低い場合、処理しきれなくなってしまいRTTが悪化してしまいます。カップラーメンで言うと10個でも20個でも同時に作ることはできますが、お湯を沸かす速度を超えると、お湯待ちして提供時間が遅くなっていきます。
スケーラビリティ(scalability)
スループットや並行性を増やすために、サーバの台数を増やしたり、より性能が高いハードウェアに切り替えられるかどうかを表します。
ネットワーク分断耐性があるとサーバの台数を増やすことができるため、スケーラビリティは高くなり、スループットや並行性を増やせます。
より高い性能があるハードウェアを用意するスケールアップと、より台数を増やして負荷を分散させるスケールアウトの2種類の方法があります。
スケールアップする場合、ハードウェアにもよりますが低価格帯の場合は値段が2倍になれば性能も2倍になることもありますが、高価格帯になるにつれて値段が2倍になっても性能が少ししか上がらないことが多いです。
スケールアウトの場合は2倍の台数を用意すれば2倍処理できます。ただしスループットは上がりますが、ターンアラウンドタイムは上がりません。
参考:CAP定理
一貫性、可用性、ネットワーク分断耐性の3つのうち、3つ同時に実現できないという定理です。
一貫性(C)、可用性(A)、ネットワーク分断耐性(P)の頭文字からCAP定理という名前になっています。
スケールアウトによるスケーラビリティを持たせるにはネットワーク分断耐性が必要になりますが、可用性を捨てられるシーンは少ないので、一貫性を諦めなければなりません。
どこに一貫性を持たせる必要があるか、どこにネットワーク分断耐性を持たせてスケールアウトできるようにするかは、アーキテクトが頭を悩ませるポイントです。
機能性(functionality)
その機能があるかどうかを表します。
同じHTTPサーバの中でも、HTTP/3などプロトコルに対応しているかといった機能に差があります。
拡張性(extendability)
機能性が足りなかった場合、機能を追加できるかを表します。
元々機能性が高く拡張性が低い戦略のプロダクトと、機能性は低めでも拡張性が高いもの、両方高いものなどがあります。
可搬性(portability)
他のOSやミドルウェア、ハードウェアで動作できるかどうかを表します。
可搬性が低いと、OSやミドルウェアのバージョンを上げたときに動作しなくなったりします。
アップグレード容易性(upgradeability)
セキュリティアップデートなどのアップデートのやりやすさ、機能追加された新バージョンにアップグレードしやすいかです。
外部に直接接続する箇所はセキュリティアップデートを必ず行わなければなりませんが、最新バージョンしかセキュリティアップデートが提供されなかったり、最新バージョンのOSにしか最新バージョンのミドルウェアが対応していないということがよくあります。よって、最新バージョンへのアップグレードを容易に行えるかどうかは、アーキテクトしか気にしないポイントなので、よく検討する必要があります。
長期保存性(archivability)
データをどの程度保持するかを表します。
毎回消えるのか、再起動するたびに消えるのか、最低1年は保持しておかなければならないのか、それとも半永久的に保持する必要があるかです。
結合度(coupling)
ソフトウェアとソフトウェアがどの程度分割できているかです。
HTTPサーバでリバースプロキシしてパスを適切に設定できている状態でないと動かないようなWebアプリケーションを作成した場合、結合度が高い状態です。Webアプリケーションサーバのみでも動くし、リバースプロキシを入れても動くような状態になっていれば、結合度が低いです。どの程度他のソフトウェアに依存して動いているかを表しています。
コスト(cost)
実際に現金を支払う必要がある金銭コストや、コンピュータのリソースをどれくらい消費するかといったコスト、保守するために工数が必要になってくる人員コストがあります。
変更容易性(changeability)
機能追加、削除をどれだけ容易に行えるか表します。
他のほとんどの指標の影響を受け、定量的に表しづらい複雑な指標です。
トライアンドエラーを繰り返し、成果を出す必要があるものを作成している場合は、アーキテクトが考えなければならない最重要の指標です。
Try
特定のミドルウェアを1つあげ、アーキテクチャ的な特性を各指標で測ってみましょう。
ソフトウェアアーキテクチャで扱うリソース
アーキテクチャは限られたリソースを目的のために構造をもたせたものです。前述したソフトウェアアーキテクチャ的な特性が目的にあたります。次に目的を達成するために使用できるリソースのうち、必ず抑えて置かなければならない古典的なものをあげます。
CPU
超高速に計算する機械です。超高速ですが、無限に速いわけではありません。1秒間に10億回くらいの計算ができます。
1つ処理するのに1,000回計算が必要なアルゴリズムで、1,000行*1,000列くらいある組み合わせを処理する場合、1秒かかります。10,000行になれば10秒、さらに10,000列になれば100秒と、計算する量は倍倍に増えていく特性があります。
アプリケーションエンジニアが「あれっ、ここって計算量意識しないとだめなんだっけ?」と思う瞬間を減らしてあげるのも、ソフトウェアアーキテクトの仕事の一つです。意図せず計算量が増えるような構造にしないことは心がけましょう。
ソフトウェアとハードウェアのアーキテクチャは別に考える場合が多く、ソフトウェアアーキテクトが具体的にリソースの性能を指定するシーンは少ないです。なのでふんわりイメージするのがオススメです。環境によって10倍場合によって100倍の性能差がありますが、1万倍・10万倍と差がつくことはめったにありません。「この場合は10ms~100msくらいで帰ってきそうだぞ・・?」くらいのイメージを持ってください。
メモリ
CPUが専有しているので、CPUから気軽にアクセスできる記憶領域です。結構大きく、結構速いです。数GB~数十GB程度保存でき、1秒あたり数十GB読み書きできます。ただし電源を切ると消えます。
数GBあれば、Webアプリケーションで扱うHTMLや画像なら全部乗ってしまいますが、1,000人分、10,000人分を一度にとっておけるかというと足りなくなります。十分広いものの、超広いわけではありません。頭を悩ませるポイントではあります。
ストレージ(ディスクとも言う)
メモリは電源を切ると消えますが、ストレージは電源を切っても消えません。ただし絶対ではないので、そこそこ消えると思っておいてください。また、超広いです。継ぎ足しできるような構成にする場合が多いので、お金があるかぎり増やせます。そこそこ安く、1GBあたり数十円で済みます。ただし結構遅く、1秒あたり数十MB~数GBで、しかも結構ブレがあり、思ったより遅い・・ということもよくあります。
ソフトウェアの構造を工夫することで、前述のデメリットを軽減することができます。アプリケーションエンジニアにストレスなく開発してもらい、ユーザには信頼感がある構造を作ります。
ネットワーク
細かいことを言うと全然違うのですが、ふわっと考えるとネットワークもメモリやストレージと同じように、データを取得したり保存したりする仕組みと考えて良いと思います。
CPU、メモリ、ストレージは自分で管理している機械ですが、ネットワークの場合は他者が管理している点が違います。他者が管理しているので、どれくらい速度が出るか不明、いつ壊れるか不明、いつまで保存してくれるか不明です。
また、Webアプリケーションの場合は、こちらがデータを返す側になります。
Try
実効速度が1Gbpsのネットワーク回線で1000人に各1MBのファイルを転送する時、実効速度が20MB/sのストレージから読み込む場合、実効速度が200MB/sのストレージから読み込む場合、実効速度が5GB/sのメモリから読み込む場合でそれぞれ理想では最短何分で転送できるか、計算してみましょう。
※現実には様々なオーバーヘッドが発生するため、理想値にはなりません。ここではだいたいでかまいません
想定回答
白文字にしているので、読む場合は選択してください。
200MB/sのストレージから読みだした場合、ネットワーク回線がボトルネックとなり、理想でも最大1250MB/sとなります。1000人 * 1MB / 125MB/s = 8秒かかります。
これ以上高速なストレージを使用したとしても、ネットワーク回線がボトルネックとなっているため、パフォーマンスの向上は見込めません。25倍速い5GB/sのメモリから読み出そうとも、8秒かかります。
ソフトウェアアーキテクチャまとめ
ソフトウェアアーキテクチャは、コンピュータのリソースを使用して、ソフトウェアに優れた特性を持たせる構造のことです。
例えばKVSのアーキテクチャの場合、データをストレージに保存するか、すぐにストレージには保存せずにメモリに保存するか、データを保存する構造に種類があります。ストレージに保存する構造にすると再起動してもデータは消えないので長期保存性が高いですが、ストレージに書き込みしなければならないのでRTTは劣化します。メモリに保存するとストレージよりメモリが高速なのでRTTは短いですが、再起動するたびにデータが消えてしまいます。間を取って、いったんメモリに保存したあとにストレージに書き込む構造にすると、RTTはメモリ並みに高速でスループットはストレージ並み、計画的な再起動ではデータは消えませんがハードウェアトラブルでの再起動の場合、データが消えます。
同じハードウェアを使っていても、採用するソフトウェアアーキテクチャによってソフトウェアアーキテクチャ的な特性が変わります。ほとんどの場合、あちらを立てればこちらが立たずというトレードオフになります。
Webアプリケーションアーキテクチャを考えるとき、どのようなソフトウェアアーキテクチャ的な特性を持ったミドルウェアなのか把握し、それらを組み合わせてWebアプリケーションのシステム全体のアーキテクチャを設計していきます。ミドルウェアがどのような特性を持っているか考えるには、ミドルウェアのソフトウェアアーキテクチャを調べるのが遠回りしつつも早道ですが、Webアプリケーションアーキテクチャを考えるときにそんなことを考えている余裕はありません。役割ごとに抽象化したイメージを持っておき、ざっくりとWebアプリケーションアーキテクチャを考えた後に、各ミドルウェアの特性を考えて選定すると良いでしょう。
アプライアンス
コンピュータは基本的には汎用的でソフトウェアによって機能を切り替えられる機械ですが、特定の機能を提供する機械もあり、アプライアンスと言います。
専用のハードウェアと、専用のハードウェアにチューニングしたソフトウェアを持っているため高速で堅牢です。ただし汎用的なコンピュータより高い性能を持つアプライアンスは値段が高いです。
ネットワーク分断耐性が低く、高い性能と堅牢性が求められるところで使用します。ロードバランサはこのユースケースに該当するので、ある程度の規模になるとアプライアンスを使用する場合が多いです。
クラウド
インターネットの向こう側にある、何かの機能を持ったサービスです。どのようなアーキテクチャが採用されているか意識せずに、機能だけを使用できます。
ただし、クラウドの向こう側でも何らかのソフトウェアが動いていて、何らかのソフトウェアアーキテクチャ的な特性があることを忘れないでください。金銭コストと保守コスト以外の特性は、クラウドでもオンプレミスでも根本的には変わりません。
クラウドにはインフラだけ提供するIaaS、ミドルウェアだけ提供するPaaS、機能だけ提供するSaaSに種類が分かれています。
Webアプリケーションアーキテクチャ
ようやく本題です。
ミドルウェアの組み合わせや、アプライアンスやクラウドを活用して構造を作ることで、Webアプリケーションに優れた特性を持たせることがアーキテクトの仕事です。
Webアプリケーションアーキテクチャでは特に可用性、変更容易性、パフォーマンスの3点が重要です。3点とも様々な要因から影響を受ける複雑な指標です。1台のサーバでは実現が難しく、バランスよく実現するために、アーキテクチャをよく設計しなければなりません。バランスよく実現するアーキテクチャを設計するために、0から考える必要はありません。ほとんどの場合、似たようなユースケースがあり、前例に習うだけで最適なアーキテクチャとなります。この典型的なアーキテクチャのことを「アーキテクチャパターン」もしくは単にパターンと呼びます。デザインパターンも似たような概念です。
それではWebアプリケーションアーキテクチャのパターンを見ていきます。
Webアプリケーションサーバのみ
Webアプリケーションサーバ1台だけの構成です。
特性はそこそこ優れています。Webアプリケーションサーバはあるため、拡張性が高く、基本的には何でもできます。Webアプリケーションサーバ用のミドルウェアやライブラリは性能が高く、信頼性が高く年単位で問題なく動きます。
スケーラビリティや変更容易性には課題があります。複数台構成にするとストレージが共有されておらず一貫性が損なわれてしまいます。アプリケーションに変更を加える場合にもダウンタイムが発生し、可用性が損なわれます。
HTTPサーバのみ
HTTPサーバのみの構成で、Webアプリケーションと言うにはちょっと無理があります。
静的コンテンツの配信しかできないので、長期保存性がほぼ無ありません。ブラウザで動作するクライアントアプリケーションは作成できます。
パフォーマンス面ではめちゃくちゃ性能が高く、分断耐性があり、HTTPサーバはスループットも並列性も高く、ボトルネックになる処理はありません。
スタティックサイトジェネレータ(SSG)やSaaSと組み合わせると相性が良いですが、サーバレスアーキテクチャを採用したほうが良いと思います。
3層アーキテクチャ
プレゼンテーション層、アプリケーション層、データ層の3システムに分割するアーキテクチャです。Webアプリケーションの場合、プレゼンテーションがブラウザで表示するHTML・CSS・js、アプリケーション層がWebアプリケーションサーバ、データ層にRDBを採用する場合が多いです。
このブラウザ-アプリケーション層-RDBの3層アーキテクチャがWebアプリケーションアーキテクチャの基本になってきます。Webアプリケーションの場合はプレゼンテーション層はブラウザになり、データ層は一貫性と可用性を持たせたいケースが多くRDBを採用しがちです。どちらも第一選択として採用してしまって問題ありません。何か特別な事情がある場合に、事情にあわせて検討していきます。
一方でアプリケーション層はバリエーションが多く、Webアプリケーションアーキテクチャという場合はアプリケーション層だけの話をしてることも多いです。アプリケーション層のアーキテクチャを見ていきます。
テンプレ構成
HTTPサーバとWebアプリケーションサーバが最低4台あり、HTTPサーバとWebアプリケーションサーバが1:1で接続され、4セットがそれぞれロードバランサから振り分けられる構成です。あと忘れてはならないのがメール配信サーバです。Webアプリケーションは能動的に通知する仕組みが弱く、誰でも間違いなく使える仕組みはemailくらいしかありません。
静的コンテンツの配信とリバースプロキシをHTTPサーバが行い、複雑な機能はWebアプリケーションサーバが担います。
可用性と変更容易性を両立させるために、最低4セットWebアプリケーションサーバを用意しています。まず常に2台は動作させておく必要があります。形あるものはいずれ壊れるので、信頼性がどんなに高くても急に1台壊れます。信頼性が高い場合は2台同時に壊れることは稀なので、2台置いておけば安心です。また、アプリケーションの変更時にダウンタイムが発生します。ダウンタイム発生時はロードバランサから切り離す必要があります。切り離し中にも2台が稼働している必要があるので、計4台となります。
この構成は、ほとんどのユースケースに対応できる汎用的な最小構成です。このテンプレ構成に、アプリケーションごとの特別な事情にあわせて追加していきます。
Try
テンプレ構成で具体的なプロダクト名を書いたアーキテクチャ図を書いてみましょう。
CDN
ブラウザとLBの間にCDNを挟んだ構成です。
CDNはフォワードプロキシしてHTTPキャッシュするクラウドサービスで、世界各地にサーバがあります。
インターネットは高速といえども、距離の影響を受けます。直接海底ケーブルで繋がっている日本-アメリカ間でも1回のTCP通信でRTTは速くて数百msかかります。世界各地にサーバがありキャッシュされていると、クライアントからサーバまでの距離が近くなり、
RTTが改善されます。
キャッシュするのでキャッシュ制御だけ気をつけなければなりませんが、コスト的にもさほど高くなく、効果も見込めるので、とりあえず導入しても良いのではないかと思います。
データキャッシュ
アプリケーション層とデータ層の間にストレージを使用せずメモリにデータを保存する、インメモリストアのKVSを配置します。
データ層に配置しているRDBは一貫性と可用性を両立させる必要があります。そのためネットワーク分断耐性を持たせられず、スケーラビリティがなくなってしまいます。
キャッシュのため2回目以降のアクセスにしか効果はありませんが、ストレージよりメモリのほうが高速なためスケールアップの効果と、KVSはスケールアウトすることもでき、データ取得にスケーラビリティを持たせることができます。
その代わり、気をつけてアーキテクチャ設計しないと、Webアプリケーションシステム全体での一貫性が損なわれてしまう可能性があります。スケールアウト可能なKVS自体は一貫性はありませんが、ほとんどのWebアプリケーションは一貫性の担保が必須です。
一貫性が必要と言いつつも、全てのデータが厳密に一貫性を持っている必要はありません。検索機能などは反映が遅れてしまっても1分程度までなら許容される場合が多いです。決済系の機能は必ず一貫性を持たせる必要があります。
目的・機能によってユーザが気づかない程度にほんの少しだけ一貫性を緩めてキャッシュを活用すると、かなりパフォーマンスを向上させることができます。
ワーカー
WebアプリケーションサーバはRTTもスループットも高性能が求められます。そのためには、常に低負荷の状態を保つ必要があります。
それでも高負荷の処理しなければならない場合もあります。そんなときは高負荷の処理専用のサーバを用意します。これをワーカーと呼びます。
ワーカーは高負荷の処理を担当するため、すぐに処理を開始できない場合も多いです。そのため、ワーカーに出す指示はメッセージキューイングシステムを経由します。
マイクロサービスアーキテクチャ
Webアプリケーションを機能ごとに分割し、アプリケーション層とデータ層を丸々機能ごとに割り当てるアーキテクチャです。
マイクロサービスアーキテクチャの特性は、変更容易性をすごく上げられる代わりにその他の特性がガタ落ちするリスクを抱えています。
特性がガタ落ちするかどうかは機能分割のやり方にかかっており難易度も高いです。玄人向きのアーキテクチャだと思います。
サーバレスアーキテクチャ
PaaSとSaaSを駆使して、Webアプリケーションを構築するアプローチがサーバレスアーキテクチャです。
スケーラビリティが非常に高く、金銭のイニシャルコストも0に近いです。ランニングコストは保守コストはほぼかかりませんが、従量課金制のサービスが多いため、アーキテクチャ設計と見積を間違えると金銭のランニングコストは青天井になる可能性があります。
気をつけないとクラウドサービスとの結合度が高くなってしまい、可搬性が落ちてしまいます。
採用を検討するべきアーキテクチャですが、まだ歴史が短く、これを選んでおけば問題ないというパターンは少ないです。
try
5分間でブログサービスをフルスクラッチするときのアーキテクチャ図をかいてみましょう。
(最初と同じワーク)
まとめ
ユーザやそのアーキテクチャで動作するシステムを開発する開発チームの体験に関わる重要部分になります。
アーキテクチャ設計は低レイヤーから高レイヤーまでプロダクトをいかに知っているかどうかという知識量と、アーキテクチャを変更したときに何が起きるか予測する見積スキルが必要です。たくさん知識をつけ、それ活用して具体的なイメージすることがが大切です。設計した後に検証するためにも、テスト環境の作成とテストにコストが必要で、一朝一夕で身につくものではありません。
最近は仮想化の技術が発達しているので、実際に設計した構成で動作させてみやすくなっています。たくさん調べて、たくさん作って試してみて、優れたアーキテクトを目指していきましょう。
アーキテクトとして次のステップを目指すには、システム設計の面接試験という書籍に取り組むのがオススメです。システムごとに必要な特性が異なり、求められている特性に合わせたWebシステムのアーキテクチャ設計を行う課題が約12個ある書籍になっています。Webシステムの典型的なパターンを10個以上学んでおけば、アーキテクトとして活躍できる下地がつくと思います。
株式会社ラクーンホールディングスではアーキテクチャを考えてくれるエンジニアを大募集中です!
興味を持っていただいた方は是非、お話ししましょう!