この章の内容は次のとおりです。
この項には次のトピックが含まれます:
オペレーティング・システムのソケット・バッファを大きくすると、ガベージ・コレクション中のパケット・ロスを最小限にするのに役立ちます。各Coherenceソケットの実装では、デフォルトのソケット・バッファ・サイズの割当てを試行します。デフォルト・サイズの割当てができない場合は警告メッセージが各ソケットの実装に記録されます。次の例は、インバウンドUDPソケット・バッファのメッセージを示しています。
UnicastUdpSocket failed to set receive buffer size to 16 packets (1023KB); actual size is 12%, 2 packets (127KB). Consult your OS documentation regarding increasing the maximum socket buffer size. Proceeding with the actual value may cause sub-optimal performance.
より大きいサイズのバッファを許可するようにオペレーティング・システムを構成することをお薦めします。ただし、<packet-buffer
要素を使用して、Coherenceパケット・パブリッシャとユニキャスト・リスナーに別のバッファ・サイズを構成できます。Oracle Coherenceでのアプリケーションの開発のパケット・バッファのサイズの構成を参照してください。
注意:
UNIXのほとんどのバージョンではデフォルトのバッファ制限が非常に小さく設定されていますが、これを少なくとも2MBに増大する必要があります。また、UDPの推奨事項は、TCPを優先するようにUDPが明示的に構成されている構成にのみ適用可能です。これは、パフォーマンスが重要なタスクのデフォルトがTCPであるためです。
Linuxの場合(rootとして実行):
sysctl -w net.core.rmem_max=2097152 sysctl -w net.core.wmem_max=2097152
Solarisの場合(rootとして実行):
ndd -set /dev/udp udp_max_buf 2097152
AIXの場合(rootとして実行):
no -o rfc1323=1 no -o sb_max=4194304
注意:
AIXでは、1MB、4MBおよび8MBのバッファ・サイズの指定のみサポートされます。
Windowsの場合:
Windowsにはデフォルトのバッファ・サイズ制限はありません。
その他:
その他のオペレーティング・システムにおけるバッファ・サイズの拡大については、該当するオペレーティング・システムのドキュメントを参照してください。
Linuxには選択可能な高分解能タイムソースがいくつか用意されていますが、残念なことに、最速のタイムスタンプ・カウンタ(TSC)でも常に信頼性があるとはかぎりません。LinuxではTSCがデフォルトで選択され、起動時のチェックで非一貫性が検出されると、より低速で安全なタイムソースへの切替えが行われます。低速なタイムソースでは、問合せの実行にTSCタイムソースの10 - 30倍のコストがかかることがあり、Coherenceのパフォーマンスに多大な影響を与える可能性があります。TSCの詳細は、次を参照してください。
https://lwn.net/Articles/209101/
Coherenceおよび基礎となるJVMでは、オペレーティング・システムで使用しているタイムソースを認識しないことに注意してください。システム・ログ(/var/log/dmesg
)をチェックして、次のメッセージが記載されていないかどうか確認することをお薦めします。
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タイムソースを使用可能にしてください。
Microsoft Windowsでは、小さなデータグラムの送信時に使用される高速I/Oパスがサポートされます。デフォルト設定で小さいと見なされるデータグラムは、1024バイトです。この値をネットワークの最大転送単位(MTU)に合せて増加すると(通常は1500)、ネットワーク・パフォーマンスが著しく向上する可能性があります。
このパラメータを調整する手順は次のとおりです。
regedit
)。HKLM\System\CurrentControlSet\Services\AFD\Parameters
を見つけます。DWORD
値(Name:
FastSendDatagramThreshold
、Value:
1500
(10進数))を追加します。注意:
COHERENCE_HOME
/bin/optimize.reg
スクリプトでもこの変更を実行できます。スクリプトを実行したら、コンピュータを再起動して変更を有効にします。
Microsoft Windowsには、既存の接続および新しい接続に使用される、TCP再送信のタイムアウトが含まれています。デフォルトの再送信タイムアウトでは、ネットワークでのTCPデータ送信のWindowsの自動チューニングに基づいて、ほんの数秒で接続が破棄される可能性があります。タイムアウトが短いと、TcpRing
処理によりクラスタ・メンバーの停止を誤って検知する結果になる可能性があり、データ損失を起こす可能性があります。デフォルトの再送信タイムアウト構成を構成し、本番ネットワークで発生する可能性のある短期の停止に対する耐性を高められます。
TCP再送信のタイムアウトを延長する手順は次のとおりです。
regedit
)。HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
を見つけます。DWORD
値(Name:
TcpMaxConnectRetransmissions
、Value:
00000015
(16進数))を追加します。DWORD
値(Name:
TcpMaxDataRetransmissions
、Value:
00000015
(16進数))を追加します。注意:
COHERENCE_HOME
/bin/optimize.reg
スクリプトでもこの変更を実行できます。スクリプトを実行したら、コンピュータを再起動して変更を有効にします。
Windowsは、テスクトップ・アプリケーション用に最適化されています。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
ファイルを次のように変更します。
vm.swappiness = 0
Linuxのカーネルでは、ハードウェア割込み要求を複数のCPUまたはCPUコア全体にバランシングする機能があります。この機能は、SMP IRQアフィニティと呼ばれ、システム・パフォーマンスとCPU使用率を向上します。Coherenceの場合、クラスタ・メンバーをホストするすべてのサーバーにイーサネット・カードの割込みをバランシングすることで、大幅なパフォーマンスの向上が得られる可能性があります。ほとんどのLinuxディストリビューションでは、irqbalanceもサポートされています。これは、最新のマルチコアおよびマルチソケット・システムのキャッシュ・トポロジと電源管理機能を認識します。
ほとんどの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単位)です。
注意:
Solaris 10上で実行する場合は、パケットの破損およびマルチキャスト接続の切断に関する問題(1000972.1
および1000940.1
)を確認してください。これらは多くの場合、EOFExceptions
、パケット・データ読取り時の大きなギャップの警告または頻繁なパケット・タイムアウトとして顕在化します。Solaris 10システム上でCoherenceを使用する場合は、これら両方の問題に対するパッチの適用を強くお薦めします。
Windowsの場合:
「コントロール パネル」を開きます。
「ネットワーク接続」を開きます。
目的のネットワーク・アダプタの「プロパティ」ダイアログを開きます。
「構成」を選択します。
「詳細設定」タブを選択します。
「リンク速度とデュプレックス」でドライバ固有のプロパティを見つけます。
このプロパティを「自動検出」または特定のリンク速度とデュプレックスに設定します。
複数のクラスタ・ノード間で数秒間にわたる通信の停止が頻繁に発生する場合は、スイッチのバッファ領域を拡大してみてください。このような通信の停止は、ローカルまたはリモートのGCに起因しない、複数ノードでの通信の遅延を特定する一連のCoherenceログ・メッセージにより特定できます。
例4-1 通信の遅延を示すメッセージ
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のドキュメントを参照してください。
クラスタ・メンバーは複数のスイッチにわたって分割されていることがあり、複数のサブネットに含まれている可能性があります。ただし、そのようなトポロジによってスイッチ間リンクに過剰な負荷がかかるため、リンクでの障害発生時にクラスタが分割される可能性が高くなります。一般的に、その影響はクラスタとアプリケーションのパフォーマンスの低下をもたらす、通信遅延という形で顕在化します。影響を最小化するために、可能な場合は、すべてのクラスタ・メンバーを同一のスイッチとサブネットに配置することを常に検討してください。UDPおよびTCPの本番ネットワークの速度の評価を参照してください。
全二重イーサネットにはフロー制御機能があります。これにより、固定リンクの受信側に合せて送信側の速度を低下させることができます。これは、受信側からイーサネット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まで拡大するようネットワーク管理者に問い合せてください。
多くの10ギガビット・イーサネット(10GbE)スイッチとネットワーク・インタフェース・カードは、1500バイトのイーサネット・フレーム標準よりも大きなフレーム・サイズをサポートしています。10GbEを使用するときには、そのテクノロジで許容されている最大値(イーサネットの場合は約16KB)にMTUを設定して、広い帯域幅がフル活用されていることを確認します。Coherenceは、ネットワークのMTUを自動的に検出して、それに応じてUDPソケット・バッファ・サイズを選択します。MTUサイズが1500バイト(標準)の場合は2MB、9000バイト(ジャンボ)の場合は4MB、9000バイト超(スーパー・ジャンボ)の場合は8MBが、UDPソケット・バッファ・サイズに選択されます。また、オペレーティング・システムのソケット・バッファも、大きいサイズに対応するように8MBに拡大していることも確認します。オペレーティング・システムの検出されたバッファが小さすぎるときには、Coherenceログに警告が記録されます。最後に、ネットワークのパフォーマンスとスループットを検証するために、データグラム・テストを必ず実行してください。ネットワーク・パフォーマンス・テストの実行を参照してください。
Coherenceでは、TCPメッセージ・バス(TMB)を利用して、クラスタ・データ・サービス間でメッセージを送信します。したがって、TCP用にネットワークを最適にチューニングする必要があります。Coherenceでは、バッファ設定などのTCP設定をオペレーティング・システムから継承します。ほとんどのサーバーでは、ネットワーク用にTCPがすでにチューニングされており、追加構成する必要はありません。ネットワーク用にCoherenceをチューニングするのではなく、ネットワーク用にTCPスタックをチューニングすることをお薦めします。
Coherenceには、ネットワーク・ノード間でのスループットおよび待機時間のテストに使用できるメッセージ・バス・テスト・ユーティリティが組み込まれています。メッセージ・バス・テスト・ユーティリティの実行を参照してください。ネットワークが低いパフォーマンスを示す場合、適切に構成されていない可能性があるので、次の推奨設定を使用してください(これらの設定は、Linuxでデモを行ったものですが、他のオペレーティング・システムにも転換できます)。
#!/bin/bash # # aggregate size limitations for all connections, measured in pages; these values # are for 4KB pages (getconf PAGESIZE) /sbin/sysctl -w net.ipv4.tcp_mem=' 65536 131072 262144' # limit on receive space bytes per-connection; overridable by SO_RCVBUF; still # goverened by core.rmem_max /sbin/sysctl -w net.ipv4.tcp_rmem=' 262144 4194304 8388608' # limit on send space bytes per-connection; overridable by SO_SNDBUF; still # goverered by core.wmem_max /sbin/sysctl -w net.ipv4.tcp_wmem=' 65536 1048576 2097152' # absolute limit on socket receive space bytes per-connection; cannot be # overriden programatically /sbin/sysctl -w net.core.rmem_max=16777216 # absolute limit on socket send space bytes per-connection; cannot be overriden; # cannot be overriden programatically /sbin/sysctl -w net.core.wmem_max=16777216
各接続では最低320KBを使用しますが、通常のメモリー不足では接続ごとに5MBを使用し、最終的にオペレーティング・システムはTCP用のシステム・バッファリング全体を1GB以下に維持しようとします。これらは、高速(10GbE以上)ネットワーク用のチューニングに基づいた推奨デフォルト値ですが、1GbEでも容認されます。
この項には次のトピックが含まれます:
この項で示す推奨事項は、一般的な使用の場合には十分で、必要な設定作業は最小限です。JVMのサイズ設定時に考慮すべき第一の問題は、使用可能なRAMとガベージ・コレクション(GC)一時停止時間とのバランスです。
キャッシュ・サーバー
Coherenceキャッシュ・サーバーについての標準的で安全な推奨事項として、固定のヒープ・サイズを8GB以下にして実行することをお薦めします。さらに、増分ガベージ・コレクタを使用して、GC一時停止時間を最小限に抑えます。最後に、JVMコマンド行で-server
を指定して、すべてのCoherence JVMをサーバー・モードで実行することをお薦めします。これにより、長期間稼働するアプリケーションにいくつかの点で最適なパフォーマンスが得られます。
次に例を示します。
java -server -Xms8g -Xmx8g -Xloggc: -jar coherence.jar
このサイズ設定では、より詳細なJVMチューニングの必要がなく、適切なパフォーマンスが得られます。ガベージ・コレクションの監視を参照してください。
ヒープ・サイズを大きくすることが可能であるため、本番環境では大きなヒープ・サイズが実装されていますが、それによりGC一時停止を最小限に抑えるためのJVMのモニターとチューニングがさらに重要になります。スクラッチ領域の容量を増やしてGCの圧縮がより迅速になるように、記憶域の比率の変更が必要になる場合もあります。また、大きなサイズのヒープの管理を最新の状態に向上させるために最新バージョンのJVMを利用することをお薦めします。ヒープ・サイズに関する考慮事項を参照してください。
TCMPクライアント
長時間稼働する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圧縮などに使用します。ただし、この推奨事項は基本的な出発点であり、ルールではありません。より正確であるが無難な出発点としては、合計ヒープからJVMヒープの若い世代のサイズの2倍を引いたサイズ(たとえば、32GB – (2 * 4GB) = 24GB)より小さい領域をキャッシュ・データが占有すると想定します。この場合、キャッシュ・データはヒープの75%を占有できます。結果の割合は構成されている若い世代のサイズによって異なります。また、<high-units>
要素を構成して、<unit-calculator>
要素にBINARY
値を指定することによって、キャッシュごとにプライマリ記憶域を制限するようCoherenceを設定できます。これらの設定は、バックアップ記憶域にも自動的に適用されます。
プライマリ記憶域とバックアップ記憶域の両方が、JVMに確保されている領域内に収まるようにすることが理想です(HotSpotベースのJVMの場合)。Java Platform, Standard Edition HotSpot Virtual Machineガベージ・コレクション・チューニングの世代のサイズ設定を参照してください。
キャッシュ・トポロジとヒープ・サイズ
大きなデータセットには、パーティション・キャッシュまたはニア・キャッシュをお薦めします。Coherence JVMの数が変化してもキャッシュのパフォーマンスに大きな影響はありません。パーティション・キャッシュのスケーラビリティは、読取りと書込みのどちらについても直線的であるためです。レプリケート・キャッシュを使用すると、GCに対する負荷がきわめて大きくなります。
データ・グリッド操作用のキャパシティの計画
データ・グリッド操作(問合せや集計など)には、別のヒープ領域の要件があり、この操作を使用するときにはそれに応じた計画を立てる必要があります。データ・グリッド操作とは、メモリー内に保持される結果セットに含まれるキャッシュ・エントリのバイナリ表現のことです。操作によっては、このエントリは、その操作の期間中はデシリアライズされた形式で保持されることもあります。一般に、これは結果セット内の各エントリのメモリー量を倍増します。さらに、バッキング・マップの実装としてRAMまたはフラッシュのジャーナリングを使用しているときには、オブジェクトの格納方法に違いがあるために2番目のバイナリ・コピーが保持されます。2番目のバイナリ・コピーは、操作期間中も保持されるため、結果セット内の各エントリのための合計メモリーは3倍に増加します。
ヒープ・メモリーの使用率は、操作の実行対象になる結果セットのサイズと、処理される同時リクエストの数によって異なります。結果セットのサイズは、エントリの合計数と、各エントリのサイズに影響を受けます。記憶域キャッシュ・サーバーに維持された適度なサイズの結果セットは、ヒープのメモリーを使い果たす可能性はほとんどありません。ただし、結果セットが著しく大きい場合は、追加のメモリー要件によってヒープがメモリーを使い果たしてしまうことがあります。一般に、データ・グリッドの集計操作には巨大なデータセットが伴われるため、その他の操作よりも使用可能メモリーを使い果たしてしまう可能性が高くなります。
JVMのヒープ・サイズは、巨大な結果セットが予想されるときには、記憶域が有効なキャッシュ・サーバーで拡大しておく必要があります。たとえば、ヒープの3分の1をスクラッチ領域に予約している場合、スクラッチ領域が予想される結果セットのサイズをサポートできるようにします。別の方法として、データ・グリッド操作にはPartitionedFilter
APIを使用できます。このAPIは、個別のバーティション・セットに対してグリッド操作を実行することで、メモリーの消費量を低減します。
システムごとに実行するJVMの数の決定
システムごとに実行するJVM(ノード)の数は、システムのプロセッサ/コア数とメモリー量によって異なります。出発点として、4つのコアごとに1つのJVMを実行することを計画してください。この推奨内容によって、次の要素のバランスが取れます。
サーバーごとに複数のJVMを使用することによって、Coherenceで広帯域幅(1GBを超える)のネットワーク・リソースをより効率的に使用できるようになります。
JVMが多すぎると、プロセッサでの競合とコンテキスト・スイッチングが多くなります。
JVMが少なすぎると、使用可能なメモリーを処理できない場合や、NICを完全に使用できない場合があります。
特に、大きなヒープ・サイズの場合、JVMには、長時間のGC休止を避けるための処理能力が必要です。
アプリケーションに応じて、1つのコアにつき1つになるまでJVMを追加できます。JVMの推奨数と構成されたヒープ・サイズも、ソケットごとのプロセッサ/コアの数とコンピュータのアーキテクチャによって異なる場合があります。
注意:
Coherenceを基本キャッシュ(get、put、removeの各操作)として使用する、キャッシュ・サーバー上にアプリケーション・クラス(エントリ・プロセッサ、アグリゲータ、問合せ、キャッシュ・ストア・モジュールなど)を持たないアプリケーションが、コア当たり1 JVMという制限を超えることがあります。この場合、正常なシナリオとフェイルオーバー・シナリオの両方を対象とするテストを行ってください。
ヒープのサイズ設定
ヒープ・サイズを検討する際は、適切なバランスを見つけることが重要です。下限はJVMごとのオーバーヘッドによって(または潜在的に数が増大する可能性のあるJVMの管理のしやすさによっても)決まります。たとえば、インフラストラクチャ・ソフトウェア(JMXエージェント、接続プール、内部JVM構造など)に100MBの固定オーバーヘッドがある場合、ヒープ・サイズが256MBのJVMを使用すると、非キャッシュ・データのオーバーヘッドは約40%になります。JVMヒープ・サイズの上限はメモリー管理のオーバーヘッドによって決まります。特に、GCの最大一時停止時間やGCに割り当てられているCPUの割合(およびその他のメモリー管理タスク)によって決まります。
GCは次の項目に影響を及ぼす可能性があります。
Coherenceに対する操作の待機時間。ヒープが大きいほど、小さいヒープより待機時間が長くなり、予測が難しくなります。
クラスタの安定性。非常に大きいヒープの場合、JVMはGC一時停止の間は応答しなくなるため、非常に長いガベージ・コレクション休止によって、クラスタ・メンバーが停止しているとTCMPが誤認識する可能性があります。TCMPではメンバーのヘルス状態を判断する際にGC一時停止が考慮されますが、ある時点でそのメンバーは停止していると判断される場合があります。
次のガイドラインが示されています。
Javaの場合、ほとんどのアプリケーションに対して、控えめな8GBのヒープ・サイズをお薦めします。このサイズは、スループット、待機時間および安定性に基づいています。ただし、多数の小さなJVMから得られるパフォーマンスのメリットよりも、少数の大きなJVMから得られる管理の簡易化のほうが重要になる一部のアプリケーションには、大きなヒープ・サイズが適しています。コア対ヒープの比率は、おおよそ4コア対8GBが理想的ですが、コアごとに数GB追加して余裕を持って使用できるようにします。アプリケーションごとに違いがあるため、それに応じてGCをモニターする必要があります。
GC一時停止の長さは、ヒープ・サイズに対して直線的でなく、もっと悪い比率で増加します。つまり、ヒープ・サイズが2倍になると、一般に、GCによる一時停止時間は2倍より長くなります。GC一時停止は、アプリケーション使用状況の影響も受けます:
ヒープ内のライブ・データ量が増すにつれ、一時停止時間が長くなります。ヒープ内のライブ・データが70%を超えないようにしてください。これにはプライマリ・データ、バックアップ・データ、インデックス、およびアプリケーション・データが含まれます。
オブジェクト割当て率が高いと一時停止時間が長くなります。それぞれのネットワーク・パケットで多くのオブジェクトが生成されるため、単純なCoherenceアプリケーションでさえ、オブジェクト割当て率が高くなる場合があります。
CPU集中型の処理によって、競合が増え、一時停止時間が長くなる場合もあります。
待機時間の要件に応じて、前述で推奨した値より大きいヒープ領域を割り当てることができますが、必ずシステムの負荷テストを実行してください。
パーティション・キャッシュの記憶域に専用のCoherenceキャッシュ・サーバー・インスタンスを使用すると、データがローカルに保存されなくなるため、アプリケーションJVMのヒープ・サイズが最小限に抑えられます。大半のパーティション・キャッシュ・アクセスはリモートで実行される(データの1/N
のみがローカルに保持される)ので、専用キャッシュ・サーバーを使用しても、通常は追加のオーバーヘッドはあまり増大しません。ニア・キャッシュ・テクノロジを使用することもできます。このテクノロジは、通常、ヒープ・サイズに最小限の影響しか及ぼしません(パーティション・キャッシュよりもさらに小さなサブセットをキャッシュするためです)。多くのアプリケーションでヒープ・サイズを著しく減らし、応答性を改善できます。
ローカルのパーティション記憶域は、coherence.distributed.localstorage
Javaプロパティ(-Dcoherence.distributed.localstorage=false
など)を使用して有効化(キャッシュ・サーバーの場合)または無効化(アプリケーション・サーバー・クライアントの場合)できます。
また、tangosol-coherence.xml
(またはtangosol-coherence-override.xml
)ファイルの<local-storage>
設定を次のように変更して無効化することもできます。
例4-2 パーティション記憶域の無効化
<?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="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秒程度にすることが必要です。Java Platform, Standard Edition HotSpot Virtual Machineガベージ・コレクション・チューニングの概要を参照してください。
あるクラスタ・ノードが別のクラスタ・ノードについて一定時間応答のないことを検出した場合、ログ・メッセージが生成されます。このメッセージは一般に、ターゲットのクラスタ・ノードがGCサイクルにあることを示しています。
例4-3 ターゲットのクラスタ・ノードがガベージ・コレクション・モードであることを示すメッセージ
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 HotSpotメカニズムは次のとおりです。
-verbose:gc
(標準出力にGCログを書き込みます。出力先をカスタムの場所に変更する場合は、-Xloggc
を使用します)
-XX:+PrintGCDetails
、-XX:+PrintGCTimeStamps
、-XX:+PrintHeapAtGC
、-XX:+PrintTenuringDistribution
、-XX:+PrintGCApplicationStoppedTime
-XX:+PrintGCApplicationConcurrentTime
-Xprof
: プロファイリングを有効にします。プロファイリングのアクティビティは、テストと本番デプロイメントとで区別する必要があり、リソースとパフォーマンスに対する影響を常にモニターする必要があります。
JDKに含まれているJConsoleおよびVisualVM (VisualGCプラグインを含む)。
この項には次のトピックが含まれます:
大きなデータセットをキャッシュしている場合、一般には、そのデータセットのほんの一部で大半のデータ・アクセスに対応しています。たとえば、1000個のオブジェクトのデータセットの場合、操作の80%は100個のオブジェクトのサブセットに対するものになる場合があります。残り20%の操作は、その他900個のオブジェクトに対して実行される場合があります。言うまでもなく、最も高い投資対効果は、100個の最もアクティブなオブジェクトをキャッシュすることで得られます。残り900個のオブジェクトをキャッシュすると、さらに25%有効性の高いキャッシングを実現できますが、リソースについては900%の増大が必要になります。
ただし、すべてのオブジェクトが同頻度でアクセスされる場合(データセットの順次スキャンなど)は、同レベルの有効性を得るためにより多くのリソースが必要になります。この場合、0%を超えるキャッシュの有効性を実現するためには、100%のデータのキャッシュが必要になります(部分的にキャッシュされたデータセットの順次スキャンは、通常、MRU、LFUおよびMRU-LFUのエビクション・ポリシーに優先することに注意してください)。実際、ほとんどの非統合(ベンチマーク)データ・アクセス・パターンは不規則であるため、データのサブセットをキャッシュすることで処理速度は速くなります。
データのサブセットがアクティブであり、そのより小さなサブセットが特にアクティブである場合は、All無効化戦略を指定したニア・キャッシュの使用が非常に有用になることがあります(実際には、これは前述のルールの2層拡張になります)。
Coherenceのニア・キャッシュ・テクノロジでは、特にPresent無効化戦略を指定している場合、クラスタ・ノード・アフィニティを透過的に利用します。このトポロジはスティッキーなロード・バランサで使用すると特に有用です。キャッシュのフロント部分がスラッシングされる(キャッシュ・エントリの存続期間が非常に短い)場合、Present無効化戦略のオーバーヘッドは(Allに比べて)高くなることに注意してください。これは、キー・レベルのイベント・リスナーの追加/削除のオーバーヘッドがより高いためです。一般にキャッシュはスラッシングしないよう調整されるため、通常は問題にはなりません。
一般には、次のキャッシュ・トポロジと使用例の組合せが最適です。
レプリケート・キャッシュ: 少量の読取り頻度の高いデータ(メタデータなど)
パーティション・キャッシュ: 大量の読取り/書込みデータ(大きなデータ・キャッシュなど)
ニア・キャッシュ: パーティション・キャッシュに似ていますが、読取り頻度の高い段階的なアクセス・パターン(ホットスポットのある大きなデータ・キャッシュなど)やスティッキーなデータ・アクセス(スティッキーなHTTPセッション・データなど)で使用するとさらに有用です。同期化の方法(失効、非同期、同期)に応じて、最悪の場合のパフォーマンス・レベルは、パーティション・キャッシュと同等のレベルから、それよりも大幅に低いレベルまで変動します。
インターリーブとは、キャッシュへの書込み間に発生するキャッシュの読取り数のことを指します。パーティション・キャッシュはインターリーブの影響を受けません(1:1のインターリーブで設計されているため)。一方、レプリケーション・キャッシュとニア・キャッシュは読取り頻度の高いキャッシュに合せて最適化されるため、読取り頻度の高いインターリーブ(各書込み間に10回の読取りなど)が適しています。これは、これら両方のキャッシュが、後続の読取りアクセス用にデータをローカルにキャッシュするためです。キャッシュへの書込みが行われると、ローカルにキャッシュされているこれらの項目は強制的にリフレッシュされますが、これは(ローカル・メモリー・ヒープからオブジェクトをフェッチするほぼゼロ・コストと比べて)比較的コストのかかる処理です。それでも、ニア・キャッシュ・テクノロジを使用する場合の最悪のパフォーマンス・レベルはパーティション・キャッシュと同レベルであり、パフォーマンス・ロスは最良のシナリオと比較した場合の損失になります。
インターリーブは(間接的にですが)読取り/書込み率に関係することに注意してください。たとえば、1:1の読取り/書込み率のニア・キャッシュでは、処理が非常に高速になるか(すべての書込み後にすべての読取りを実行)、非常に遅くなる可能性があります(1:1のインターリーブで書込みと読取りを交互に実行)。