この章では、最大パフォーマンスの実現を支援するチューニング方法を示します。第4章「ネットワーク・パフォーマンス・テストの実行」も参照してください。
この章には次の項が含まれます:
この項には、次のトピックが含まれます:
パケットの損失を最小限に抑えるには、オペレーティング・システムのソケット・バッファを大きくして、ガベージ・コレクション時にJavaアプリケーションが停止している間も受信ネットワーク・トラフィックを処理できるようにする必要があります。Coherenceはデフォルトで、2MBのソケット・バッファの割当てを試行します。オペレーティング・システムの構成で巨大なバッファを使用できないようにしている場合は、Coherenceはそれよりも小さなバッファを使用します。UNIXのほとんどのバージョンではデフォルトのバッファ制限が非常に小さく設定されていますが、これを少なくとも2MBに増大する必要があります。
オペレーシング・システムが完全なサイズのバッファの割当てに失敗すると、Coherenceは次の警告を発行します。
UnicastUdpSocket failed to set receive buffer size to 1428 packets (2096304 bytes); actual size is 89 packets (131071 bytes). Consult your OS documentation regarding increasing the maximum socket buffer size. Proceeding with the actual value may cause sub-optimal performance.
小さいバッファで操作を実行しても安全ですが、より大きなバッファを許容するようオペレーティング・システムを構成することをお薦めします。
Linuxの場合(rootとして実行):
sysctl -w net.core.rmem_max=2096304 sysctl -w net.core.wmem_max=2096304
Solarisの場合(rootとして実行):
ndd -set /dev/udp udp_max_buf 2096304
AIXの場合(rootとして実行):
no -o rfc1323=1 no -o sb_max=4194304
注意: AIXでは、1MB、4MBおよび8MBのバッファ・サイズの指定のみサポートされます。 |
Windowsの場合:
Windowsにはデフォルトのバッファ・サイズ制限はありません。
その他:
その他のオペレーティング・システムにおけるバッファ・サイズの拡大については、該当するオペレーティング・システムのドキュメントを参照してください。
Coherenceは、<packet-buffer
要素を使用することで、パケット・パブリッシャとユニキャスト・リスナーに、別のサイズに設定されたバッファを要求するように構成できます。
Linuxには選択可能な高分解能タイムソースがいくつか用意されていますが、残念なことに、最速のタイムスタンプ・カウンタ(TSC)でも常に信頼性があるとはかぎりません。LinuxではTSCがデフォルトで選択され、起動時のチェックで非一貫性が検出されると、より低速で安全なタイムソースへの切替えが行われます。低速なタイムソースでは、問合せの実行にTSCタイムソースの10 - 30倍のコストがかかることがあり、Coherenceのパフォーマンスに多大な影響を与える可能性があります。Coherenceおよび基礎となるJVMでは、オペレーティング・システムで使用しているタイムソースを認識しないことに注意してください。システム・ログ(/var/log/dmesg
)をチェックして、次のメッセージが記載されていないかどうか確認することをお薦めします。例6-1にタイムソース・ログのサンプルを示します。
例6-1 Linuxタイムソースのログ・メッセージ
kernel: Losing too many ticks! kernel: TSC cannot be used as a timesource. kernel: Possible reasons for this are: kernel: You're running with Speedstep, kernel: You don't have DMA enabled for your hard disk (see hdparm), kernel: Incorrect TSC synchronization on an SMP system (see dmesg). kernel: Falling back to a sane timesource now.
ログ・メッセージによると、これが、CPU使用率の変動(SpeedStep)、DMAの無効化、またはマルチCPUコンピュータに対する誤ったTSCの同期化などに起因して発生していることを示しています。存在する場合は、システム管理者と連係してその原因を特定および修正し、TSCタイムソースを使用できるようにします。Linuxの以前のバージョンの一部では、マルチプロセッサ・システムに非同期TSCに関連する不具合があります。この不具合の結果として、クロックが急に4398秒進んだすぐ後に正しい時刻に戻る場合があります。この不具合によって、ノードがクラスタから不適切に削除されるという結果をもたらす誤ったCoherenceパケット転送タイムアウトがトリガーされる場合があります。4398秒のタイムアウトの警告とともにクラスタの切断が生じた場合は、Linuxカーネルをアップグレードすることをお薦めします。このようなログ警告の例を次に示します。
A potential communication problem has been detected. A packet has failed to be delivered (or acknowledged) after 4398 seconds ...
Linux TSCに関するこの問題の詳細は、次のリソースを参照してください。
Microsoft Windowsでは、小さなデータグラムの送信時に使用される高速I/Oパスがサポートされます。小さいと見なされるデータグラムのデフォルト設定は1024バイトです。この値をネットワークMTUに合せて増大すると(通常は1500)、ネットワーク・パフォーマンスが著しく向上する可能性があります。
このパラメータを調整する手順は次のとおりです。
レジストリ エディタを実行します(regedit
)。
レジストリ・キーHKLM\System\CurrentControlSet\Services\AFD\Parameters
を見つけます。
新しいDWORD
値(Name:
FastSendDatagramThreshold
、Value:
1500
(decimal))を追加します。
再起動します。
注意: COHERENCE_HOME /bin/optimize.reg スクリプトは、この変更を実行します。スクリプトを実行したら、コンピュータを再起動して変更を有効にします。 |
このパラメータの詳細は、http://technet.microsoft.com/en-us/library/bb726981.aspx
の「Appendix C」を参照してください。
Windows (NT、2000、XPを含む)は、デスクトップ・アプリケーションの使用に合せて最適化されます。2つのコンソール(DOSボックス)ウィンドウを開くと、その他のプロセスに優先度の高い実行中のスレッドがあっても、フォーカスのある1つのコンソールがCPUのほぼ100%を使用してしまうことがあります。このアンバランスを修正するには、フォアグラウンド・アプリケーションが軽量で動作するようにWindowsのスレッド・スケジューリングを構成する必要があります。
「コントロール パネル」を開きます。
「システム」を開きます。
「詳細設定」タブを選択します。
「パフォーマンス」の「設定」を選択します。
「詳細設定」タブを選択します。
「プロセッサのスケジュール」で「バックグラウンド サービス」を選択します。
注意: COHERENCE_HOME /bin/optimize.reg スクリプトは、この変更を実行します。スクリプトを実行したら、コンピュータを再起動して変更を有効にします。 |
スワッピング(ページングと呼ぶこともあります)とは、RAMメモリーで使用するアプリケーション・データを格納および取得するために、2次記憶域を使用することです。スワッピングは、オペレーティング・システムによって自動的に実行されます。通常、使用可能なRAMメモリーが使い果たされたときに発生します。スワッピングは、Coherenceのパフォーマンスに大きな影響を与える可能性があるため、その発生を回避する必要があります。通常、スワッピング自体がCoherenceノードのクラスタからの削除を表します。これは、そのノードがRAMからスワップされることで、長時間の無応答状態が発生するためです。詳細は、「仮想メモリーの使用(ディスクへのページング)の回避」を参照してください。
スワッピングを回避するには、コンピュータに十分な使用可能RAMメモリーを搭載するか、実行プロセスの数を把握して使用可能なすべてのRAMを使い果たさないようにします。vmstat
やtop
(UnixとLinux)、taskmgr
(Windows)などのツールを使用して、スワップ・レートを監視してください。
Linuxのswappiness
Linuxでは、RAMに余裕があるときにも、プロセスやヒープの一部をスワップ・アウトするようにデフォルトで設定できます。swappinessは、最終的なメモリー・リクエストを処理するために実行されます。Coherence JVMに対するswappinessは避ける必要があります。Linuxではswappinessの設定値を0から100までの値に設定できます。値が大きいほど、楽観的なスワッピングが行われます。デフォルト値は、60です。Coherenceについては、常に低い値(可能ならば0)を設定する必要があります。
現在設定されているswappiness値を確認するには、コマンド・プロンプトで次のコマンドを入力します。
cat /proc/sys/vm/swappiness
一時的にswappinessを設定するには、rootユーザーとして/proc/sys/vm/swappiness
に値をエコーします。次の例では、値に0を設定しています。
echo 0 > /proc/sys/vm/swappiness
値を永続的に設定するには、/etc/sysctl.conf
ファイルを変更します。
Linuxのカーネル(2.4以降)では、ハードウェア割込み要求を複数のCPUまたはCPUコア全体にバランシングする機能があります。この機能は、SMP IRQアフィニティと呼ばれ、システム・パフォーマンスとCPU使用率を向上します。Coherenceの場合、クラスタ・メンバーをホストするすべてのサーバーにイーサネット・カードの割込みをバランシングすることで、大幅なパフォーマンスの向上が得られる可能性があります。
ほとんどのLinuxインストールでは、ネットワーク割込みのバランシングが構成されません。デフォルトのネットワーク割込みの動作では、すべてのネットワーク割込みの処理に1つのプロセッサ(通常はCPU0)を使用するため、大量のネットワーク・トラフィックがあると重大なパフォーマンス・ボトルネックになる可能性があります。ネットワーク割込みを複数のCPU間にバランシングすることで、ネットワークベースの操作のパフォーマンスが向上します。
SMP IRQアフィニティの構成方法の詳細は、要点のみが示された次のドキュメントを参照してください。
http://www.mjmwired.net/kernel/Documentation/IRQ-affinity.txt
システムのIRQの一覧を表示するには次のコマンドを実行します。この一覧には、IRQに割り当てられたデバイスと、そのデバイスに対して各プロセッサが処理した割込みの数が含まれます。
# cat /proc/interrupts
次の例は、1つのネットワーク・インタフェースを示す出力の一部です。この出力では、すべての割込みが同一のプロセッサ(CPU0)で処理されています。このネットワーク・カードには、複数の伝送および受信キューがあり、それらに独自のIRQが割り当てられています。複数のネットワーク・カードを使用するシステムは、追加のIRQを各カードに割り当てます。
CPU0 CPU1 CPU2 CPU3 65: 20041 0 0 0 IR-PCI-MSI-edge eth0-tx-0 66: 20232 0 0 0 IR-PCI-MSI-edge eth0-tx-1 67: 20105 0 0 0 IR-PCI-MSI-edge eth0-tx-2 68: 20423 0 0 0 IR-PCI-MSI-edge eth0-tx-3 69: 21036 0 0 0 IR-PCI-MSI-edge eth0-rx-0 70: 20201 0 0 0 IR-PCI-MSI-edge eth0-rx-1 71: 20587 0 0 0 IR-PCI-MSI-edge eth0-rx-2 72: 20853 0 0 0 IR-PCI-MSI-edge eth0-rx-3
目的は、1つのプロセッサではなく、4つのプロセッサ全体に割込みをバランシングすることです。理想としては、システムに装備されたプロセッサの全体的な使用率も使用して、どのプロセッサが割込みを処理できるかを判断します。mpstat
を使用すると、システムのプロセッサの統計を表示できます。この統計には、過剰に使用されているプロセッサと十分に使用されていないプロセッサが表示されるため、すべてのCPUにネットワーク割込みをバランシングする最適な方法を判断する際に役立ちます。
SMP IRQアフィニティは、smp_affinity
ファイルで構成します。各IRQには専用のsmp_affinity
ファイルがあります。このファイルは、/proc/irq/
irq_#
/
ディレクトリにあります。現在のIRQ(たとえば 65)のアフィニティ設定を確認するには、次のコマンドを実行します。
# cat /proc/irq/65/smp_affinity
戻される16進数値はビットマスクであり、IRQ 65の割込みがルーティングされるプロセッサを表します。値の各桁は、4個のCPUからなるグループを表します。4個のプロセッサのシステムの場合、4個のすべてのプロセッサのグループを表す16進数値は、f(つまり15)になり、次のようにマップされるときには00000fになります。
Binary Hex CPU 0 0001 1 CPU 1 0010 2 CPU 2 0100 4 CPU 3 1000 8 ----------------------- all 1111 f
1個のプロセッサまたはプロセッサのグループを対象にするには、ビットマスクを適切な16進数値に変更する必要があります。前述の例で示したシステムについて説明すると、IRQ 65のすべての割込みをCPU1にルーティングして、IRQ 66のすべての割込みをCPU2にルーティングするには、smp_affinity
ファイルを次のように変更します。
echo 000002 > /proc/irq/65/smp_affinity # eth0-tx-0 echo 000004 > /proc/irq/66/smp_affinity # eth0-tx-1
IRQ 65のすべての割込みをCPU1とCPU2の両方に振り分ける場合は、smp_affinity
ファイルを次のように変更します。
echo 000006 > /proc/irq/65/smp_affinity # eth0-tx-0
各IRQのすべての割込みを、すべてのCPUに振り分ける場合は、smp_affinity
ファイルを次のように変更します。
echo 00000f > /proc/irq/65/smp_affinity # eth0-tx-0 echo 00000f > /proc/irq/66/smp_affinity # eth0-tx-1 echo 00000f > /proc/irq/67/smp_affinity # eth0-tx-2 echo 00000f > /proc/irq/68/smp_affinity # eth0-tx-3 echo 00000f > /proc/irq/69/smp_affinity # eth0-rx-0 echo 00000f > /proc/irq/70/smp_affinity # eth0-rx-1 echo 00000f > /proc/irq/71/smp_affinity # eth0-rx-2 echo 00000f > /proc/irq/72/smp_affinity # eth0-rx-3
ネットワーク・カード(NIC)が最大リンク速度および全二重で動作するよう構成されていることを確認します。この確認処理はオペレーティング・システムにより異なります。
Linuxの場合(rootとして実行):
ethtool eth0
インタフェース設定の調整方法および詳細は、ethtool
のmanページを参照してください。
Solarisの場合(rootとして実行):
kstat ce:0 | grep link_
これにより、インタフェース0のリンク設定が表示されます。重要な項目はlink_duplex
(全二重は2)とlink_speed
(Mbps単位)です。
Windowsの場合:
「コントロール パネル」を開きます。
「ネットワーク接続」を開きます。
目的のネットワーク・アダプタの「プロパティ」ダイアログを開きます。
「構成」を選択します。
「詳細設定」タブを選択します。
「リンク速度とデュプレックス」でドライバ固有のプロパティを見つけます。
このプロパティを「自動検出」または特定のリンク速度とデュプレックスに設定します。
1Gb以上のPCIネットワーク・カードでは、システムのバス速度がネットワークのパフォーマンスを制限する要因になることがあります。PCIおよびPCI-Xバスは半二重で、すべてのデバイスはそのバス上のデバイスの最低速度で実行されます。標準のPCIバスには最大約1Gb/秒のスループットがありますが、全二重の1GbのNICを使用してそのスループットを実現することはできません。PCI-Xにはさらに高い最大スループットがありますが(1GB/秒)、バス上に低速のデバイスが1つでもあるとそれが足かせとなります。満足な双方向のデータ・レートを実現できない場合は、コンピュータのバス構成を評価してください。たとえば、NICをプライベート・バスに再配置するだけでパフォーマンスが向上する場合もあります。
複数のクラスタ・ノード間で数秒間にわたる通信の停止が頻繁に発生する場合は、スイッチのバッファ領域を拡大してみてください。このような通信の停止は、ローカルまたはリモートのGCに起因しない、複数ノードでの通信の遅延を特定する一連のCoherenceログ・メッセージにより特定できます。
例6-2 通信の遅延を示すメッセージ
Experienced a 4172 ms communication delay (probable remote GC) with Member(Id=7, Timestamp=2006-10-20 12:15:47.511, Address=192.168.0.10:8089, MachineId=13838); 320 packets rescheduled, PauseRate=0.31, Threshold=512
Cisco 6500シリーズなどの一部のスイッチでは、各イーサネット・ポートまたはASICで使用可能なバッファ領域の容量を構成できます。負荷の高いアプリケーションでは、デフォルトのバッファ領域の増大が必要になる場合があります。Ciscoでこれを実現するには、次を実行します。
fabric buffer-reserve high
この設定の詳細は、Ciscoのドキュメントを参照してください。
クラスタ・メンバーは複数のスイッチにわたって分割されていることがあり、複数のサブネットに含まれている可能性があります。ただし、そのようなトポロジではクラスタ通信に対するネットワーク遅延の影響が桁違いに大きくなる可能性があります。不安定な形で、この影響は通信の遅延として具現化され、クラスタとアプリケーションのパフォーマンスに影響を与えます。ネットワーク遅延の影響を最小化するために、可能な場合は、すべてのクラスタ・メンバーを同一のスイッチとサブネットに配置することを常に検討してください。
「本番ネットワークの速度の評価」も参照してください。
全二重イーサネットにはフロー制御機能があります。これにより、固定リンクの受信側に合せて送信側の速度を低下させることができます。これは、受信側からイーサネットPAUSEフレームを送信側に送信することで実行します。PAUSEフレームで指定された期間、送信側は送信を停止します。この停止により、負荷の高くないコンピュータに送信するトラフィックも含め、送信側のすべてのトラフィックがブロックされます。これには行頭ブロック条件が含まれる場合があります。その場合、スイッチ上に過負荷のコンピュータが1つあると、その他すべてのコンピュータ速度が実質的に低下します。ほとんどのスイッチ・ベンダーは、スイッチ・リンク間のイーサネットのフロー制御を無効にして、多くてもコンピュータに直接接続されているポートでのみ使用することをお薦めします。この設定でも行頭ブロックは発生する可能性があるため、イーサネットのフロー制御は無効にすることをお薦めします。TCP/IPやCoherence TCMPなどのより高いレベルのプロトコルには、行頭ブロックの影響を受けず、低レベルのフロー制御も必要としない独自のフロー制御メカニズムがあります。
この問題の詳細は、http://www.networkworld.com/netresources/0913flow2.html
を参照してください。
Coherenceはデフォルトで1500バイトのネットワークMTUを想定し、その想定に基づいて、1468バイトのデフォルトのパケット・サイズを使用しています。パケット・サイズがMTUを満たさないと、ネットワークは有効に活用されません。機器が使用するMTUが異なる場合は、ネットワーク・パスの最小MTUよりも32バイト小さい値を<packet-size
設定に指定してCoherenceを構成します。
ノード間の完全なパスを経由する機器のMTUが不明な場合は、そのMTUを特定するために、標準のping
やtraceroute
ユーティリティを使用できます。たとえば、2つのコンピュータ間で一連のpingまたはtraceroute操作を実行します。それぞれの試行において、最初は大きいパケット・サイズを指定し、断片化されずにパケットが処理されるようになるまで徐々に値を下げていきます。
Linuxの場合、次を実行します。
ping -c 3 -M do -s 1468 serverb
Solarisの場合、次を実行します。
traceroute -F serverb 1468
Windowsの場合、次を実行します。
ping -n 3 -f -l 1468 serverb
その他のオペレーティング・システムについては、ドキュメントでping
またはtraceroute
コマンドについて調べて、断片化の回避方法を考慮した上でパケット・サイズを指定してください。
パケットを断片化する必要があるというメッセージが出力される場合、指定したサイズはパスのMTUより大きいことになります。断片化せずにパケットを送信できるサイズがわかるまでパケット・サイズを小さくしていきます。1468より小さいパケットを使用する必要がある場合は、MTUを少なくとも1500まで拡大するようネットワーク管理者に問い合せてください。
この項で示す推奨事項は、一般的な使用の場合には十分で、必要な設定作業は最小限です。JVMのサイズ設定時に考慮すべき第一の問題は、使用可能なRAMとガベージ・コレクション(GC)一時停止時間とのバランスです。
キャッシュ・サーバー
Coherenceキャッシュ・サーバーについての標準的で安全な推奨事項として、固定のヒープ・サイズを4GB以下にして実行することをお薦めします。さらに、増分ガベージ・コレクタを使用して、GC一時停止時間を最小限に抑えます。最後に、JVMコマンドラインで-server
を指定して、すべてのCoherence JVMをサーバー・モードで実行することをお薦めします。これにより、長期間稼働するアプリケーションにいくつかの点で最適なパフォーマンスが得られます。
例:
java -server -Xms1g -Xmx1g -Xincgc -Xloggc: -cp coherence.jar com.tangosol.net.DefaultCacheServer
このサイズ設定では、より詳細なJVMチューニングの必要がなく、適切なパフォーマンスが得られます。ガベージ・コレクションの詳細は、「ガベージ・コレクションの監視」を参照してください。
ヒープ・サイズを大きく(JDK 6では最大20GBのヒープ)することが可能であるため、本番環境では大きなヒープ・サイズ実装されていますが、それによりGC一時停止を最小限に抑えるためのJVMの監視とチューニングがさらに重要になります。スクラッチ領域の容量を増やしてGCの圧縮がより迅速になるように、記憶域の比率の変更が必要になる場合もあります。また、大きなサイズのヒープの管理が大幅に向上する最新バージョンのJVM (HotSpot 1.6など)を利用することをお薦めします。詳細は、「ヒープ・サイズに関する考慮事項」を参照してください。
キャッシュ・クライアント
長時間稼働するGCが原因で、Coherence TCMPクライアントが停止しているとの誤認識が生じる可能性があるため、Coherence TCMPクライアントも同様にサーバーをキャッシュするように構成する必要があります。
Extendクライアント
専門的に言えば、Coherence Extendクライアントはクラスタ・メンバーではなく、このため、長時間稼働するGCからの影響が小さいです。Extendクライアントの場合、Coherenceの埋込み先のアプリケーションで説明されているとおりに既存のガイドラインに従うことをお薦めします。
この項では、次の事項を決定します。
システムに必要なCPUの数
各システムに必要なメモリーの量
システムごとに実行するJVMの数
JVMごとに構成するヒープのサイズ
すべてのアプリケーションがそれぞれ異なるため、この項をガイドラインとしてよく読む必要があります。適切な構成を選択するには次の質問に対する答えが必要になります。
Coherenceキャッシュに格納することになるデータの量はどのくらいか。
待機時間とスループットに関するアプリケーション要件は何か。
アプリケーションはどれくらいCPUまたはネットワーク集中型か。
サイズ設定は、不正確な技法です。パフォーマンスおよび負荷の頻繁なテストに代わるものはありません。
この項には、次のトピックが含まれます:
固定サイズのヒープを使用して実行すると、必要に応じてJVMでヒープを増大する必要がなくなり、パフォーマンスが向上します。固定のヒープ・サイズを指定するには、JVMオプションの-Xms
と-Xmx
を同じ値に設定します。例:
java -server -Xms4G -Xmx4G ...
1つのJVMプロセスでは、指定されているヒープ・サイズより多くのシステム・メモリーが消費されます。ヒープ・サイズ設定によって、JVMでアプリケーションに使用できるヒープの量が指定されますが、JVM自体もさらにメモリーを消費します。消費される量は、オペレーティング・システムおよびJVM設定によって異なります。たとえば、Linuxで実行し1GBのJVMで構成されたHotSpot JVMでは、約1.2GBのRAMが消費されます。JVMのメモリー使用量を外部で測定して、RAM負荷率が大きくなりすぎないようにすることが重要です。top
やvmstat
などのツール、およびタスク・マネージャは、実際に使用されているRAMの量の特定に役立ちます。
記憶域の比率
指定したサイズのキャッシュ・サーバー内に格納できるデータの量として、プライマリ・キャッシュ記憶域のヒープの3分の1以下に使用を抑えることを基本的にお薦めします。これによって、次の3分の1をバックアップ記憶域に、最後の3分の1をスクラッチ領域に割り当てることができます。スクラッチ領域は、クラスの保持、一時オブジェクト、ネットワーク転送バッファ、GC圧縮などに使用します。<high-units>
要素を構成して、<unit-calculator>
要素にBINARY
値を指定することによって、キャッシュごとにプライマリ記憶域を制限するようCoherenceを設定することができます。これらの設定は、バックアップ記憶域にも自動的に適用されます。
プライマリ記憶域とバックアップ記憶域の両方が、JVMに確保されている領域内に収まるようにすることが理想です(HotSpotベースのJVMの場合)。コレクタ生成のサイズ設定の詳細は、次のHotSpotのガベージ・コレクションのチューニング・ガイドを参照してください。
http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html
キャッシュ・トポロジとヒープ・サイズ
大きなデータセットには、パーティション・キャッシュまたはニア・キャッシュをお薦めします。Coherence JVMの数が変化してもキャッシュのパフォーマンスに大きな影響はありません。パーティション・キャッシュのスケーラビリティは、読取りと書込みのどちらについても直線的であるためです。レプリケーション・キャッシュを使用すると、GCに対する負荷がきわめて大きくなります。
データ・グリッド操作用のキャパシティの計画
データ・グリッド操作(問合せや集計など)には、別のヒープ領域の要件があり、この操作を使用するときにはそれに応じた計画を立てる必要があります。データ・グリッド操作とは、メモリー内に保持される結果セットに含まれるキャッシュ・エントリのバイナリ表現のことです。操作によっては、このエントリは、その操作の期間中はデシリアライズされた形式で保持されることもあります。一般に、これは結果セット内の各エントリのメモリー量を倍増します。さらに、バッキング・マップの実装としてRAMまたはフラッシュのジャーナリングを使用しているときには、オブジェクトの格納方法に違いがあるために2番目のバイナリ・コピーが保持されます。2番目のバイナリ・コピーは、操作期間中も保持されるため、結果セット内の各エントリのための合計メモリーは3倍に増加します。
ヒープ・メモリーの使用率は、操作の実行対象になる結果セットのサイズと、処理される同時リクエストの数によって異なります。結果セットのサイズは、エントリの合計数と、各エントリのサイズに影響を受けます。記憶域キャッシュ・サーバーに維持された適度なサイズの結果セットは、ヒープのメモリーを使い果たす可能性はほとんどありません。ただし、結果セットが著しく大きい場合は、追加のメモリー要件によってヒープがメモリーを使い果たしてしまうことがあります。一般に、データ・グリッドの集計操作には巨大なデータセットが伴われるため、その他の操作よりも使用可能メモリーを使い果たしてしまう可能性が高くなります。
JVMのヒープ・サイズは、巨大な結果セットが予想されるときには、記憶域が有効なキャッシュ・サーバーで拡大しておく必要があります。ヒープの3分の1をスクラッチ領域に予約している場合(前述の推奨値)、割り当てられているスクラッチ領域が予想される結果セットのサイズをサポートできるようにします。別の方法として、データ・グリッド操作にはPartitionedFilter
APIを使用できます。このAPIは、個別のバーティション・セットに対してグリッド操作を実行することで、メモリーの消費量を低減します。このAPIの使用の詳細は、Oracle Coherence Java APIリファレンスを参照してください。
システムごとに実行するJVMの数の決定
システムごとに実行するJVM(ノード)の数は、システムのプロセッサ/コア数とメモリー量によって異なります。出発点として、2つのコアごとに1つのJVMを実行することを計画してください。この推奨内容によって、次の要素のバランスが取れます。
サーバーごとに複数のJVMを使用することによって、Coherenceでネットワーク・リソースをより効率的に使用できるようになります。Coherenceのpacket-publisherとpacket-receiverでは、JVMごとのスレッドの数が固定されます。コアを追加すると、それらのコア間でスケーラビリティを向上できるようにJVMを追加できます。
JVMが多すぎると、プロセッサでの競合とコンテキスト・スイッチングが多くなります。
JVMが少なすぎると、使用可能なメモリーを処理できない場合や、NICを完全に使用できない場合があります。
特に、大きなヒープ・サイズの場合、JVMには、長時間のGC休止を避けるための処理能力が必要です。
アプリケーションに応じて、1つのコアにつき1つになるまでJVMを追加できます。JVMの推奨数と構成されたヒープ・サイズも、ソケットごとのプロセッサ/コアの数とコンピュータのアーキテクチャによって異なる場合があります。
ヒープのサイズ設定
ヒープ・サイズを検討する際は、適切なバランスを見つけることが重要です。下限はJVMごとのオーバーヘッドによって(または潜在的に数が増大する可能性のあるJVMの管理のしやすさによっても)決まります。たとえば、インフラストラクチャ・ソフトウェア(JMXエージェント、接続プール、内部JVM構造など)に100MBの固定オーバーヘッドがある場合、ヒープ・サイズが256MBのJVMを使用すると、非キャッシュ・データのオーバーヘッドは約40%になります。JVMヒープ・サイズの上限はメモリー管理のオーバーヘッドによって決まります。特に、GCの最大一時停止時間やGCに割り当てられているCPUの割合(およびその他のメモリー管理タスク)によって決まります。
GCは次の項目に影響を及ぼす可能性があります。
Coherenceに対する操作の待機時間。ヒープが大きいほど、小さいヒープより待機時間が長くなり、予測が難しくなります。
クラスタの安定性。非常に大きいヒープの場合、JVMはGC一時停止の間は応答しなくなるため、非常に長いガベージ・コレクション休止によって、クラスタ・メンバーが停止しているとTCMPが誤認識する可能性があります。TCMPではメンバーのヘルス状態を判断する際にGC一時停止が考慮されますが、ある時点でそのメンバーは停止していると判断される場合があります。
次のガイドラインが示されています。
Oracle 1.6 JVMまたはJRockitの場合、ほとんどのアプリケーションに対して、控えめな4GBのヒープ・サイズをお薦めします。このサイズは、スループット、遅延および安定性に基づいています。ただし、多数の小さなJVMから得られるパフォーマンスのメリットよりも、少数の大きなJVMから得られる管理の簡易化のほうが重要になる一部のアプリケーションには、大きなヒープ・サイズ(最大20GB)が適しています。コア対ヒープの比率は、おおよそ1コア対2GBが理想的ですが、コアごとに数GB追加して余裕を持って使用できるようにします(3GBまたは4GB)。アプリケーションごとに違いがあるため、それに応じてGCを監視する必要があります。
OracleのConcurrent Mark and Sweep (CMS) GC (-XX:+UseConcMarkSweepGC
)、またはJRockitのDeterministic GC (-Xgcprio:deterministic
)を使用すると、GCのパフォーマンスが向上します。
GC一時停止の長さは、ヒープ・サイズに対して直線的でなく、もっと悪い比率で増加します。つまり、ヒープ・サイズが2倍になると、一般に、GCによる一時停止時間は2倍より長くなります。GC一時停止は、アプリケーション使用状況の影響も受けます:
ヒープ内のライブ・データ量が増すにつれ、一時停止時間が長くなります。ヒープ内のライブ・データが70%を超えないようにしてください。これにはプライマリ・データ、バックアップ・データ、インデックス、およびアプリケーション・データが含まれます。
オブジェクト割当て率が高いと一時停止時間が長くなります。それぞれのネットワーク・パケットで多くのオブジェクトが生成されるため、単純なCoherenceアプリケーションでさえ、オブジェクト割当て率が高くなる場合があります。
CPU集中型の処理によって、競合が増え、一時停止時間が長くなる場合もあります。
待機時間の要件に応じて、前述で推奨した値より大きいヒープ領域を割り当てることができますが、必ずシステムの負荷テストを実行してください。
パーティション・キャッシュの記憶域に専用のCoherenceキャッシュ・サーバー・インスタンスを使用すると、データがローカルに保存されなくなるため、アプリケーションJVMのヒープ・サイズが最小限に抑えられます。大半のパーティション・キャッシュ・アクセスはリモートで実行される(データの1/N
のみがローカルに保持される)ので、専用キャッシュ・サーバーを使用しても、通常は追加のオーバーヘッドはあまり増大しません。ニア・キャッシュ・テクノロジを使用することもできます。このテクノロジは、通常、ヒープ・サイズに最小限の影響しか及ぼしません(パーティション・キャッシュよりもさらに小さなサブセットをキャッシュするためです)。多くのアプリケーションでヒープ・サイズを著しく減らし、応答性を改善できます。
ローカルのパーティション記憶域は、tangosol.coherence.distributed.localstorage
Javaプロパティ(-Dtangosol.coherence.distributed.localstorage=false
など)を使用して有効化(キャッシュ・サーバーの場合)または無効化(アプリケーション・サーバーの場合)できます。
また、tangosol-coherence.xml
(またはtangosol-coherence-override.xml
)ファイルの<local-storage>
設定を次のように変更して無効化することもできます。
例6-3 パーティション記憶域の無効化
<?xml version='1.0'?> <coherence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.oracle.com/coherence/coherence-operational-config" xsi:schemaLocation="http://xmlns.oracle.com/coherence/ coherence-operational-config coherence-operational-config.xsd"> <cluster-config> <services> <!-- id value must match what's in tangosol-coherence.xml for DistributedCache service --> <service id="3"> <init-params> <init-param id="4"> <param-name>local-storage</param-name> <param-value system-property="tangosol.coherence.distributed. localstorage">false</param-value> </init-param> </init-params> </service> </services> </cluster-config> </coherence>
記憶域が無効なクライアントがキャッシュにアクセスする前に、記憶域が有効なJVMが少なくとも1つ起動している必要があります。
長時間のGC一時停止時間はCoherenceクラスタに悪影響を与えることがあり、通常はノードの停止と区別が付きません。Javaアプリケーションは、このような一時停止中にパケットを送受信できません。オペレーティング・システムがバッファしているパケットの受信については、そのパケットは破棄されることがあるため、再送信する必要があります。このため、GC一時停止時間が最小限になるようにクラスタ・ノードのサイズを設定、調整することが重要です。一般的に、ノードの停止時間のうちGCによるものを10%未満に抑え、通常のGC一時停止時間を100ミリ秒未満に抑え、最大のGC一時停止時間を1秒程度にすることが必要です。
GCのチューニングの詳細は、次のHotSpotガベージ・コレクション・チューニング・ガイドを参照してください。
http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html
あるクラスタ・ノードが別のクラスタ・ノードについて一定時間応答のないことを検出した場合、ログ・メッセージが生成されます。このメッセージは一般に、ターゲットのクラスタ・ノードがGCサイクルにあることを示しています。
例6-4 ターゲットのクラスタ・ノードがガベージ・コレクション・モードであることを示すメッセージ
Experienced a 4172 ms communication delay (probable remote GC) with Member(Id=7, Timestamp=2006-10-20 12:15:47.511, Address=192.168.0.10:8089, MachineId=13838); 320 packets rescheduled, PauseRate=0.31, Threshold=512
PauseRate
は、統計が最後にリセットされてからノードが応答なしと見なされるまでの時間の割合を示します。稼働時間に対して応答しない時間の割合が数パーセント以上あるとレポートされたノードは、GCのチューニングを調査する必要があります。
GCアクティビティは、様々な方法で監視できます。いくつかのOracle JVMメカニズムを次に示します。
-verbose:gc
(標準出力にGCログを書き込みます。出力先をカスタムの場所に変更する場合は、-Xloggc
を使用します)
-XX:+PrintGCDetails
、-XX:+PrintGCTimeStamps
、-XX:+PrintHeapAtGC
、-XX:+PrintTenuringDistribution
、-XX:+PrintGCApplicationStoppedTime
-XX:+PrintGCApplicationConcurrentTime
-Xprof
: プロファイリングを有効にします。プロファイリングのアクティビティは、テストと本番デプロイメントとで区別する必要があり、リソースとパフォーマンスに対する影響を常に監視する必要があります。
JConsole、VisualVM (VisualGCプラグインを含む)、およびJRockit Misson Control
Coherenceには、ネットワーク上でのトラフィックの量を調整するための、<traffic-jam
および<flow-control
TCMP構成要素があります。これらの設定は、クラスタ・ノード内およびクラスタ・ノード間のパケット・フローの速度を制御するために使用します。これらの設定の構成の詳細は、『Oracle Coherence開発者ガイド』を参照してください。
前述の設定がパフォーマンスにどれほど影響しているかをチェックするには、クラスタ・ノードにパケットの損失や重複があるかどうかをチェックします。これは、様々なクラスタ・ノード上で次のJMXの統計を確認するとチェックできます。
ClusterNodeMBean.PublisherSuccessRate
: 1.0未満である場合は、パケットが失われ再送信されていることがわかります。レートが0.98未満であれば、調査および調整が必要になる場合があります。
ClusterNodeMBean.ReceiverSuccessRate
: - 1.0未満であれば、同じパケットが複数回受信されています(重複しています)。これは、パブリッシャがパケットの損失を過度に申告していることに起因している可能性があります。
ClusterNodeMBean.WeakestChannel
: 現在のノードとの通信が最も困難なリモート・クラスタ・ノードを特定します。
JMXを使用したCoherenceの監視の詳細は、『Oracle Coherenceマネージメント・ガイド』を参照してください。
大きなデータセットをキャッシュしている場合、一般には、そのデータセットのほんの一部で大半のデータ・アクセスに対応しています。たとえば、1000個のオブジェクトのデータセットの場合、操作の80%は100個のオブジェクトのサブセットに対するものになる場合があります。残り20%の操作は、その他900個のオブジェクトに対して実行される場合があります。言うまでもなく、最も高い投資対効果は、100個の最もアクティブなオブジェクトをキャッシュすることで得られます。残り900個のオブジェクトをキャッシュすると、さらに25%有効性の高いキャッシングを実現できますが、リソースについては900%の増大が必要になります。
ただし、すべてのオブジェクトが同頻度でアクセスされる場合(データセットの順次スキャンなど)は、同レベルの有効性を得るためにより多くのリソースが必要になります。この場合、80%のキャッシュの有効性を実現するためには、10%ではなく80%のデータセットのキャッシュが必要になります(部分的にキャッシュされたデータセットの順次スキャンは、通常、MRU、LFUおよびMRU-LFUのエビクション・ポリシーに優先することに注意してください)。実際、ほとんどの非統合(ベンチマーク)データ・アクセス・パターンは不規則であるため、データのサブセットをキャッシュすることで処理速度は速くなります。
データのサブセットがアクティブであり、そのより小さなサブセットが特にアクティブである場合は、All無効化戦略を指定したニア・キャッシュの使用が非常に有用になることがあります(実際には、これは前述のルールの2層拡張になります)。
Coherenceのニア・キャッシュ・テクノロジでは、特にPresent無効化戦略を指定している場合、クラスタ・ノード・アフィニティを透過的に利用します。このトポロジはスティッキーなロード・バランサで使用すると特に有用です。キャッシュのフロント部分がスラッシングされる(キャッシュ・エントリの存続期間が非常に短い)場合、Present無効化戦略のオーバーヘッドは(Allに比べて)高くなることに注意してください。これは、キー・レベルのイベント・リスナーの追加/削除のオーバーヘッドがより高いためです。一般にキャッシュはスラッシングしないよう調整されるため、通常は問題にはなりません。
一般には、次のキャッシュ・トポロジと使用例の組合せが最適です。
レプリケーション・キャッシュ: 少量の読取り頻度の高いデータ(メタデータなど)
パーティション・キャッシュ: 大量の読取り/書込みデータ(大きなデータ・キャッシュなど)
ニア・キャッシュ: パーティション・キャッシュに似ていますが、読取り頻度の高い段階的なアクセス・パターン(ホットスポットのある大きなデータ・キャッシュなど)やスティッキーなデータ・アクセス(スティッキーなHTTPセッション・データなど)で使用するとさらに有用です。同期化の方法(失効、非同期、同期)に応じて、最悪の場合のパフォーマンス・レベルは、パーティション・キャッシュと同等のレベルから、それよりも大幅に低いレベルまで変動します。
インターリーブとは、キャッシュへの書込み間に発生するキャッシュの読取り数のことを指します。パーティション・キャッシュはインターリーブの影響を受けません(1:1のインターリーブで設計されているため)。一方、レプリケーション・キャッシュとニア・キャッシュは読取り頻度の高いキャッシュに合せて最適化されるため、読取り頻度の高いインターリーブ(各書込み間に10回の読取りなど)が適しています。これは、これら両方のキャッシュが、後続の読取りアクセス用にデータをローカルにキャッシュするためです。キャッシュへの書込みが行われると、ローカルにキャッシュされているこれらの項目は強制的にリフレッシュされますが、これは(ローカル・メモリー・ヒープからオブジェクトをフェッチするほぼゼロ・コストと比べて)比較的コストのかかる処理です。それでも、ニア・キャッシュ・テクノロジを使用する場合の最悪のパフォーマンス・レベルはパーティション・キャッシュと同レベルであり、パフォーマンス・ロスは最良のシナリオと比較した場合の損失になります。
インターリーブは(間接的にですが)読取り/書込み率に関係することに注意してください。たとえば、1:1の読取り/書込み率のニア・キャッシュでは、処理が非常に高速になるか(すべての書込み後にすべての読取りを実行)、非常に遅くなる可能性があります(1:1のインターリーブで書込みと読取りを交互に実行)。