ip_vsのhash tableについて調べてみた

ipvsadm -Ln しか使わない現場も多いと思います。
しかしip_vsについてちょっと気になって調べてみたらものすごい奥が深いことがわかりました。

自分の会社ではほぼすべてのトラフィックをグローバルIPを持たせたLVSマシンで受けています。
また提供しているサービスの特性で、ipvsadmのタイムアウトを短くしていても、多いときで30万ちょっとくらいのセッションがあります。

ipvsadm -Ln でも確認できるのですが、ipvsadm -Lnc | wc -l を以前から使っていました。
これはip_vsが保持しているセッションのリストを表示するオプションです。

とまあ、ここまでは理解していたんですが、 netfilterとかチューニングしてる過程でハッシュのチューニングとかしたし、何十万本もコネクションリストもってるip_vsも、実はコネクションリストを高速でスキャンするためのハッシュ領域があるんじゃね?と、思い調べ始めました。

ちなみに、ip_vsは新しいコネクションを作ろうとするたびにすべてのコネクションリストを評価する、とどこかに書いてありました。どこかに。何十万もセッションがある状態で、ハッシュが効率よく使われていないとしたら、恐ろしいCPUのリソースを無駄に消費してることになります。

調べたところハッシュの実体はすぐ見つかりました。以下の size=4096 です。

$ sudo ipvsadm -L                                                                                 
IP Virtual Server version 1.2.1 (size=4096)

果たしてこの値が最適なのか、変更できるかは以下のリンクを参考にしました。

http://daretoku-unix.blogspot.jp/2011/04/ipvs.html

IPVS 接続ハッシュテーブルはハッシュの衝突を扱うのにチェイニングスキーム
を使っています。大きなIPVS接続ハッシュテーブルを使うと100,000単位の
コネクションを扱う場合においてハッシュテーブルの衝突を大きく減らします。

デフォルト値ではせいぜい10万くらいがいいところというみたいです。
また実メモリの使用量なども書いてありますが、計算すればいいだけなので割愛します。

値の増やし方は以下のリンクを参考にしました。

http://kb.linuxvirtualserver.org/wiki/Performance_and_Tuning

カーネルを再構築しないとダメみたいです。

やたらめったらコネクションが多い場合は増やしたほうがいいということですね。
また自分の現場では設定済みですが、コネクションはタイムアウトを短くすることで減らすことができます。netfilterと一緒ですね。

ipvsadm --set tcp tcpfin udp(それぞれ秒)

そしてここまで調べて気になったのが”ハッシュの衝突”という表現です。

衝突したらコネクションは破棄されてしまうのか?もしかしてリハッシュとかしてCPUに余計なコストがかかってるんじゃないか?
など、気になり調べてみたんですが、ここまでくるとインフラではなくプログラミングのアルゴリズムの話です。

”ハッシュの衝突を扱うのにチェイニングスキーム”を使う、とドキュメントには書いてあります。
チェイニングスキームについてすぐ出てきたドキュメントが以下のリンクになります。(wikipediaですが・・・)

http://en.wikipedia.org/wiki/Hash_table#Separate_chaining

同じハッシュに複数の値が入るというアルゴリズムのようです。

プログラムをしっかり勉強した方ならわかると思いますが、ハッシュがコリジョンする確率とか、その場合の回避方法をいくつかしっていると思います。

ip_vsはパフォーマンスをできる限り優先するために、チェイニングスキームで多少コストがかかっても、生のコネクションリストをなめるよりはるかに早いので、多くのハッシュエントリーを確保して、コネクションリストをできるかぎり高速でスキャンするという設計思想みたいです。

ハッシュの衝突を回避するためには、そもそも箱を大きくすれば当たらないということですね。
デフォルトが小さすぎるんです。

ついでなんですが、32bitだと95%の確立を保てるのは15万前後のようです。

http://preshing.com/20110504/hash-collision-probabilities

興味深いですね。
誕生日パラドックスとか誕生日攻撃とか、ついでにいろいろ調べていて目に入りました。

知れば納得です。
こんどはnetfilterのハッシュの扱いについて調べてみようと思います。

当然ですがカーネルを再構築したところ確かにふえました。

$ sudo ipvsadm -L
IP Virtual Server version 1.2.1 (size=1048576)
Prot LocalAddress:Port Scheduler Flags
 -> RemoteAddress:Port Forward Weight ActiveConn InActConn

コメントを残す

メールアドレスが公開されることはありません。


*