表示を早くする:レンタルサーバーで実現するサーバー負荷分散

by

in

Webサイトの表示が遅い。これは誰もが経験する問題です。

施策が上手くいってアクセスが増えたのは良かったが、表示が遅くなってしまった。デザインを変更したが表示が遅くなってしまった。新しく契約したサーバーがなんだか重い。

理由は様々ですが、自社が運営しているWebサイトの表示が遅いと一大事です。

この記事では、レンタルサーバーを運用しているITエンジニアやデザイナー、小規模事業者の方々に向けて、Webサイトの表示を早くするためのサーバー負荷分散の具体的な方法とその利点を解説します。

プロキシサーバーの導入や静的ファイルのURLを分ける手法を中心に、サーバーの負荷を分散し、システムの安定性とパフォーマンスを向上させる方法を詳しく紹介します。

上位プランへの契約見直し

まずは本末転倒かもしれませんが、契約プランの見直しをする事をオススメします。

レンタルサーバーを契約する利点としては、サーバー管理を外部委託することで本来の業務に注力できる事です。複雑なサーバー構成や負荷分散についての知識、適切なキャッシングを管理してくれる対価としてレンタルサーバーの使用量を払っています。

言うなれば負荷分散をする仕事はレンタルサーバー事業者であり、契約して使用している私達は動いているWordPressなどのアプリケーション層だけを管理することに注力すべきです。

よりサービスレベルが高いプランへの変更や、専用サーバーへの移行などを検討することで適切な負荷分散が行われている環境へアップグレードするのが得策かと考えます。

これから解説する内容はそれでも負荷分散を自社で行いたい、もしくはWebサイトのアクセス速度を向上する方法論を理解したい人に向けての解説を行っていきます。

プロキシサーバーの導入

プロキシサーバー、つまりリバースプロキシは、クライアントのリクエストを受け取り、それをオリジンサーバーに転送する中継役を担います。

今までは直接 WordPress などのアプリケーションが動いているサーバーにアクセスしていましたが、中継役として機能するサーバーを間に挟む構成です。

一見、中継役のサーバーを追加することで遅くなってしまうのではないかと感じてしまいますが、いくつかの利点が存在します。

  • 負荷分散
    • アプリケーションを動かすサーバーを複数作る事ができます。
    • 複数のオリジンサーバーにリクエストを分散し、各サーバーの負荷を均等にする。
    • これにより、特定のサーバーに過度な負荷がかかるのを防ぎ、全体的なシステムのパフォーマンスを向上させます。
  • キャッシング
    • 静的コンテンツをキャッシュし、オリジンサーバーへのリクエストを減少させる。
    • 最初はオリジンサーバーにアクセスをするのですが、静的コンテンツのような変化しないものはプロキシサーバーから配信します。
    • 静的コンテンツとは 画像、CSS、JavaScriptファイルなど のWebサイトでもっとも読み込まれる回数が多い物です。
  • SSL終端
    • SSL/TLSの暗号化・復号化をプロキシサーバーで行い、オリジンサーバーの負荷を軽減する。
    • オリジンサーバーでの処理を少なくし、アプリケーションの生成のみに注力させます。
  • セキュリティ強化
    • クライアントから直接オリジンサーバーにアクセスさせないことで、攻撃リスクを低減する。

リバースプロキシを導入することで、Webアプリケーションはより高いパフォーマンスと可用性を実現でき、ユーザー体験の向上に寄与します。

しかし、これらの利点はオリジンサーバーのみでも対応しているレンタルサーバー業者さんもあります。例えばエックスサーバーではサーバーキャッシュ としてキャッシングの処理が提供されているため、ご利用のレンタルサーバーの機能をご確認ください。

静的ファイルのURLを分ける

静的ファイル(画像、CSS、JavaScriptなど)を専用のサーバーで配信することで、アプリケーションサーバーの負荷を大幅に軽減できます。

