クラシル開発ブログ

クラシル開発ブログ

10分で完成!WEBサイトパフォーマンス計測基盤 ver.2019

f:id:gomesuit:20191214231124p:plain

はじめに

本記事は dely Advent Calendar 2019 の15日目の記事です。

昨日は開発部サーバサイドエンジニアの高橋くんが「Rails6の複数データベースの仕組みと実装時にハマったところ」という記事を書きましたので是非読んでみてください。

tech.dely.jp

こんにちは!dely開発部SREの井上です。 本記事ではWEBサイトのパフォーマンスを定期的に計測する仕組みについて紹介をしたいと思います。

実は去年のAdvent Calendarでも同じような記事を書いたのですが、時代背景に沿って計測するツールをsitespeed.ioからLighthouseに変更したので理由も含めて紹介させてください。

基盤の構築においては下記のサービスやツールを利用しています。

  • AWS
    • CodeBuild
    • S3
    • Athena
  • Terraform
  • Lighthouse

前置きはいいから構築方法だけ知りたいという方は こちら にどうぞ!

目次

WEBサイトのパフォーマンスについて

もう今さら言うことでもないと思いますが、WEBサイトのパフォーマンスはユーザ体験に大きく影響を与えます。

直近(2019/12/10)でも下記のような記事をGoogleが公開しています。

developers-jp.googleblog.com

Chromeブラウザにおいて読み込みが速いサイトと遅いサイトを見分けるためのバッジが将来的に付けることを検討しているという内容ですが、サイトの読み込み速度をより一層ユーザとサービス提供者に意識させようという意思を感じます。

上記のような動きもあり、今後もWEBサイトのパフォーマンスを重視する傾向は変わることはないだろうと個人的には予想しています。

WEBサイトのパフォーマンスの計測手段

WEBサイトのパフォーマンスは重要だという話ですが、改善を行うためにもまずは現状を計測する必要があります。 2019年12月現在、WEBのパフォーマンスを計測する主な手段としては下記のようなものが存在します。

Google自身もパフォーマンス計測ツールについてまとめているので興味があれば見てみてください。とても参考になります。

developers.google.com

定期的に計測することの必要性について

WEBのパフォーマンスにおいてボトルネックを特定するだけであれば、その時点で数回の計測を実施すればよいですが、対策に伴う効果測定をしたい場合は対策後に再度計測を実施する必要があります。複数の対策を長期的に実施していく場合などは、対策を行う度に計測しなおす必要があります。

また、上記とは反対に何かのタイミングで意図せずパフォーマンスが悪くなっていないかを検知したいときやパフォーマンスが悪化した前後で何が原因だったのかなどを遡って確認したいこともあります。

上記のような要件を満たすためには、一定間隔で繰り返しWEBパフォーマンス計測を実施する必要があります。

定期的なWEBパフォーマンス計測について

定期計測における要件は下記のようになると考えます。

  • 一定の条件下において指標の変動を可視化することが可能

    • 計測する環境(例えばPCの性能やネットワーク環境)が起因して計測値がずれてしまうのであれば、何が原因で指標が上下しているのか正しく分からなくなるため、一定の条件化で計測し続けることが必要です。
  • パフォーマンスの問題のデバッグが可能

    • パフォーマンスが劣化したと考えられるタイミングにおいて、例えば問題がcssにあるのかjsにあるのかサーバのレイテンシにあるのかなどといった原因分析を可能とする指標が記録されているべきです。
  • ユーザ体験に関連するさまざまな指標が計測可能

    • ときにはリスク込みでパフォーマンスを犠牲にしなければいけない選択をする場合もあると思います。そういった選択をできるようにしておくためにも、パフォーマンスの劣化がどれだけユーザ体験に影響を与えているのかということも指標として記録できている必要があります。

定期計測において重要なのは「指標の変動が分かり」、「変動の原因がどこにあるのか明確にできること」だと考えます。

逆に言えば定期のパフォーマンス計測においては上記の要件を満たせば成り立つため、詳細なボトルネックの原因分析などを行うタイミングのパフォーマンス計測とは計測ツールを分けても問題ないと考えます。

