はじめに
ISUCONの時期が迫って参りました。参加される方々は色々な準備に取り組まれているのではないでしょうか。アプリケーションをどのように修正していくのか?データベースをどのようにチューニングしていくのか?といったトピックをチームメンバーのみんなと会話をしながら、さまざまな作戦を練っているのではないでしょうか?
ISUCON11でどのようなWebサービス環境が出題されたかを振り返ると、Webアプリケーションやデータベースと一緒にNGINXというWebサーバが用いられており、非常に重要な役割をになっています。ついついWebアプリケーションやデータベースにばかり目が行きがちですが、NGINXのパフォーマンス状況を把握し、Webサービスの改修を行っていく中でボトルネックがNGINXに移ってしまっていないかを常に把握していくことは、非常に重要な戦略となってきます。
例えば、秒間にどれだけのリクエストを処理できているのか?コネクションの破棄が発生していないのか?などを常に把握しておくことで、Webサービスの改修作業が適切な方向に進んでいるのかいないのかを判断する1つの指標となってきます。
また、よりみなさまの身近な活動の例として、NGINXやWebアプリケーションの改善を進めていく中で想定されたレスポンスを得ることができなくなった際にログの確認を行うかと思います。1秒を争う中で、対象のサーバにリモートでアクセスし、適切なログファイルを探し、必要なログラインを検索するというのは非常にヒリヒリするタスクかと思います。NGINXのaccess.logやerror.logを一箇所に集約できていたら、どうでしょう?しかも、検索を簡単に実施できたら?そう言った施策を施しながら、みなさんがWebサービス環境改善に集中するための事前準備を迅速に行っておくことは、一見地味ですが、間違いなく作業終盤に効果的な作業となってきます。
概要
本ブログでは、Webサービスの重要な一部となっていたNGINXを、New Relicを用いてどのようにパフォーマンスを計測し可視化を行うかを説明します。また、access.logやerror.logをNew Relic上で一元管理するためのセットアップ方法についても説明します。
New Relicを適用することで得られるメリットについて
NGINXが稼働しているサーバのキャパシティ利用状況を確認することができます。そのため、キャパシティの観点から、チューニングの可否やパフォーマンスのボトルネック箇所を特定することが可能です。CPUのキャパシティ余剰はまだまだ余裕があるのか?メモリ消費は適切か?など
NGINXのリクエスト処理状況を計測することができるため、Webシステム全体でNGINXの負荷状況やボトルネックとなっているかを判断することが可能です。どれだけのリクエストを処理することができているのか?設定変更後にコネクション破棄の発生頻度を改善することができたか?など
NGINXや後続Webアプリケーションを変更した際に、適切なリクエストの処理を行うことができているか?あるいは、リクエストを適切に処理できずエラーが発生していないか?といった点をログにリモートアクセスすることなく内容の確認を行うことが可能です。
New Relic適用方法
前提:
- New Relicを利用するアカウントを既にもっている。
- もしまだお持ちでない場合、こちらの無料サインアップページよりアカウントを作成してください。
- 手順の説明を優先しますので、こちらの競技者用AMIを用いて環境を構築しました。
- リージョン: Asia Pacific(Tokyo)
- AMI ID: ami-06c39e451ff9930db (Ubuntu22.04)
- 推奨インスタンスタイプ: c6i.large
これのAWS上での展開方法については割愛します。
- New RelicのInfrastructureエージェントを適用します。適用手順は、こちらの当社ブログを参考に進めます。
適用方法
- 上記の当社ブログの手順に従って、Infrastuructureエージェントの導入を実施します。
- 補足事項: このブログを作成した(2022年7月)時点では、Infrastructureエージェントのログ機能を実現しているfluentbit(td-agent)は、Ubuntu 22.04をサポートしていません。そのため、ブログに従った手順を実施した際に、Log Integrationは自動でスキップされます。(プロンプト上では何も表示されません。)
- 補足事項: 今回利用したAMI IDにはMemcachedが導入されているので、Memcached Integrationも導入するかを聞かれますが、Nを選択しスキップして下さい。(Yを選択した場合の手順は割愛しています。)
- NGINX Monitoring Integrationを導入するための事前作業を行います。
- 導入する環境にNGINXのhttp_stub_status_moduleが導入されているかを確認します。
- コマンドプロンプトより、以下のコマンドを実行します。
- sudo nginx -V 2>&1 | grep stub_status
- 出力結果:
configure arguments: --with-cc-opt='-g -O2 -ffile-prefix-map=/build/nginx-9P0wNJ/nginx-1.18.0=. -flto=auto -ffat-lto-objects -flto=auto -ffat-lto-objects -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -flto=auto -ffat-lto-objects -flto=auto -Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-compat --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --add-dynamic-module=/build/nginx-9P0wNJ/nginx-1.18.0/debian/modules/http-geoip2 --with-http_addition_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_sub_module
- 上記の出力が確認できた場合、既にモジュールが導入済みとなります。
- 今回適用したAMIでのNGINXの設定ファイルの本部分は、/etc/nginx/sites-available/isucon.confファイルとなります。
- sudo vi /etc/nginx/sites-avaiable/isucon.conf
server {
listen 80;
client_max_body_size 10m;
root /home/isucon/private_isu/webapp/public/;
location / {
proxy_set_header Host $host;
proxy_pass http://localhost:8080;
}
location /status {
stub_status;
}
}
- 上記のlocation /statusブロックを追加します。
- 追加後、NGINXを再起動します。
- sudo systemctl restart nginx
- 再起動後、手元のWebブラウザから http://<IPアドレス>/status にアクセスし、ステータス情報が表示されることを確認します。
- NGINX Monitoring Integrationを導入する
- 当社ブログで紹介している手順に従いますが、Guided Installではなく、NGINXを選択して進めて下さい。
- 前提作業が完了していれば、NGINX Monitoring Integrationはスムーズに完了します。
- もし、別の環境で試していて作業が完了できない場合には、こちらのドキュメントを参考にし、INTEGRATION_FILE_NAMEをnri-nginxとして導入作業を実施して下さい。
- 導入実行後、/etc/newrelic-infra/integrations.d配下に、nginx-config.yymlファイルが作成されますので、もしデータ収集周期などを変更する場合にはこのファイルを編集します。こちらを参照下さい。
- NGINXのデータを確認するには、以下の手順に従って下さい。
- NGINXダッシュボードを参照する
- New Relicポータルにアクセスし、左ペインからNGINX serversを選択する。選択後、NGINXの一覧が表示されますので、その中から参照したいNGINXを選択します。
- AWS EC2上で実装されたNGINXですと、server:<インスタンスID>:<ポート番号>の表示となっています。
- New Relicポータルにアクセスし、左ペインからNGINX serversを選択する。選択後、NGINXの一覧が表示されますので、その中から参照したいNGINXを選択します。
- NGINXダッシュボードを参照する
- NGINXダッシュボードが表示されます。
- 秒間あたりのリクエスト処理数、アクティブなコネクション数、秒間あたりのコネクション成功数、秒間あたりのコンエクション破棄数を参照することができます。
- Data Exploreを参照する
- New Relicポータルにアクセスし、Query your dataあるいはBrowse dataを選択します。
- 表示される画面の左上で、Data explorerを選択し、Eventsを選択後、Event typeからNginxSampleを選択します。Plotから参照できるデータ一覧が表示されるので、参照したいデータ(例: net.connectionsWaiting)を選択します。
- 選択後、画面右側にグラフが表示されます。
- もし、NGINXから計測したデータをカスタマイズして常に即座に確認したいという要件がある場合、カスタムダッシュボードの活用をご検討下さい。
- 参考情報はこちらです。
- NGINXのログ取り込みを行うためのlog forwarderの導入
- log forwarderとして、Fluentdを導入します。導入に当たって、サーバの再起動が発生する可能性があります。
- 参考情報はこちらからご確認してください。
- 事前準備
- ulimit -nコマンドを実行し、65535以上となっていることを確認してください。もし、1024といった値が表示された場合、/etc/security/limits.confを編集します。
- sudo vi /etc/security/limits.conf
- 以下を追記します。
root soft nofile 65536
root hard nofile 65536
* soft nofile 65536
* hard nofile 65536
- サーバを再起動します。
- sudo shutdown -r now
- 再起動後、サーバにリモートでアクセスし、ulimit -nコマンドの出力が65535となっていることを確認します。
- fluentd(td-agent)の導入作業を行います。
- 参考情報はこちらです。
- コマンドラインより以下を実行し、fluentd(td-agent)のインストールを行います。
- curl -fsSL https://toolbelt.treasuredata.com/sh/install-ubuntu-jammy-td-agent4.sh | sh
- 補足: fluentd(td-agent)の稼働状況は以下のコマンドにて確認します。
- sudo systemctl status td-agent
- td-agent用のNew Relic Fluentdプラグインをインストールします。
- sudo td-agent-gem install fluent-plugin-newrelic
- fluentd(td-agent)の設定ファイルを編集し、New Relicポータルにログを送る設定を追加します。
- API KeysからINGEST - LICENSEを取得します。API Keyについてはこちらのブログを参考にしてください。このINGEST - LICENSEの値を、次のステップで設定ファイルに記載します。
- fluentd(td-agent)の設定ファイルは、/etc/td-agent/td-agent.confになります。このファイルを編集します。
- sudo vi /etc/td-agent/td-agent.conf
- 以下のコードをtd-agent.confの最後尾に追記します。
<source>
@type tail
<parse>
@type none
</parse>
path /var/log/alternatives.log
tag alternatives.log
</source>
<source>
@type tail
<parse>
@type none
</parse>
path /var/log/cloud-init.log
tag cloud-init.log
</source>
<source>
@type tail
<parse>
@type none
</parse>
path /var/log/auth.log
tag auth.log
</source>
<source>
@type tail
<parse>
@type none
</parse>
path /var/log/dpkg.log
tag dpkg.log
</source>
<source>
@type tail
<parse>
@type nginx
</parse>
path /var/log/nginx/access.log
tag nginx-access.log
</source>
<source>
@type tail
<parse>
@type nginx
</parse>
path /var/log/nginx/error.log
tag nginx-error.log
</source>
<filter **>
@type record_transformer
<record>
service_name ${tag}
hostname "#{Socket.gethostname}"
</record>
</filter>
#Forward all events to New Relic
<match **>
@type newrelic
license_key <先ほど取得したINGEST - LICENSEの値>
</match>
- 監視ログファイルの参照権限の制約を回避するために、td-agentユーザをadmグループに追加します。
- sudo adduser td-agent adm
- fluent(td-agent)を再起動し、設定を反映させます。
- sudo systemctl restart td-agent
- 収集したログを参照するには以下の手順に従って下さい。
- 当該サーバのみのログを参照したい場合、New Relicポータルにアクセスし、左ペインのYour sytemからHostsを選択します。その後、中央に監視対象サーバの一覧が表示されますので、該当するサーバを選択します。選択したサーバの計測データを表示するUIに切り替わるので、左ペインからMonitorのLogsを選択します。
- NGINXのログラインは自動でパースされていますので、timestamp属性を元にログラインを選択し、右側から表示されるUIから詳細情報を参照することができます。
- あるいは、Add columnをクリックすることで、任意の属性情報を表示させるように追加することができます。
- 当該サーバのみのログを参照したい場合、New Relicポータルにアクセスし、左ペインのYour sytemからHostsを選択します。その後、中央に監視対象サーバの一覧が表示されますので、該当するサーバを選択します。選択したサーバの計測データを表示するUIに切り替わるので、左ペインからMonitorのLogsを選択します。
- 他のサーバやアプリケーションから収集したログを一緒に参照したい場合、New Relicポータルにアクセスし、メインメニューのLogsを選択することで、集められたログ情報を参照することができます。
まとめ
ここまでお読みくださりありがとうございます。実装手順は非常に多く感じられるかもしれませんが、実施している内容を理解頂くと、実行しているコマンドなどは非常に少ないことをご理解頂けるかと思います。スムーズに進めば、全体で10分もかからない内容です。
New Relicが実現するデータ計測やログの一元化により、さまざまな改修を進めながら、即座にその結果を確認することができることを体験頂くことができます。みなさんがお持ちになっている創造的な発想力をコード改善に向けて頂くためにも、是非、New Relicを十二分に活用して、コード改善の結果を即座に可視化できる環境を構築してください。Happy Coding!!
参考資料集
本ブログに掲載されている見解は著者に所属するものであり、必ずしも New Relic 株式会社の公式見解であるわけではありません。また、本ブログには、外部サイトにアクセスするリンクが含まれる場合があります。それらリンク先の内容について、New Relic がいかなる保証も提供することはありません。