この手法では、静的コンテンツを配信するために別のサーバーを用意し、そのURLを使用します。URLを分けるというのがポイントで、利点としては以下になります。

  1. ブラウザの同時接続数の増加
    • 多くのブラウザは同じドメインに対して同時に開ける接続数に制限があります。
    • 静的ファイルを別ドメインで配信することで、この制限を回避し、同時により多くのファイルをダウンロードできるようになります。
  2. キャッシュの効率化
    • 静的ファイル(画像、CSS、JavaScriptなど)は通常変更されないため、長期間キャッシュすることが望ましいです。
    • 別ドメインで配信することで、動的コンテンツ(HTMLなど)と静的コンテンツのキャッシュポリシーを分けて設定しやすくなります。
  3. Cookieの送受信の削減
    • メインドメインに設定されているCookieはすべてのリクエストに含まれます。
    • ですが、静的ファイルを配信する別ドメインではCookieを除外することで、リクエストサイズを小さくし、パフォーマンスを向上させることができます。
  4. セキュリティの向上
    • 静的ファイルを別ドメインで配信することで、CORSポリシーを適切に設定し、セキュリティを強化することができます。
  5. CDNの効果的な利用
    • 静的ファイルを別ドメインで配信することで、CDNを簡単に設定しやすくなります。
    • CDNを利用することで地理的に分散したエッジサーバーからコンテンツを配信することが出来るので、ユーザーのアクセス速度を向上させることができます。

物によっては htaccess やアプリケーション設定を適切に変更することでサーバー負荷分散を可能にしますが、URLを分ける事で設定しやすくなります。

URLを分ける方法としては

  • エッジキャッシュ型CDNを活用
    • 前述のプロキシサーバーのような構成
    • エッジキャッシュ型CDNを経由してアプリケーションが実行される
    • Cloudflare や AWS CloudFront の活用
  • 静的ファイルを配信する専用サーバーにファイルを設置
    • AWS S3 の活用や、FTPを使用した別サーバーへのアップロード

が考えられます。

CDNを活用した静的ファイル配信

ここでは大まかなCDNの設定方法を解説していきます。実際の設定方法はCDNプロバイダーによって変わりますが、概要や設定する際の流れをまとめていきます。

先におさらいすると、CDN(コンテンツデリバリーネットワーク)の利点としては、静的ファイルを地理的に分散されたエッジサーバーから高速に配信できます。

これにより、ユーザーに近い場所からコンテンツが配信されるため、ロード時間が短縮され、全体的なパフォーマンスが向上します。

また、CDNを利用する流れを設定するだけで静的ファイルを配信する専用サーバーなども不要になるため、URLを分けるお手軽な方法と言えます。

  1. CDNプロバイダーの選定と登録
    • Cloudflare、AWS CloudFront、Google Cloud CDNなどのCDNプロバイダーを選択し、アカウントを作成します。
  2. CDN設定
    • CDNプロバイダーの管理画面で、新しいCDNディストリビューションを作成し、静的ファイル専用のサブドメインを設定します。
    • オリジンサーバーとして、静的ファイル専用サーバーまたはオリジンサーバーを指定します。
  3. DNS設定
    • 静的ファイル専用のサブドメイン(例:static.example.com)をCDNのエッジサーバーにポイントします。
  4. アプリケーションの設定変更
    • 静的ファイルのURLをCDNのURLに変更します。
<link rel="stylesheet" href="https://cdn.example.com/css/style.css">
<script src="https://cdn.example.com/js/app.js"></script>
<img src="https://cdn.example.com/images/logo.png" alt="Logo">

CDNへのキャッシュ設定

静的ファイルをキャッシュすることでリクエストのたびにオリジンサーバーにアクセスする必要がなくなり、サーバー負荷が軽減されます。

CDNに対して、適切なキャッシュ設定を行うことでコンテンツの配信速度が向上し、ユーザー体験が向上します。

