NewRelic は、PHP や Ruby、Javaだけでなく .NET のプロファイリングも優れています。
今回は、ASP.NET のアプリケーションの前段に ARR を使ったリバースプロキシを置いた時に、アプリケーション本体のみをプロファイルさせるための方法について説明します。
目次
事前に読んでおくといいもの
- そもそも NewRelic Agent のコンフィグをどこでやるか把握しましょう
https://docs.newrelic.com/docs/agents/net-agent/installation-configuration/net-agent-configuration
- .NET でできないことも把握しましょう
https://docs.newrelic.com/docs/agents/net-agent/installation-configuration/known-issues-net
やりたいこと
IIS 上に、ASP.NET MVC なアプリをホスティングしているとしましょう。
ここで、前段に ARR(Application Request Routing) を利用した リバースプロキシを置いているとします。よくある nginx を前段において、アプリをバックエンドをIISで組んでいるケースと思ってください。
つまり以下のような構成です。
さて、NewRelic にやらせたいことの1つはアプリケーションのモニタリング・監視ですね。この辺がピンとこない方は、@IT で id:kkamegawa さんが簡潔にきっちりまとめられている記事が参考になるでしょう。
このNewRelic による監視をもう少し実用面で考えます。
.NET Agent の副作用は凄まじい
さて、このまま .NET Agent を入れて問題ないでしょうか?
NewRelic .NET Agent は、Ruby や PHP の Agent と同様にプロファイルします。さて、どこでというと、このケースでは IIS に dll を突っ込んでです。
結果どうなるかというと、アプリケーションのパフォーマンスが低下します。アプリの構成にもよりますが、30%~50%弱影響を受けるケースもざらにあります。
監視はしたいけど、パフォーマンスをむやみに下げたくないですよね?特に IIS 上で、複数のWebサイトを同居させていている場合は顕著です。
アプリケーション と リバースプロキシではプロファイル制御したい
さらに今回の構成のようなリバースプロキシのサイトでもプロファイルが走ると、アプリケーションのThroughputだけ見たくても リバースプロキシサイト分が追加されて2倍になります。これは良くない。大変良くない。
リバースプロキシは単純にリダイレクト書けるだけなので、NewRelic .NET Agent を走らせる意味が(ほぼ)皆無です。無駄といえます。
とすると、同じIIS 上で プロファイルを走らせるサイトと走らせないサイトが出てきますね?これをどうやるかが本題です。
つまりこれを目指します。
NewRelic のプロファイラを制御する
IIS 上の設定
Webサイトごとにアプリケーションプールは分離させよう
IIS の WebSite は、WorkerProcess(w3wp.exe) を アプリケーションプール単位で動作させています。
NewRelic .NET Agent は、WebSite単位でプロファイルをしているのですが、その対象はアプリケーションプールです。Webサイトごとにアプリケーションプールを分離させて置くことは大事です。
アプリケーションプールの実行ユーザーが問題となる
WorkerProcess を何で動かしているかは NewRelic .NET Agent の設定に関して影響します。
ふつーは ApplicationPoolIdentity でしょう。しかし、アクセス制御をしたいなど多くのシーンではSpecific User
にしていることが多いと思います。このSpecific User
の時に困ったことになります。
いずれのパターンでも対応可能ですし後述しますが、自分がなぜそのアプリケーション実行ユーザーにしているかは把握しておくことを推奨します。
newrelic.config は罠
さて、NewRelic Agent は、newrelic.config で制御可能と NewRelic doc には書いてあります。セクションとしては instrumentation Section の Applications element (instrumentation)
がいかにもそれっぽいでしょう。
https://docs.newrelic.com/docs/agents/net-agent/installation-configuration/net-agent-configuration
結論からいうと、これではアプリケーションプール単位での制御ができないケースがあります。
どういうことかというと、ApplicationPool を ApplicationPoolIdentity
ではなく、Specific User
で動かしていると NewRelic Agent がアプリケーションプール名を取得できません。なんてこった!
NewRelic agent は、IISRESET
でプロファイルが再開された時にログを吐くのですが、そこで ApplicationPool 名をとれているか確認できます。
This application pool () is not explicitly configured to be
アプリケーションプールが誰で実行されていてもプロファイルを制御する
newrelic.config でアプリケーションプール単位の制御ができないことがわかりました。
ではどうするか。そのヒントはここにあります。(何と答えが NewRelic doc上にない)
https://docs.newrelic.com/docs/agents/net-agent/instrumentation/instrumenting-non-iis-apps
これがポイントです。
<add key="NewRelic.AgentEnabled" value="true" />
では、IIS のWebサイト単位でどうやって制御するかといえば web.config です。(user.config で転換している場合はそっちでok)
プロファイルを取りたくないサイトに対して、アプリケーション名を明示して、プロファイルの実行を false
とすれば ok です。(プロファイルを取りたい場合は、true にしましょう。)
<appSettings> <add key="NewRelic.AppName" value="my_web_app" /> <add key="NewRelic.AgentEnabled" value="false" /> </appSettings>
あとは、ASP.NET アプリをデプロイした際に NewRelicのプロファイルはこの web.configに従ってプロファイルを停止します。
まとめ
NewRelic Profiler の制御は大事です。現在 NewRelic.config は使わない方向に NewRelic は移行しており、Online で大体設定可能になっています。つまりNewRelic.config オワコン。
ASP.NET に限らず、プロファイルの制御は アプリサイドのコンフィグで可能なので web.config や .exe.config で制御してください。
特にリバースプロキシを持っている IIS の場合は必須ですよ。お気を付けて。
ずっと書こうと思っていながら1か月以上放置していました*1
*1:いつも通り