ウェブサイト ホスティング パターン 

ウェブサイトは最も基本的なシステム構成例として取り上げられることが多いですが、その構成は要件やワークロードによって異なる、大変奥深いものです。

求められる要件の例としては可用性、性能 / 拡張性、コスト パフォーマンス、アジリティなどが代表例ですが、これらのうち、何を重視するかによって、コンピュート、ストレージ、ネットワークといった各構成要素の適切なアーキテクチャを検討する必要があります。Google Cloud ではこれら要件を満たすためのソリューションをいくつか提供しています。これらを適切に採用し、各ワークロードに適した要件を実現することが重要となります。

コンピュートについては、Compute Engine、App Engine、Google Kubernetes Engine、Cloud Funtions、Firebase Hosting など多様な選択肢があり、非機能要件や、現行システムからの移行を考慮する場合は、移行難易度等も考慮して適切なオプションを選択する必要があります。

また、ストレージについても、保存するデータ形式やストレージ アクセスに求められるパフォーマンス等に応じて適切なオプションの選択が必要となります。

その他、データベース、ネットワークなどの要素についても同様に、ワークロード特性や求められる要件に応じて組み合わせは複数存在するため、ここではその全てを述べることは難しいですが、下記ドキュメントにて、それらサービス群の概要を整理しています。

参考ドキュメント :
Google Cloud サービスの概要
ウェブサイトの提供 | ソリューション 

Dynamic site hosting パターン

解決する課題・使いどころ

ワークロード特性や、求められる要件によって、Dynamic site hosting のアーキテクチャは異なりますが、ここでは、可用性、性能 / 拡張性、またオンプレミスなど現行環境からの移行難易度の低さを重視したアーキテクチャ( IaaS を利用するアーキテクチャ)について解説します。これら要件を満たすため、考慮する必要があるのは以下のポイントです。

可用性

  • 冗長構成

可用性を高めるうえで、冗長構成はベスト プラクティスとなります。ユーザの責任で冗長化構成を組むこともできますが、マネージドサービスを効果的に利用することで冗長化構成の構築 / 管理を Google Cloud に任せることもできます。 

  •  分散処理構成

ロードバランサを適切に構成して、冗長化されたインスタンスに対する分散処理を行う事で、仮に特定のインスタンスがダウンした場合でも、他のインスタンスでサービス稼働を継続し、影響を最小限に抑えるためのアーキテクチャを実現できます。また、分散処理を構成することで、後述の性能 / 拡張性向上にもつながります。

分散処理構成を選択した場合、ステートレス アプリケーションの場合、この限りではありませんが、クライアントからの繰り返されるアクセスに対して、同一クライアントからのアクセスは、ロードバランサ配下で動作する複数のインスタンスのうち、毎回同じインスタンスへ接続する必要も出てきます。これを実現するために、セッション管理構成を実現する必要があります。移行期間 / 難易度等を考慮し、アプリケーションからステートを外出しする改修が可能な場合、ステートを外部のメモリストレージなどに保持することで、この課題に対処することも可能です。 

なお、上記の冗長構成や分散処理構成に関しては「マルチゾーン ウォーム スタンバイ」パターンでも解説しているため、そちらも参照ください。

性能 / 拡張性

  • オートスケール構成

負荷に応じたインスタンスのオートスケールを可能とするよう設計します。オートスケールは瞬時にインスタンスをスケールできるわけではない点に注意して、負荷特性を考慮したオートスケール設定を行う必要があります。 

ストレージについては、増加するデータサイズに対し、ストレージの自動拡張を可能とするための設定も行います。

アーキテクチャ

インターネット経由での 3 層 ウェブアプリを想定して、アーキテクチャを図示します。ここではアプリケーション サーバ + リレーショナル データベース を想定します。
※ 本アーキテクチャはゾーン障害に対して、インスタンス グループの複数ゾーンデプロイ、 Cloud SQL による HA 構成等、 Google Cloud ネイティブな構成で対処する方法を示しています。可用性に関しては、より詳細な要件がある場合、 Compute Engine 上に DBMS をインストールし、 サードパーティー ソリューション等でクラスタリング構成といったオプションもあります。詳細は「マルチゾーン ウォーム スタンバイ 」パターンにて記載します。 