例えば、.htaccessファイルで以下のようなキャッシュヘッダーを設定します。

<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresByType image/jpg "access plus 1 year"
    ExpiresByType image/jpeg "access plus 1 year"
    ExpiresByType image/gif "access plus 1 year"
    ExpiresByType image/png "access plus 1 year"
    ExpiresByType text/css "access plus 1 month"
    ExpiresByType application/pdf "access plus 1 month"
    ExpiresByType text/x-javascript "access plus 1 month"
    ExpiresByType application/x-shockwave-flash "access plus 1 month"
    ExpiresByType image/x-icon "access plus 1 year"
</IfModule>

<IfModule mod_headers.c>
    <FilesMatch "\.(ico|jpg|jpeg|png|gif|swf|css|js)$">
        Header set Cache-Control "max-age=31536000, public"
    </FilesMatch>
</IfModule>

CDNに対するキャッシュ指示はCDNプロバイダーやプロキシサーバーによって変わりますが、共通する物としては Cache-Control が重要になります。以下を参照ください。

Cache-Control は HTTP のヘッダーフィールドで、 キャッシュ をブラウザーや共有キャッシュ(プロキシーや CDN など)において制御するためのディレクティブ (指示) を、リクエストとレスポンスの両方で保持します。

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Cache-Control

キャッシュには大まかに

  • プライベートキャッシュ
    • ユーザー個人に対するキャッシュ
  • 共有キャッシュ
    • サーバー内で複数のユーザーに活用されるキャッシュ

が存在し、CDNへのキャッシュ設定は共有キャッシュになります。これらを適切に理解、設定していかないと意図しない情報の公開に繋がるため注意が必要です。

しかし、これらの設定を行うことで静的ファイルの配信が最適化され、アプリケーションサーバーの負荷が大幅に軽減されます。

データベースの負荷分散

WebサイトはHTMLのみで公開することもできますが、管理の効率化や表示する内容ではデータベースを活用する必要があります。

このデータベースは大量のデータから目的の物を取得するため、運用していくことで次第に負荷が高まるため表示速度が遅くなる原因となります。

ここではデータベースによる表示速度の遅延を解消する方法を軽く紹介していきます。実際の設定方法については省略しているため、必要に合わせてチャレンジしてみてください。

リードレプリカの導入

リードレプリカは、データベースの負荷を分散するための効果的な手法の一つです。

リードレプリカを導入することで、データベースの読み取りリクエストを複数のレプリカに分散させ、オリジナルのデータベース(マスター)の負荷を軽減できます。

構成としては

  • マスター
    • 書き込み専用のデータベース
  • スレーブ
    • 読み込み専用のデータベース

となっており、1つのデータベースサーバーにアクセスが集中することなく、負荷分散を実現することができます。

マスターに書き込まれた内容は即座にスレーブに反映され、通常はスレーブが複数台設定される事になります。

データベースシャーディングの利点

データベースシャーディングは、大規模なデータセットを複数のデータベースに分割する手法です。

前述のリードレプリカはマスターとスレーブで全て同じ内容が共有されますが、シャーディングではそれぞれのデータベースに分割されて管理されていきます。

各シャードは特定のデータセットを保持し、負荷を均等に分散します。

  • スケーラビリティ
    • データベースのサイズが大きくなるにつれて、シャードを追加することでスケールアウトが可能。
  • パフォーマンス向上
    • 各シャードに対するクエリ数が減少するため、パフォーマンスが向上。
  • 可用性の向上
    • 一部のシャードがダウンしても、他のシャードは引き続き動作するため、システム全体の可用性が向上。

実装をするためには以下のポイントが重要です。

  • シャーディングキーの選定
    • データをどのように分割するかを決定するために、シャーディングキーを選定します。一般的にはユーザーIDなどを使用。
  • シャードマッピング
    • シャーディングキーに基づいて、どのシャードにデータを配置するかを決定します。
  • アプリケーションの変更
    • データベース接続部分を変更し、シャーディングキーに基づいて適切なシャードに接続するようにします。

