詳解 NewRelic で監視＆性能改善〜その１


# 概要

１年半ほどNewRelicを本番環境+開発環境で使ってきて知見が溜まってきたので共有したいと思います。
ここで説明している機能は有料版のものも含みます。

[詳解 NewRelic で監視＆性能改善〜その１](http://qiita.com/wapa5pow/items/e3ef018af270cc2ad014)
[詳解 NewRelic で監視＆性能改善〜その２](http://qiita.com/wapa5pow/items/0a4132c62d807286af9d)

# NewRelicとは

![overview.png](https://qiita-image-store.s3.amazonaws.com/0/30079/6d7835c4-2e26-1dc3-f33d-9149f46f84c8.png)

NewRelicとはサーバ、またはアプリケーションの状態をモニターし、その性能を改善するために使われるツールです。
既存のモニタリングツールとしては、zabbix, ganglia, nagios, munin など各種ありますが、NewRelicが優れているのはその手軽さかと思います。
インストールしたらアプリケーションをサーバ運営する上で必要なメトリックスが一通り揃っています。
既存のモニタリングツールだとインストールするユーザが必要なメトリックスを定義して設定、場合によってはスクリプトを書かなければいけません。
その点、NewRelicはデフォルトのメトリックスが非常に充実しており見やすく配置されており追加設定なしで十分という場合も多いでしょう。
既存のメトリックスにない場合でも手軽にインストールできるプラグインが充実しております。

この記事ではNewRelicの誰でもしっている機能から、有料版の細かい機能までをケーススタディ別で紹介したいと思います。

# 前提環境

スマートフォンゲームのアプリケーションサーバを開発してます。
NewRelicでメトリックスを取っているアプリケーショの環境図は以下です。

![server.png](https://qiita-image-store.s3.amazonaws.com/0/30079/1e814d2b-f78b-19a9-c339-18c25973c741.png)

* AWS環境
* アプリサーバは複数台でEC2に乗っているDjango (python)のアプリケーション
* MySQLとRedisにアプリサーバが繋がっている

と、ごくごく一般的な構成です

それではサーバエンジニアのケーススタディを始めます :sunny: 

# ケース1: アプリケーションの応答が遅いけどもっと早くならないか

いろいろな人から言われると思います。ざっくりすぎてよくわからないので、まず問題を定義するところから始めます。
遅いところはどのAPIなのか。いつから遅くなったのか。特定の場合のみ遅いのか。他のユーザはどうなのか。
たくさんありますが、何が問題なのかを具体的にします。その結果以下のような問題がわかりました。

* ガチャのAPIが１日まえくらいから遅くなった。他のプレイヤー全員が遅いわけではなく、早い人もいる。

だいぶ具体的になったので、NewRelicを見てみます。
APPSで該当のアプリケーションを選んでから、Transactionsという項目を押してください。
「Slowest average response time」というものを選ぶと応答時間の順に遅いAPIがわかります。
（注意: 全体的に遅いですが、まだ性能改善前で、サーバのチューニングもしていないのです。。。）

![gacha_transaction.png](https://qiita-image-store.s3.amazonaws.com/0/30079/60d5c39d-442c-2781-b1a0-3c4ebe920c81.png)

そこのgachaのクリックすると右側に以下のようなページが見えます。

![gacha_select2.png](https://qiita-image-store.s3.amazonaws.com/0/30079/5bab414e-c622-15dc-5095-862aa90dce1b.png)

このページを見ることによって以下の事がわかります。

* pythonコードのFunctionで多くの時間を取っている
* unit_player_xxのselectが多い
* unit_player_xxのinsert, updateも多い

問題定義の内容とソースコードの両者を合わせてボトルネックを探ると以下の点が問題でした。

* 大量にユニットを所持しているユーザのレスポンスが遅かった => ユーザの取得済みユニットの全リストをAPIで返しているが必要ないので削除
* ガチャで取得したユニットごとに複数のinsert/udpateが走っている => 更新系はbulkで行う

上記の対応をすることによりAPIが早くなり問題ない応答時間になりました。
このようにNewRelicではAPIごとのSQL発行数, Redisへのクエリ発行数, pythonコードの実行時間が取得で性能改善に役立ちます。

ただ、ここで注意しなければならないのは、Avg timeはあくまでかかった時間なので、サーバのCPUがいっぱいいっぱいだと、pythonコードが処理できずコードの時間が長くなったりします。

# ケース2: MySQLがなんか遅そうなのだけれどもどこが原因？

NewRelicのMySQL項目を説明するためのケースのようですが、実際に起こり得ます。
ユーザが増えてきた際にAppサーバのCPUは50%くらいで問題なさそうなのになんかおそくなったという際はMySQLかRedisが原因かもしれません。

よくわからないときは基本のOverviewを見ています

![mysql_slow.png](https://qiita-image-store.s3.amazonaws.com/0/30079/1bd1f885-3ec6-3b62-10f2-391a39dc4823.png)

なんだかMySQLが遅そうですね。そのようなときは、左ペインDatabasesを選択し、ひとまず以下の項目を見てみます。
（注意: 別の時間のものです。単に紹介なので）

![databases.png](https://qiita-image-store.s3.amazonaws.com/0/30079/78b34697-1802-cb86-2fe3-953d51d2b18e.png)

クエリごとの応答時間がわかるので、遅くなったクエリなど一目瞭然です。
このケースでありがちなのは、データの履歴が少なかったときは早かったのですが、多くなってくると遅くなるパターンなどです。
インデックスの貼り忘れだったり、そもそも履歴が必要なかったりするケースがあったりするのでそこを直します。
それぞれのクエリをクリックするとそのクエリを発行しているAPIもわかるので改善により役立ちます。

この項目ではクエリ単位でしか見れませんが、MySQLのサーバ自体のメトリックスをみたい場合は、MySQL pluginがおすすめです。
（注意: 別の時間のものです。単に紹介なので）

[http://newrelic.com/plugins/new-relic-platform-team/52](http://newrelic.com/plugins/new-relic-platform-team/52)

インストールすると以下のような項目が見れます。

![plugin_1.png](https://qiita-image-store.s3.amazonaws.com/0/30079/8e444286-2202-e3b3-7f42-5172a55f05f9.png)
![plugin_2.png](https://qiita-image-store.s3.amazonaws.com/0/30079/9cdf18a2-eb57-b3fb-4fa7-b8e915a2bf56.png)
![plugin_3.png](https://qiita-image-store.s3.amazonaws.com/0/30079/ff42f4cb-4971-9d3b-6f3c-e755916daf7a.png)


# ケース3: CPUがいっぱいいっぱいになっているがなにがおこっているのか

どのプロセスがCPUをくっているのか知りたいときもありますがAWSコンソールの標準のメトリックスでは全然わかりません。
そんなときもNewRelicならdefaultでインストールしたエージェントでとれます。

トップペインからSERVERSを選びます。Processesを左ペインから選ぶとどのプロセスがCPUを多く使っているかわかります。


![servers_1.png](https://qiita-image-store.s3.amazonaws.com/0/30079/7b92f7f9-5305-97f3-462f-42f596429619.png)
![servers_2.png](https://qiita-image-store.s3.amazonaws.com/0/30079/cb68d11e-e72e-fbe0-8181-19601f6e5831.png)


# ケース4: いつデプロイしたのか知りたい

NewRelicのWeb APIにイベントを投げる事によってデプロイした時間にマークをつけることができます。

![deploy.png](https://qiita-image-store.s3.amazonaws.com/0/30079/f10c710e-d91e-3ce5-f710-5e01d542afaf.png)

# ケース5: リリースしてからてんやわんや

なんだかよくわからないケースですが、本番サーバにしかNewRelicをいれていなかったというお話です。
NewRelicは開発期間中に開発サーバにいれてこそ効果が発揮されます。
よくあるのは開発で早く動いていても本番になると性能が劣化するパターンです。開発環境では十分な負荷がかかっていないので、SQLのクエリが遅かったりすることろがわかりません。
そのような際は開発環境にもNewRelicを入れておき、APIごとのSQL発行数などを監視しておきます。
もちろん負荷試験をリリース毎にやればいいのですが、コスト・時間的に現実的ではない場合も多いです。
月々多少の費用はかかりますが十分ペイできると思います。

# 結び

ここまで基本的なNewRelicの使い方をケース別でまとめました。
次回は、最近覚えたNewRelicの便利な機能であるKey Transactions, X-Rayについて紹介します。