LoginSignup
9
9

More than 3 years have passed since last update.

Webアプリ性能をnscd使って改善した話

Last updated at Posted at 2018-10-10

はじめに

Webサイトにおけるパフォーマンス(サイト表示速度)を改善するポイントはいくつもあります。
以下一例です。

  • フロントエンドの改善
    • リクエスト回数を減らす
    • 通信量を減らす
    • レンダリング速度の最適化
    • CDN活用
  • サーバサイド
    • (Memcached/Redis等)キャッシュ活用
    • アプリロジック改善
      • n+1問題回避やらいろいろ
    • APサーバと静的コンテンツ配信サーバ分離
    • 開発言語バージョンアップ
    • DBチューニング
      • インデックス見直し
      • SQLチューニング

弊社サービスでは、これまでも上記に取り組み、少しずつ改善はしていました。
それもそろそろ今のアーキテクチャでは頭打ちかな?という状況でしたが、最近実施して意外にも
大きく改善したことがあったのでご紹介します。

環境構成

  • インフラは全てAWS
  • APサーバには、apache2.4 + php7.2 + opcache
  • Cacheサーバには、ElastiCache(セッション用、キャッシュ用の2つ)
  • DBサーバには、RDS for PostgreSQL

よくある構成ですね。^^;

主題:nscdでDNSキャッシュ

弊社の環境では、Route53のPrivateDNSでRDS/ElastiCacheエンドポイントに別名のホスト名を
割り当ててそれをAPサーバから使うことで、リソース切り替えを容易にしています。(疎結合!)
この方式の弊害としては、PrivateDNSだとALIASレコードが使えないため、CNAMEレコードを設定する必要が
あり、これにより名前解決に余計に1回クエリが飛んでしまうというもの。

PrivateDNSでもALIASレコードは使えるようです(コメント欄参照)

また、phpは(apache)プロセス内でDNSクエリ結果をキャッシュしないようで、毎回DNSクエリを投げます。
このRDS/ElastiCacheの名前解決処理により、遅延が発生している可能性を疑いました。

そこで、nscdを用いてDNSクエリ結果をキャッシュを試してみました。
nscd(name service cache daemon)とは、その名の通り、DNSやNISなどの一般的なネームサービスの
内部DBを保持し、passwd、group、hostsファイルなどの情報をキャッシュするサービスです。

nscd導入手順

$ sudo yum install nscd
$ sudo vi /etc/nscd.conf  # 後述のnscd.confの内容にする
$ sudo systemctl start nscd
$ sudo systemctl enable nscd
$ sudo apachectl graceful # Apache利用の場合
/etc/nscd.conf
    logfile             /var/log/nscd.log
#   threads             4
#   max-threads         32
    server-user         nscd
#   stat-user           somebody
    debug-level         0
#   reload-count        5
    paranoia            no
#   restart-interval    3600

    enable-cache            hosts       yes
    positive-time-to-live   hosts       60
    negative-time-to-live   hosts       5
    check-files             hosts       yes
    shared                  hosts       yes

    enable-cache        passwd      no
    enable-cache        group       no
    enable-cache        services    no
    enable-cache        netgroup    no

効果

結果として、 約30% サイトの平均レスポンスタイムが改善しました。
(当社比。もちろん、SDKや各種エンドポイントの利用頻度によって効果は違います)
DNSクエリをtcpdumpで確認してみると、RDS/ElastiCacheだけではなくS3やCloudFrontなど他の
AWSリソースにもリクエストを投げており、それらSDKを利用したアクセスにも効果がありました。

注意点

DNSキャッシュしている期間は、フェイルオーバー遅延などが起こるので、許容できる範囲でttlを設定する必要があります。

おまけの改善:リリース回数が増えると性能劣化する問題

次に、nscdでレスポンスが速くなったことで リリース後にレスポンスが遅くなる という問題が顕在化しました。
(nscdの改善に比べればおまけみたいなものですが)

原因

OPcacheのCache Fullが発生し、キャッシュにのりきらなくなったことが原因でした。
※OPcacheについては、php.netQiita記事を参照ください。
Opcache Control Panelを使って性能劣化時のOPcacheキャッシュ利用状況を取得してみました。
取得した結果(抜粋)が以下です。
ocp.png
Cache Fullが1になってますね。^^;

弊社では、php実装したWebアプリは、
デプロイサーバでコード取得→composer install→APサーバ配布→シンボリックリンク切り替え
という流れでアトミックにデプロイしています。よくある方法ですね。
最近リリース頻度が増えてきており、1日に数回リリースすることがあります。(多分2桁はいかないけど)

OPcacheは、一度キャッシュしたデータは放置すると消えません。
キャッシュをクリアするには再起動するかopcache_reset()を実行する必要があります。
なので、リリースを繰り返した結果キャッシュサイズ上限を超えると、毎回コンパイルが走り、性能が劣化することになります。

対策

  • Apache再起動してキャッシュクリア
  • 上限超えないように共有メモリサイズ(opcache.memory_consumption)を増やす
  • 変更なしファイルは同じタイムスタンプでデプロイする(不要なキャッシュを回避)

などなど、いろいろやり方はあると思いますが、
今回は簡単にできるhttpd再起動(apachectl graceful)の定期実行でキャッシュクリアするようにしました。

効果

一部サーバのレスポンスタイムの推移です。後半は性能劣化が起きなくなっています\(^o^)/
restime_avg.png

まとめ

頭打ちと思っていても、まだまだ改善できる余地はあるのだなぁ(スキル不足w)と実感。
ちなみに今回の改善をする前に、php5.6 -> php7にあげたのですが、その時に全然改善しなかったのは
他のボトルネックが大きすぎて、見えづらかったのかも。と今になって思いました。

最後に、今回あげた改善例も種類は違えどキャッシュの改善。
やっぱりキャッシュ戦略大事ですね!!

9
9
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
9