高可用性を実現するデータベース設計

高可用性とはサービス提供が出来なくなる事態の発生頻度が少ないことを指します。ここでは速度を上げるための負荷分散ではなく、システムとして正常に稼働するための負荷分散を提案します。

高可用性を実現するためには、データベースの冗長性とフェイルオーバーの仕組みを導入する必要があります。

  1. レプリケーションの設定
    • リードレプリカに加えて、マスター-マスターレプリケーションを設定することで、フェイルオーバーを自動化します。各マスターが他のマスターに対してレプリケーションを行うことで、どちらかがダウンしてももう一方が引き続き動作します。
  2. フェイルオーバーの設定
    • フェイルオーバーを自動化するために、管理ツール(例:MHA、Orchestrator)を使用します。これにより、マスターサーバーがダウンした場合に自動的にリードレプリカを昇格させます。
  3. バックアップとリストア
    • 定期的なバックアップを実施し、迅速なリストアが可能な体制を整えます。これには、データベースのフルバックアップと増分バックアップを組み合わせる方法が有効です。
  4. 監視とアラート
    • データベースの監視を強化し、異常が検出された場合に即座にアラートを受け取る仕組みを導入します。これにより、問題発生時に迅速に対応できます。

これらの方法を組み合わせることで、データベースの負荷を効果的に分散し、高可用性とスケーラビリティを実現することができます。

レンタルサーバー環境ではあまり活用が出来ない部分もありますが、これらの手法は今後のシステム移転などの際に活用することで信頼性の高いシステムを構築できます。

アプリケーションレイヤーでの負荷分散

タスクキューを利用した非同期処理

タスクキューもしくはキューイング処理は、バックグラウンドタスクを非同期で処理するためのメカニズムです。

これにより、アプリケーションサーバーのリクエスト処理の負荷を分散し、応答時間を短縮することができます。

キューイング処理は常駐プロセスを立ち上げて実行するのが定石ですが、レンタルサーバーでは常駐プロセスを立ち上げるのは推奨されません。

ですが、crontabの設定は認められているため、cronをうまく使う事で実現することが可能となります。Laravelでの実装方法を例にこちらの記事でまとめています。

マイクロサービスアーキテクチャの導入

マイクロサービスアーキテクチャは、アプリケーションを複数の小さなサービスに分割する手法です。

各サービスは独立してデプロイおよびスケールすることができ、異なる技術スタックを使用することも可能です。

以下に、マイクロサービスでの運用をするメリットをまとめていきます。

  1. サービスの分割
    • アプリケーションを機能ごとに分割し、各機能を独立したサービスとして定義します。例えば、ユーザー管理、注文処理、支払い処理などのサービスに分けます。
  2. APIゲートウェイの設定
    • 各マイクロサービスへのリクエストを管理するために、APIゲートウェイを設定します。APIゲートウェイは、リクエストを適切なサービスにルーティングし、認証やレート制限などの共通機能を提供します。
  3. サービス間通信
    • マイクロサービス間の通信には、REST APIやgRPCを使用します。メッセージングキューを利用することで、非同期通信も可能です。
  4. 独立したデプロイ
    • 各サービスを独立してデプロイできるように設定し、必要に応じてスケールします。これにより、特定のサービスに負荷が集中しても、他のサービスに影響を与えません。

要するにアプリケーションで提供されるサービスを分割し、別サーバーで運用。サービス間の処理はAPIを実行して繋ぎ合わせる事で負荷分散を実現します。