定期計測に適したパフォーマンス計測ツールについて

2019年12月現在においてはLighthouse一択だと思っています。

LighthouseはGoogleがオープンソースで開発・公開しているWeb開発向けの診断ツールです。 下記のさくらのナレッジさんの記事が非常に詳しく解説してくれているのでこちらをご参照ください。

knowledge.sakura.ad.jp

WEBサイトのパフォーマンスを手軽に計測するためにGoogleが提供しているサービスがPageSpeed Insightsになりますが、PageSpeed Insightsの分析エンジンにはLighthouseが利用されていることがGoogleによって公開されています。

webmaster-ja.googleblog.com

WEBサイトのパフォーマンスを向上することの目的は当然ユーザ体験になるべきですが、その前段としてSEOが語られることは少なからずあると思います。そういったときは大抵の場合、指標のマスターとしてPageSpeed Insightsが挙げられます。定期計測において計測する指標や数値は可能な限りPageSpeed Insightsのものと一致させておいたほうが意思決定の根拠として扱いやすいのは間違いありません。

その証拠として前述で挙げているツールのほとんどが内部でLighthouseを利用する手段を用意しています。

www.sitespeed.io

www.webpagetest.org

去年の記事においてはsitespeed.ioを測定ツールとして採用しましたが、上記の理由からLighthouseを使った計測にリプレースしました。

定期計測に適したパフォーマンス計測手法について

定期計測においては前述の通り計測する環境に左右されないことが必須になるため、ローカルPCの環境に依存するツールを用いた測定手法は適していません。また人間が定期的にツールを実行するのは現実的ではないため、自動で定期的にツールが実行される仕組みが必要になります。

計測ツールにLighthouseを使う場合でも、Lighthouseを「計測する環境に左右されず」かつ「自動で定期的に動作させる」ための機構は別途考える必要があります。

PageSpeed Insights API について

PageSpeed Insights API を使うことで環境に左右されずLighthouseによる計測を行うことが可能です。

developers.google.com

PageSpeed Insights API については低頻度であれば、利用するにあたってAPIキーすら不要なため非常に手軽に使えます。しかし、Lighthouseの設定が出来ないため、例えばPCとmobileの二通りで計測したり、ユーザエージェントをカスタマイズして計測したりといったユースケースに合わせたカスタマイズが出来ないことがデメリットとして挙げれれるため今回は採用していません。

WEBパフォーマンス計測に特化した有料外部サービスについて

最近はLighthouseが組み込まれた有料サービスが出てきています。

こういったサービスを使えば「計測する環境に左右されず」かつ「自動で定期的に動作させる」を達成することが可能そうです。(使ったことがないので明確には言えません)

とても便利そうですがもちろん利用料がかかります。そもそも使ったことがなく評価出来ていないので検討の余地はありますが、今回はそこまで出来ていないので今後の課題にしようと思います。

calibreapp.com

speedcurve.com

Lighthouseを「計測する環境に左右されず」かつ「自動で定期的に動作させる」ための機構

やっと本題になりますが、Lighthouseを「計測する環境に左右されず」かつ「自動で定期的に動作させる」ための機構をAWSを使って考えてみました。

f:id:gomesuit:20191214200841p:plain

  • CodeBuild

Lighthouseを実行する実行環境として利用します。 CloudWatchEventによって定期的に動作します。

  • S3

Lighthouseによる計測結果の格納と、HTMLのホスティングとして利用します。

  • Athena

S3に格納された計測結果に対してSQLを実行するために利用します。

  • 可視化ツール

Athenaをデータソースとしてグラフ化などを行います。 可視化ツールに何を使うのかまではこの記事内には記載しませんが、delyではRedashを利用しています。

可視化例

delyでは例えば下記のSQLを実行することによって、

