2012年1月29日日曜日

効率のいいリクエスト処理

Webサイトの運用、大変ですよね。お疲れ様デスよ。まったく。

普通にネットワーク構成するとハードウェアロードバランサの下にWebサーバー並べて負荷分散する感じになるでしょう。処理が追いつかなかったらWebサーバー追加だぜ!とか、富豪富豪。ふぇっふぇっふぇ。でも、そんな富豪ばかりじゃない。

Application Request Routing | IIS 拡張機能 | TechNet

略してARR。NLBみたいにネットワークの負荷分散じゃなくてHTTPでのリクエスト負荷分散。ソフトウェアLB。

ARRが単なるリバースプロキシだと思ったら大間違いでした。この子かなり優秀。

そもそも、SSLオフロードさせようと思って、パフォーマンステストをしてたんですけど、思いの外Request / Secが高くなる。変だなーと思って、HTTPSじゃなくてHTTPでも試してみたら、それでもRequest / Secが高い。なんで!?と思いパフォーマンスモニターでいろいろ見てたら、どーもノードサーバーの処理が重い時にはARRがリクエストのルーティングをちょっと保留してるくさい。レスポンスタイムを見て、重くなってきたのかどーかを判断してるのかなー。それ以外に指標がないと思うので、そーじゃないかという予想。

arr1

arr2

VS のロードテスト(今はまだUltimate使えるからね)でチェックしてみました。10~250ユーザーまで徐々に増やしていく設定でWebアプリケーションの動きをシミュレートさせる。下のグラフはパフォーマンスモニタ。

黄色がCPU、青がWeb Service:Current Connections、緑がW3SVC_W3WP:Request / Sec、赤がASP.NET v2.0:Request Queued。

まずは、ARRを通さずに直接リクエストした状態です。CPUは概ねフルに使いつつ、コネクション数が段階的に増え、リクエストキューに処理待ちリクエストが溜まっていく様子です。直感的にそーなるなー、っていう動きがそのまま再現できてますね。

arr3

どんどん負荷を上げる(ユーザー数を増やす)と、キューにたまる数が増えて、グラフ上Request / Secを上回ります。これはつまり同時処理性能を超えたリクエストがWebアプリケーションサーバーに来てるっていう状態ですね。さばけないからキューイング。ASP.NETのキューイング。

最終的にすべて終了すると↓こうなって、何もかも0に戻る。

arr4

ロードテスト結果。

arr5

Request / Secが281でページ/秒の平均が26.0です。

今度は全く同じ事をARR経由させて実行します。

arr6

arr7

この段階ですでに挙動が違うんですよね。下のグラフはWebアプリケーションサーバーの状態なんですけど、コネクション数の増え方が違う。段階的なんだけど、伸びかたが明らかに違う。この時のARRの同じグラフを見てみるとどーなってるか。

arr8

なるほどね。こっちにはユーザー数と同じ増え幅でコネクション数が増えてます。

ARRからノードサーバー(Webアプリケーションサーバー)へはTCP接続を使いまわしてる?コネクションプーリング。

arr9

ユーザー数をどんどん増やしていくと、リクエストキューにたまるのが直接接続時の挙動でしたが、ARRを経由した場合、キュー(赤)がたまるのに合わせてコネクション数(青)が増えてる。関連があるような挙動ですね。

で、観測を続けると、キューの数が減少に転じてます。不思議ですね。ユーザー数は同じでリクエスト数も同じように発生してるのに、Webアプリケーションサーバーではキューがたまりません。

その時のロードテストの状態。

arr10

Request / Secは298で落ちてない。若干上がってるくらい。

arr11

最終的にテスト実行完了時点でCPUやRequest/Sec、キューの数は0に落ちるのに、コネクション数(青)はまだ0にならない。しばらく高止まり。これはつまりARRがコネクションをすぐに切ってないということですね。

arr12

Request / Secが347でページ/秒の平均が32.4.0。ページの応答時間平均にいたっては6.45から4.20ですよ!約1.5倍。これはどういうことなのかというと、Webアプリケーションサーバーの同時処理性能が下がるようなリクエストをルーティングせず、しばらくARRでキューイングしておくことで、Webアプリケーションサーバーがベストパフォーマンスを出せるように調整してるから、じゃないでしょうか。実際にWebアプリケーションサーバーのキューの数はARRを経由させたほうが少ない状態を維持し、コネクション数も少ない。何度か試した結果コネクション数が半分の時もあるのに、ページの応答時間平均は常に概ね1.5倍早い。

無理に同時実行させないことで早くレスポンスを返す。結果的にRequest/Secも上がる。SSLオフロードでWebアプリケーションサーバーのCPU利用を実処理に専念させようとしただけなのに、この結果。恐るべしARR!

ちなみにARRとWebアプリケーションサーバーが同居した場合にはまるで性能向上しませんでした。してもいいかと思ったんだけど、そういう訳でもないんですね。IISとASP.NETの双方でのCPU利用(ネットワークも思いのほかCPU利用するのかもね)を最適化するならARRは別サーバーで用意しましょう。

ARR賢い。単なるリバースプロキシじゃない。ノードサーバーはIISに限定するものじゃないので、性能判断の指標はレスポンスタイムしか無いと思うけど、その辺の情報は見つけることが出来ませんでした。

今回はARR1台、ノードサーバー(Webアプリケーションサーバー)1台なので、こういう結果でしたが、ノードサーバーの台数が増えた場合にはどのように効率化されるのかは、環境次第だと思うので、自身の環境で試してみたらどーでしょー。

もし、仮に同じような性能向上をするならWebアプリケーションサーバーが4台以上ある場合、1台をARRにしたほうがレスポンス性能がいいということになるかもよー。

目指せ、続ハイパフォーマンスWebサイト!

2012年1月2日月曜日

HttpBench on GitHub

年明け早々です!お正月生まれのツール。

HttpBench – GitHub

ApacheBenchにはいつもお世話になってます。でも、同じようにHTTPSも計測したいです。absめ!

localhostに対してab –n 100 –c 10 http://localhost/

hb3

localhostに対してhb –n 100 –c 10 http://localhost

hb4

それっぽいー。けど、手抜きすぎー。

せっかくなのでIIS ExpressでHTTPSへのリクエストを確認。

hb5 hb6

左がHTTPで右がHTTPS(IIS Expressの勝手証明書)。ab(abs)だとうまくできないですよね。

abだと、すごくたくさんオプション指定できるし、計測も細かい。流石です。が、hbはまだ全然。とりあえず実行回数/コンカレント数/BASIC認証、HTTP GETだけ。

あ。バイナリ配布ってどうしよ...。いつかすると思う。今はそんな段階でもないからいいよね。

コンカレントをMaxDegreeOfParallelismじゃなくて、Threadを作って処理してます。普通にTaskでもよかったのかなー。

hb7

↑-c 200指定。

目指せハイパフォーマンスWebサイト!

dotnetConf2015 Japan

https://github.com/takepara/MvcVpl ↑こちらにいろいろ置いときました。 参加してくださった方々の温かい対応に感謝感謝です。