tsyama記

プログラミングとそのほか

バックエンドエンジニアとLighthouse

はじめに

仕事で作ったAWS環境をLighthouseにかけられる刑に処されました。

前提

  • サイトはNuxt.jsで構築
  • 管理画面はWordPressを使用し、NuxtからはWP REST APIを使用
  • AWSについては下記の構成
    • EC2(t3.small * 1台)
    • ALB
    • Route53
    • S3
    • CloudFront

f:id:tsyama-desu:20190626003417p:plain

バックエンドエンジニアがLighthouseで考えること

バックエンドエンジニアとしてやった対策をまとめてみました。

Performance

Enable text compression

テキスト圧縮の有効化

リクエストヘッダにAccept-Encodingが含まれている場合、テキスト形式のデータを圧縮してデータ通信量を削減することができます。

Apacheで設定する場合

mod_deflateが導入されているのを確認した上で、下記のような設定を記述します。

<IfModule mod_deflate.c>
     SetOutputFilter DEFLATE
     AddOutputFilterByType DEFLATE text/html text/plain
</IfModule>

参考:Apacheのmod_deflateでコンテンツを圧縮してサイトを高速化する方法 | OXY NOTES

CloudFrontで設定する場合

今回の場合ではS3など、CloudFrontをかまして配信されているコンテンツの場合は、CloudFront側でテキスト圧縮が可能です。コンソールから2, 3ポチで設定できます。

参考:[超簡単]cloud frontの料金を最大1/5に減らす節約方法 | YongJin Kim's Blog

Uses efficient cache policy on static assets

静的なアセットと効率的なキャッシュ ポリシーの配信

端的に言ってしまうとcache-controlの設定です。Apacheなどであれば設定ファイルでどうとでもなりますが、S3で配信しているファイルのキャッシュ設定はやや面倒です。

Apacheの場合

<ifModule mod_expires.c>
  ExpiresActive On
  ExpiresByType image/png "access plus 1 month"
</ifModule>

mod_expiresを使用して設定します。
直接cache-controlヘッダを追加することでも対応できます。

参考:Apache httpd の mod_expires でキャッシュ有効期限を設定しよう | WEB ARCH LABO

S3の場合

S3オブジェクトはメタデータを設定することで、アクセスした際のヘッダを指定することができます。

参考:S3 オブジェクトにメタデータを追加する方法 - Amazon Simple Storage Service

ただ、上記のようにファイルひとつずつキャッシュをさせることはできても、Apacheのように特定のタイプのファイルをまとめて設定することができません。S3を使う場合はだいたい結構なファイル数を扱うことが多いと思われるので、ひとつひとつメタデータを設定するのは現実的な運用ではない…。

このあたりはどういう運用をするかにもよりますが、アップロード時に処理をかまし、S3にアップロードされた時点で適切なメタデータが設定されている状態にするのが正攻法かと思います。すでにアップロードされている多数のファイルのメタデータを変更するという場合は、aws s3 syncコマンドをうまく使うといいかもしれません。

Keep Server Response Times Low

サーバーのレスポンスタイムを低く保つ

ここがサーバサイドエンジニアの腕の見せどころでしょう。ですよね。ボトルネックを見極めたうえで、さまざまな手段を用いて迅速にレスポンスを返してやることが求められます。

打てる施策も幅広いので、ここでは僕がよくやることリストをいくつか紹介してお茶を濁しておきましょう。

サーバサイドキャッシュ

ささっとできて爆発的な効果をもたらしやすいと話題のキャッシュくんです。キャッシュ施策をまだ打っていないのであれば、真っ先にやってみるといいです。

簡単なのはファイルキャッシュですが、しっかりやりたいならmemcachedやRedisを検討します。今回はWP REST APIの呼び出しがボトルネックになっていたため、WP REST Cacheというプラグインを使用してがっつりキャッシュをかけました。

一点注意として、何も考えずにキャッシュを導入するのはリスクである、ということは肝に命じておきましょう。

キャッシュを消すタイミングや、不適切なユーザーにキャッシュが使われることはないかといった運用上の懸念は意識しておく必要がありますし、知らず知らずのうちに使われていたキャッシュのせいで不具合の原因特定に時間がかかってしまう、というのもよくある話です。

DBクエリチューニング

DBは総じてボトルネックになりがちです。ボトルネック特定のための計測についてもDB周りを狙い撃ちしてみるといいでしょう。

スロークエリログやフレームワークデバッグツールを活用しながら、適宜インデックスを張っていきます。

参考: 漢(オトコ)のコンピュータ道: MySQLのEXPLAINを徹底解説!!

Apacheチューニング

Apacheでは同時にリクエストを捌くプロセス数を設定で変更することができます。適正値はサイトの性質やアクセス数により大きく変わるため、実際に運用しながらチューニングしたり、事前に負荷テストをしておくのがいいかもしれません。

参考: 中規模サイトのApacheチューニング - Qiita

また、場合によってはApacheを使用せず、同時接続に強いNginxを採用するという選択肢を取ってもいいでしょう。

Avoid multiple page redirects

複数のページ リダイレクトの回避

世の中は様々なリダイレクトに溢れています。リダイレクトはたいていの場合過去の業に縛られがちなので、業の深いサイトはおびただしいリダイレクトが発生し、管理しきれなくなったりします。気を付けましょう。

Best Practices

Uses HTTPS

今どきフォームや個人情報を扱っていなくても、SSL化ぐらいはしておくようにしたいですね。AWSを使っているならALBで証明書を登録しておくと、Webサーバ側でSSL化のことを気にしなくて良くなるので幸せです。

参考: AWSのサービスでドメインを取得しALBでSSLで接続出来るようにする - Qiita

Uses HTTP/2 its own resources

上述のALBを使用しているなら、HTTP/2対応もとってもチョロいです。ALBの設定で項目が見つけられるはずなので確認してみましょう。また、CloudFrontを噛ませている場合はそちらで対応することも可能です。

ただ、ALBで対応する場合はEC2側の設定により、Safariでエラーが発生してしまうことがあります。EC2でAmazon Linux2を使用したときに発生するようなので、下記記事を参考にしてください。

参考: AmazonLinux2のhttpdをALB経由で公開するWeb環境で発生していた、SafariのHTTPS接続エラーを改善してみた | DevelopersIO

もちろんwebサーバ側でHTTP/2対応をすることもできます。

参考: HTTP/2を実際に使用するためのサーバー設定 | さくらのナレッジ

SEO

Page has successful HTTP status code

基本的なことですが、HTTPステータスコードは正しく使うようにしましょう。

おわりに

Lighthouseの言いなりになるのがよいというわけではありませんが、バックエンドエンジニアとしてもサイト高速化といった対応の参考になるところが多く、自分の作ったサイトで一度試してみるのもいいのではないかと思います。