マイクロサービスアーキテクチャの利点を最大限に活用するためには、各サービス間の負荷分散とスケーリングを効果的に行う必要があります。

  1. 負荷分散の設定
    • 各サービスに対するリクエストを分散するために、ロードバランサーを使用します。ロードバランサーは、リクエストを複数のインスタンスに均等に分配します。
    • AWS ELB(Elastic Load Balancing)やNGINXなどのツールを使用します。
  2. 自動スケーリング
    • サービスの負荷に応じて、自動的にインスタンスをスケールアウトおよびスケールインするための設定を行います。
    • AWS Auto ScalingやKubernetesのHorizontal Pod Autoscalerを使用します。
  3. モニタリングとアラート
    • 各サービスのパフォーマンスをモニタリングし、異常が検出された場合にアラートを設定します。これにより、問題が発生した際に迅速に対応できます。
    • PrometheusやGrafanaなどのツールを使用します。
  4. フェイルオーバーの設定
    • サービスがダウンした場合に、自動的に他のインスタンスにフェイルオーバーする設定を行います。これにより、高可用性を確保します。

これらの方法を組み合わせることで、アプリケーションの負荷を効果的に分散し、スケーラビリティと高可用性を実現することができます。

アプリケーションそのものを分割する方法を紹介しました。これ以外にもスポットでレンタルサーバーで実現できない機能、ブラウザ立ち上げでのスクレイピングをAWS Lambdaで実装した経験をまとめた記事もあるので、こちらもマイクロサービスの運用で参考になるかと思います。

レンタルサーバー環境でも、これらの手法を活用することで、信頼性の高いシステムを構築できます。

負荷分散のベストプラクティス

以上で、負荷分散をする方法について紹介しました。これ以外にもある場合にはコメント欄に書き込んでいただけると大変ありがたく思います。

次に負荷分散をすべきタイミングを把握するために日々の取り組むべき事や、検討すべき点についてまとめていきます。

モニタリングとパフォーマンスチューニング

負荷分散を効果的に行うためには、システムのパフォーマンスを常にモニタリングし、必要に応じてチューニングすることが重要です。

以下は、モニタリングとパフォーマンスチューニングをするためのトピックになります。

  1. モニタリングツールの導入
    • システムの状態をリアルタイムで監視するために、適切なモニタリングツールを導入します。Prometheus、Grafana、New Relicなどのツールが一般的です。
    • 各サービスのメトリクス(CPU使用率、メモリ使用率、リクエスト数、エラーレートなど)を収集し、ダッシュボードで視覚化します。
  2. アラート設定
    • システムに異常が発生した際に、迅速に対応できるようにアラートを設定します。閾値を設定し、特定のメトリクスが閾値を超えた場合に通知を受け取るようにします。
  3. パフォーマンスチューニング
    • 定期的にシステムのパフォーマンスをレビューし、ボトルネックを特定します。必要に応じて、コードの最適化、データベースのインデックス作成、キャッシュの導入などを行います。
    • ロードテストを実施し、負荷がかかったときのシステムの挙動を確認します。Apache JMeterやLoadRunnerなどのツールを使用します。

フェイルオーバーと冗長性の確保

システムの可用性を高めるためには、フェイルオーバーと冗長性を確保することが重要です。

事前に検討しておくべき点であり、これにより障害が発生した場合でもシステムのダウンタイムを最小限に抑えることができます。

  1. 冗長構成の設計
    • 各コンポーネント(Webサーバー、アプリケーションサーバー、データベースなど)を冗長化します。
    • 複数のインスタンスを用意し、負荷分散を行うことで、一部のインスタンスがダウンしても他のインスタンスがサービスを継続します。
  2. 自動フェイルオーバーの設定
    • フェイルオーバーを自動化するために、管理ツールを使用します。例えば、データベースの場合、MHAやOrchestratorを使用して自動フェイルオーバーを設定します。
    • アプリケーションレイヤーでは、ロードバランサーを使用してフェイルオーバーを実現します。AWS ELBやNGINXのロードバランサー機能を活用します。
  3. バックアップとリカバリ
    • 定期的なバックアップを行い、迅速にリカバリできる体制を整えます。フルバックアップと増分バックアップを組み合わせて実施し、データの整合性を確保します。
    • ディザスタリカバリプランを策定し、災害時に迅速に対応できるように準備します。