SELECT 
    'https://webperf-by-codebuild-58b94c1bbe1c0755.s3-ap-northeast-1.amazonaws.com/html/' || DOMAIN || '/' || device || '/' || category || '/' || YEAR || '/' || MONTH || '/' || DAY || '/' || hour || '/' || MINUTE || '/output.report.html' as link,
    DOMAIN,
    device,
    category,
    YEAR,
    MONTH,
    DAY,
    hour,
    MINUTE,
    CAST(YEAR || '-' || MONTH || '-' || DAY || ' ' || hour || ':' || MINUTE as timestamp) AS time,
    metrics.details.items[1].speedIndex / 1000.0 as speedIndex,
    metrics.details.items[1].firstContentfulPaint / 1000.0 as firstContentfulPaint,
    metrics.details.items[1].firstMeaningfulPaint / 1000.0 as firstMeaningfulPaint,
    categories.performance.score * 100 as performance_score,
    categories.accessibility.score * 100  as accessibility_score,
    categories."best-practices".score * 100  as best_practices_score,
    categories.seo.score * 100 as seo_score
FROM
    "<Terraformによって生成されたデータベース>"."lighthouse"
where
    DOMAIN = '{{ domain }}' and device = '{{ device }}' and category = '{{ category }}'
    AND CAST(YEAR || '-' || MONTH || '-' || DAY || ' ' || hour || ':' || MINUTE as timestamp) >= current_timestamp - interval '1' month
    order by CAST(YEAR || '-' || MONTH || '-' || DAY || ' ' || hour || ':' || MINUTE as timestamp) desc;

下記のような結果を得ることができます。

f:id:gomesuit:20191214201024p:plain

また上記の結果を下記のようにRedashを使ってグラフ化しています。

f:id:gomesuit:20191214201134p:plain

上記は弊社での可視化例ですが、Lighthouseによって様々なメトリクスが取得されているので色々な指標の相対的な変動を計測することが可能になっています。

構築方法

ここまで読んで頂いた方には伝わると思いますが、こんなに色々考えるのは面倒ですよね。 やりたいことはただ「WEBサイトのパフォーマンス計測を定期的に行いたい」だけなのに、どこまで考えなければいけないのだろう・・・という印象を持ってしまうと思います。

なのでこの基盤を10分で構築する方法を手順化しましたので紹介させて頂きます。

本記事で使用するコードは全てGithubにあげています。 github.com

前提

基盤構築に伴って最低限下記が実行環境に設定されている必要があります。

  • awscliのインストールとcredentialの設定

Terraformの利用に伴ってAWSのアクセスキーとシークレットキーの設定が必要です。

  • Terraformのインストール

  • IAMに対するTerraformを実行するための十分な権限設定

  • AWS CodeBuildとGitHubの接続

AWSコンソール上のCodeBuildにおいてプロジェクト設定時のページで下記のように、「GitHubアカウントを切断」と表示されている必要があります。されていない場合は「GitHubに接続」ボタンからGitHub連携を済ませてください。

f:id:gomesuit:20181201200034p:plain

CodeBuildとGitHubが接続されていないとTerraformのapply時にエラーになりますのでご注意ください。

準備

1.リポジトリのフォーク

下記のリポジトリをご自身のアカウントにForkします。Cloneして新しくリポジトリを作成しても大丈夫です。

github.com

2.Terraformのtfstateファイル管理用のS3バケットの作成

空のS3バケットを1つ作成します。 既存のものでも大丈夫ですが、tfstateファイルのkeyをコードにべた書きしているので新規でS3バケットを作成することをおすすめします。

3.terraform.tfvarsの作成

sitespeed.ioの出力したhtmlをS3のホスティング機能を使って参照するため、自身のIPでアクセス制限をかけます。 またCodeBuildがソースを取得する先を、手順で作成したリポジトリのURLに変更します。

サンプルファイルがあるのでコピーしてから、

$ cd terraform
$ cp terraform.tfvars.sample terraform.tfvars

ファイル内のリポジトリのURLを作成した自身のGitHubリポジトリに変更します。

# 作成した自身のGitHubリポジトリ
git_repository = "https://github.com/<user-name>/<repository-name>"

4.Terraform作業ディレクトリの初期化

下記のコマンドでTerraformの作業ディレクトリを初期化します。

$ make terraform-init
cd terraform && \
        terraform init
Initializing the backend...
bucket
  The name of the S3 bucket
  Enter a value: 

S3バケットの入力を求められるので手順2で作成したtfstate用のS3バケットの名前を入力します。

5.対象サイトの指定

計測するページのURLをurls.csvに記載します。 一行に ドメイン名,対象URL,カテゴリ の順で記載します。 複数行記載すると1回のCodeBuildの実行で複数のURLが計測されます。 カテゴリ名は対象URLをカテゴライズするために付与します。任意の文字列を入力してください。

例えば https://www.kurashiru.com/ を計測対象URLとする場合、下記のようになります。 トップページなのでカテゴリはtopとしました。 ※計測対象のWEBサイトはご自身が管理されているものを記載してください。

www.kurashiru.com,https://www.kurashiru.com/,top

構築

Terraformを実行します。

$ make terraform-apply

しばらくすると下記のようにコンソールに出力されるので、確認の後に「yes」と入力するとリソースの生成が始まります。

Plan: 16 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value:

上記コマンドで生成したリソースを削除する場合は下記コマンドを実行します。

$ make terraform-destroy

計測結果の参照

最大1時間待つか設定済みのCodeBuildを手動で1度実行するとS3に計測結果が置かれます。

HTML

S3バケットにhtmlが出力されているのでブラウザで開くことで計測結果を閲覧することができます。

例えばURLは下記のようなものになります。

https://s3-ap-northeast-1.amazonaws.com/webperf-by-codebuild-33916b229c860831/html/example.com/desktop/top/2019/12/14/10/37/output.report.html

f:id:gomesuit:20191214201406p:plain

SQL

AWSコンソールのAthenaでSQLを実行すると結果が取得できるようになっています。

SQL例

SELECT * FROM "webperf_by_codebuild_33916b229c860831"."lighthouse" limit 10;

f:id:gomesuit:20191214201520p:plain

カスタマイズ

Lighthouseの設定

Lighthouseには実行時に独自のヘッダを設定することが可能です。

https://github.com/GoogleChrome/lighthouse#cli-options

またネットワーク速度をエミュレートすることなども可能です。

https://github.com/GoogleChrome/lighthouse/blob/master/docs/configuration.md

検証環境などベーシック認証などをかけている環境へも上記のような設定を含めることで計測対象にすることが出来ます。

計測間隔の調整

計測のトリガーはCloudWatch Eventで行っています。そのためCloudWatch Eventの設定を変更することで計測間隔の調整をすることが可能です。

Terraformの該当ファイルは terraform/codebuild_trigger.tf です。schedule_expressionの cron(0 * * * ? *) を変更することで間隔を変更することが可能です。

反映するにはもう一度 make terraform-apply を実行します。

料金について

本記事の設定で実際にかかっている料金をご参考までにお伝えします。

現在4つのURLの計測を1時間毎に実行していますが、AWSの料金は1日$0.6程になります。格安かどうかで言うと活用次第だとは思いますが、サーバの運用や管理もいらないため、とりあえず動かしておくというのもありなのではないでしょうか。

さいごに

去年作ったWEBパフォーマンスの定点観測の仕組みをバージョンアップしてみました。

WEBパフォーマンスの計測はフロントエンド技術の進化や検索エンジンのアルゴリズムの変化に伴ってどんどん変化する分野だと思うので、常に同じ計測方法をし続けるのではなく定期的に見直していかなければいけない分野だと再認識しました。

本記事の内容はSREとしてのお仕事とは少しずれているのでSREのことが気になる方は下記の記事を是非読んでみてください!

tech.dely.jp

delyではSREを絶賛募集しています!クラシルの開発スピードを落とさず、信頼性も担保するという難易度の高い課題に挑戦したい方はぜひ声をかけてください!

www.wantedly.com

明日はdelyコマース事業部エンジニアのjohnさんが投稿します!お楽しみに!

delyの開発チームについて詳しく知りたい方はこちらもあわせてどうぞ!