architecture
  • Compute Engine
    Google Cloud 上で提供される VM であり、他のパブリッククラウドの IaaS と同様に Linux / Windows をサポートします。今回のパターンでは、インスタンス テンプレートからインスタンス グループを作成の上、要件に応じたスケーリング設定、ヘルスチェック設定等を行います。
  • Cloud Load Balancing
    暖機運転なしで毎秒ゼロから大規模リクエストまでスケールするロードバランサです。Cloud Load Balancing の配下に、先述の Compute Engine インスタンスグループを配置して、リクエストを分散させて利用します。今回のパターンでは、セッション アフィニティ機能を利用して負荷分散制御を行い、また、コネクション ドレインを設定することで安定性を高めます。
    • セッション アフィニティ
      ステートフル アプリケーションの負荷分散を行う場合、そのままの状態ではMIG を用いて冗長化したサーバ間でセッション情報を共有できず、この状態でロードバランシングを行うと、例えば最初にアクセスした VM と別 VM に Cloud Load Balancing によってディスパッチされた場合、セッション情報が失われてしまいます。この課題の対応方法としてセッション アフィニティ機能を利用します。
    • コネクション ドレイン
      コネクション ドレインを有効化して、 VM がインスタンス グループから除外されたときに、既存で進行中のリクエストを完了するための時間を確保します。
  • Cloud SQL
    Google Cloud 上で提供されるマネージド リレーショナル データベース であり、MySQL 、PostgreSQL 、Microsoft SQL Server をサポートしています。 今回のパターンでは、HA 構成や、自動バックアップ、ポイントインタイム リカバリ機能を利用することで可用性を強化します。また、ストレージの自動増量機能を有効化し拡張性を高めます。その他、必要に応じてリードレプリカを利用することで、読み取りパフォーマンスの向上を図ることもできます。 
    • HA 構成
      インスタンスを別のゾーンに複製し HA 構成を実現することができます。HA 構成を組むことでプライマリ インスタンスが応答しなくなった場合、自動的にスタンバイ インスタンスからデータを提供するようフェイルオーバーされます。
    • バックアップ
      Cloud SQL は、オンデマンド バックアップ、自動バックアップの 2 種類のバックアップが可能です。各バックアップ種別によりバックアップ保存期間が異なるため、要件に応じて適切なバックアップ機能を選択します。
    • ポイント インタイム リカバリ
      要件に応じて、ポイント インタイム リカバリ ( PITR ) 機能を利用します。 なお、PITR ではバイナリログが使用されますが、これらのログは定期的に更新され、Cloud SQL の保存容量を使用するため注意が必要です。(バイナリログのサイズが原因で問題が生じた場合、インスタンスのストレージ サイズを大きくすることはできますが、ディスク使用量のバイナリログサイズが大きくなるのはあくまで一時的です。予期しないストレージの問題を回避するには、PITR の使用時にストレージの自動増量を有効にすることを推奨します)
    • ストレージの自動増量
      Cloud SQL では、ストレージ容量が上限に近づいたときに自動的に容量をスケールアップすることが可能です。
    • リードレプリカ
      リードレプリカは、Cloud SQL プライマリ インスタンスから複製された Cloud SQL インスタンスです。リードレプリカは読み取り専用であり、レプリカを使用して、プライマリ インスタンスから読み取りリクエストやアナリティクス トラフィックをオフロードすることが可能となります。(上記アーキテクチャ図にはリードレプリカ構成を表現していませんが、読み取りパフォーマンスの向上を図りたい場合などは、導入を検討してください)

利点

  • 本アーキテクチャを採用することで、既存システム構成を極力変更せず、同一リージョン内で、可用性を高め、かつスケーラビリティの高いアーキテクチャを実現できます。可用性については、複数ゾーンに跨がるインスタンス グループへの負荷分散を Cloud Load Balancing で行うこと、また Cloud SQL の提供する HA 構成で実現し、性能 / 拡張性については、インスタンス グループのオートスケール機能および、 Cloud SQL のもつリードレプリカ機能、ストレージの自動増量機能で対処します。

注意事項

  • MIG を利用したオートスケール構成を実現する場合、最小 / 最大インスタンス数は需要予測や性能試験を基に決めるようにしましょう。MIG を利用することで柔軟性の高いアーキテクチャを実現できますが、スケーラビリティ性能に限界もあるため、十分な検証が必要です。また、「 マルチゾーン ウォーム スタンバイ 」パターンでも述べていますが、Cloud SQL を使うときには、メンテナンス ウィンドウを設定し、メンテナンスの時間を事前に設定します。また、バックアップなども業務要件に応じて設定すると良いです。

Sample config や Code

  • Compute Engine
    • インスタンス テンプレート 
      • マシンの構成:汎用 / シリーズ N2 (要件に合わせて、 CPU コア数 / メモリサイズレベルで指定することも可能)
      • ディスク: SSD 永続ディスク
      • 起動スクリプト:インスタンス起動時に必要な設定を指定
    • インスタンスグループ
      • ロケーション:複数のゾーン (ゾーンの停止などの極端なケースでもアプリケーションの可用性を確保するため、 Compute Engine のアプリケーションを複数のゾーンに分散することをおすすめします)
      • クールダウン期間:インスタンス起動後-安定するまでの時間よりも長い時間
      • 自動スケーリングの指標 / 指標タイプ: HTTP 負荷分散の使用率
      • インスタンスの最小数 / インスタンスの最大数:需要予測や性能試験を基に設計した値 
    • ヘルスチェック
      • 異常しきい値: 3 以上 (3 以上に設定するのが理想的です。これにより、発生頻度の低いネットワークパケットの損失などの障害による影響を回避できます)
      • 正常しきい値: 2 (多くの場合、値 2 で十分です)
      • タイムアウト:予想されるレスポンス時間の 5 倍以上の十分な値 (これにより、ビジー状態のインスタンスや低速のネットワーク接続などの予期しない遅延による影響を回避できます)
      • チェック間隔: 1 秒からタイムアウトの 2 倍までの値 (値が長すぎると、失敗したインスタンスがすぐに捕捉されません。値が短すぎると、毎秒かなりの数のヘルスチェック プローブが送信されるため、インスタンスとネットワークがビジー状態になる可能性があります)
    • Cloud Load Balancing 
      • フロントエンドの構成
      • バックエンドの構成
        • ヘルスチェック:インスタンス グループで指定した「自動修復」のヘルスチェックとは別のヘルスチェックを指定
        • セッションアフィニティ:作成した Cookie
        • コネクションのドレインタイムアウト:300
      • Cloud SQL ( MySQL )
        • ストレージの種類 : SSD
        • ストレージの自動増量を有効化:オン
        • バックアップを自動化する : 有効
        • ポイントインタイムリカバリを有効にする : オン
        • 可用性 :高可用性 (リージョン)
        • 優先ウィンドウ : インスタンスの定期メンテナンスを行うのに最適な曜日を設定
        • 更新の順序 : 格納されるデータに応じた優先度を設定 

このパターンで作成された事例

関係するデザインパターン

参照文献

キャッシュを活用したウェブホスティング

解決する課題・使い所

ウェブ アプリケーションはウェブサーバ(多くの場合アプリケーション サーバを兼ねるため、本章では「ウェブサーバ」と総称)を中心として、様々なサーバと連携して動作します。また、時として多大な負荷の原因となる大量のアクセスの矢面に立つ必要があります。しかしながら、従来のインフラではこういった大量のアクセスに対応しきれずにサイトがダウンしてしまったり、スループットが著しく低下するといった課題があります。

これに対してキャッシュを有効に活用することで、ウェブサーバが処理すべきトラフィックを最小化することや、連携するデータベースサーバ等のバックエンド(本章では、これらを便宜上「バックエンド」と総称)がボトルネックとならないよう、バックエンドへのリクエストを緩和することが可能となります。 

ここでは、用途に応じてキャッシュを活用したアーキテクチャの例を解説します。

アーキテクチャ

キャッシュの導入が有効なポイントは大きくわけて以下の 2 箇所が考えられます。

  1. コンテンツ キャッシュ/コンテンツ配信ネットワーク(CDN) 
    ウェブサーバの前段に、画像やスタイルシート、JavaScript 等の静的コンテンツをキャッシュし、代理応答するコンテンツ配信ネットワークを配置します。Google Cloud では、Cloud CDN がこれに相当します。
  2. インメモリ キャッシュ
    アプリケーションがデータベースなどのバックエンドに対して発行するクエリの内、実行頻度が高く実行結果が共通するクエリの実行結果を、バックエンド(特に一般的なリレーショナルデータベース)へのクエリに比べ高速に応答することが見込まれる インメモリ キャッシュに格納し、アプリケーションからのクエリ先として機能させます。Google Cloud では、インメモリ キャッシュのマネージド サービスとして Memorystore を提供しています。現在は Redis が一般利用可能であり、Memcached もベータ提供が始まっています(2020 年 10 月 7 日現在)。 
architecture

利点

  1. CDN によってウェブ アプリケーションサーバの負荷を軽減することができます。 
  2. インメモリ キャッシュの適切な活用によりデータベースが処理するクエリの量を減らすことができるため、データベースの負荷軽減を図ることができるほか、データベースのクエリ応答より一般的に高速な応答が見込まれるインメモリ キャッシュから応答することにより、アプリケーション全体のスループットの向上が見込めます。 

Sample config や Code(提供可能な場合) 

  • Cloud CDN を導入する場合 (上図 (1))
    • 紐付けるHTTP(S) 負荷分散を指定します。該当する HTTP(S) 負荷分散が未作成の場合、ここで新しく作成することも出来ます。
    • HTTP(S) 負荷分散と Cloud CDN を紐付ける方法は複数あり、Cloud CDN のメニューから HTTP(S) 負荷分散を選択して紐付ける方法、HTTP(S) 負荷分散のバックエンド サービスやバックエンド バケットを作成する際に Cloud CDN を有効化することも可能です。
    • TCP 負荷分散 や UDP 負荷分散 では Cloud CDN を有効化することが出来ません。 
  • Memorystore for Redis を導入する場合 (上図 (2))
    • Memorystore のネットワーク スループットはメモリ容量に応じて増減するため、必要な容量だけではなくボトルネックの影響を受けずに応答することが出来るネットワーク スループットを確保するよう、適切に容量を設定する必要があります。
memorystore
    • Memorystore インスタンスを配置するプロジェクトとリージョンは必ずアクセス元である Compute Engine のインスタンスと合わせる必要があります。また、この Compute Engine インスタンスが所属する VPC からの接続を許可する必要があり ます。

注意事項

  • システム全体を見据えたパフォーマンス改善: 必ずしも特定の一点のみを改善すればよいというわけではなく、ウェブ サーバ側の負荷を緩和することでより多くのリクエストを処理できるようになった結果、バックエンドに今まで以上の負荷がかかってしまい、結果的にバックエンドがボトルネックとなってアプリケーション全体の性能に悪影響を及ぼすこともあります。このため、アプリケーションに要求される性能やアクセス特性などの非機能要件を明確にしたうえでボトルネックとなりうる箇所を特定し、ある箇所の性能向上が他の箇所の負荷に与える影響を考慮した上で適切に各所の改善に着手する必要があります。 必ずしも特定の一点のみを改善すればよいというわけではなく、ウェブ サーバ側の負荷を緩和することでより多くのリクエストを処理できるようになった結果、バックエンドに今まで以上の負荷がかかってしまい、結果的にバックエンドがボトルネックとなってアプリケーション全体の性能に悪影響を及ぼすこともあります。このため、アプリケーションに要求される性能やアクセス特性などの非機能要件を明確にしたうえでボトルネックとなりうる箇所を特定し、ある箇所の性能向上が他の箇所の負荷に与える影響を考慮した上で適切に各所の改善に着手する必要があります。 
  • キャッシュの適切な有効期限の設定: Cloud CDN では格納されているキャッシュに有効期限を設定できます。コンテンツの更新頻度などの特性に合わせて有効期限を適切に設定することが重要です。例えば、ほぼリアルタイムに更新されるようなコンテンツのキャッシュ有効期限を長く設定してしまうと、オリジン側でコンテンツが更新されているにもかかわらず、CDN が応答するキャッシュ コンテンツは古い状態のまま、といったような予期せぬ応答結果を招いてしまうことがあります。反対に、滅多に更新されない種類のコンテンツのキャッシュ有効期限を短く設定してしまうと、その必要が無いにもかかわらず頻繁にオリジンへのリクエストが発生してしまい期待した負荷軽減効果やコストメリットを享受できないといった弊害が生まれることがあります。
  • キャッシュできるコンテンツ: 静的なコンテンツであれば無条件にキャッシュに保存されるわけではなく、キャッシュに保存されるにはドキュメントに記載されている要件を満たす必要があります。
  • Cloud CDN の設定:Cloud CDN の設定は単体で行うのではなく、HTTP(S) 負荷分散の設定と合わせて行うことで、HTTP(S) 負荷分散の特徴であるグローバルなエニーキャスト IP アドレス等の恩恵を受けることができます。
  • キャッシュの永続化: Memorystore for Redis の基本階層ではメンテナンスやインスタンスのスケーリングの際などにキャッシュがフラッシュされます。キャッシュのフラッシュを避けるためにはフェイルオーバー機能を備える標準階層を利用できます。また、Memorystore for Redia はオープンソース Redis の機能のうち、エクスポート機能によるスナップショットは使えますが、AOF 永続化によるキャッシュの永続化はサポートしていません。
  • アプリケーション実装への変更: データベースへのクエリ結果のキャッシュとして Memorystore を利用する場合、これらバックエンドへ問い合わせを行うアプリケーションの実装に修正を加える必要があります。

このパターンで作成された事例

参照文献