実際の運用でのトラブルシューティング

運用中に問題が発生した場合、迅速にトラブルシューティングを行うことが重要です。

以下は、実際の運用で役立つトラブルシューティングの手法です。

  1. ログの分析
    • 各コンポーネントのログを収集し、分析します。ログ管理ツール(例:ELKスタック、Graylog)を使用して、ログの可視化と検索を容易にします。
    • エラーログや警告ログを確認し、問題の原因を特定します。
  2. システムの状態確認
    • モニタリングツールを使用して、システムの現在の状態を確認します。異常が発生しているメトリクスを特定し、対応策を講じます。
    • リソースの使用状況(CPU、メモリ、ディスクI/Oなど)を確認し、リソース不足が原因でないかをチェックします。
  3. 問題の切り分け
    • 問題の発生箇所を特定するために、各コンポーネントを個別に確認します。ネットワーク、アプリケーション、データベースなど、各層での問題を順番に切り分けます。
    • テスト環境で再現テストを行い、問題の再現性を確認します。
  4. 修正と再発防止
    • 問題の原因を特定したら、迅速に修正を行います。修正後、同様の問題が発生しないように再発防止策を講じます。
    • 修正内容をドキュメント化し、他のチームメンバーと共有します。

これらのベストプラクティスを実践することで、負荷分散を効果的に行い、システムのパフォーマンスと可用性を維持することができます。

レンタルサーバー環境でも、これらの手法を活用して、高信頼性のシステムを構築し、運用することが可能です。

最後に:負荷分散の重要性と将来の展望

負荷分散は、現代のウェブアプリケーションやサービスにおいて不可欠な技術です。

適切な負荷分散を行うことでシステムのパフォーマンス向上、可用性の確保、スケーラビリティの向上が実現できます。

特に、ユーザー数やトラフィックが急増する状況においても、安定したサービス提供を維持するためには負荷分散の実装が欠かせません。

負荷分散の重要性

ここれはサーバー負荷分散をするための目的をおさらいします。逆にこれらを解決できない負荷分散は実施しないように注意していきましょう。

  1. パフォーマンス向上
    • リクエストを複数のサーバーに分散することで、各サーバーの負荷を軽減し、レスポンス時間を短縮します。
  2. 可用性の確保
    • 冗長性を持たせることで、一部のサーバーがダウンしても他のサーバーがバックアップとして機能し、サービスの継続性を確保します。
  3. スケーラビリティの向上
    • トラフィックの増加に応じてサーバーを追加することで、システム全体のキャパシティを柔軟に拡張できます。

将来の展望

今後の負荷分散技術は、より高度で自動化されたソリューションへと進化していくと考えられます。

以下のような技術トレンドが期待されます

  1. 自動スケーリング
    • クラウドサービスを利用した自動スケーリングが一般化し、需要に応じて動的にリソースを調整する仕組みが標準となるでしょう。
  2. CDN活用
    • CDNを活用することで、ユーザーに近い場所でデータ処理を行い、さらに高速なレスポンスを提供します。
  3. AIと機械学習の活用
    • AIや機械学習を利用して、トラフィックパターンを予測し、自動で最適な負荷分散設定を行うシステムが普及するでしょう。
  4. マルチクラウド戦略
    • 複数のクラウドサービスプロバイダーを組み合わせたマルチクラウド戦略により、リソースの最適化と高可用性を実現します。

これらの技術を活用することで、より効率的で柔軟な負荷分散を実現し、次世代のウェブサービスを支える基盤を構築していくことが期待されます。

レンタルサーバー環境においても、これらの技術を積極的に導入し、進化するニーズに対応することが重要です。

レンタルサーバーを最大限使いこなすための方法

Laravelの記事を厳選して紹介

投稿者


Comments

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA