2010年07月20日
実践SNMP+Java GetBulk
SNMP4Jを利用したSNMP GetBulk操作について説明します。
連続したMIBオブジェクトを一括で取得したい場合、GetNextに比較すると、
マネージャ/エージェント間のPDU数を減らすことが出来る為、効率良く取得出来ます。
<Javaコード>
- String oid = ".1.3.6.1.2.1.1"; // mib-2.system
- // SNMP通信パラメータを設定するクラス。
- CommunityTarget comTgt = new CommunityTarget();
- comTgt.setAddress( new UdpAddress("localhost/161") ); // UDPアドレス(ターゲット・アドレス/SNMPポート)
- comTgt.setCommunity( new OctetString("public") ); // SNMPコミュニティ名
- comTgt.setTimeout(1000); // タイムアウト時間(ミリ秒)
- comTgt.setRetries(1); // リトライ数
- comTgt.setVersion(SnmpConstants.version2c); // GetBulkはv2以降でサポート
- // PDUを生成します。
- PDU pdu = new PDU();
- pdu.setType(PDU.GETBULK);
- pdu.setMaxRepetitions(5); // 一括繰り返し取得数。system.sysDescr.0から5つをGetBulk
- pdu.setNonRepeaters(0); // 繰り返し取得しないバーバインドのindex。
- // PDUにバーバインドを格納します。
- OID targetOID = new OID(oid);
- pdu.add(new VariableBinding(targetOID));
- // SNMP操作の基本になるクラス。
- Snmp snmp = null;
- // DefaultTcpTransportMappingクラスもありますが、使いどころは不明?
- DefaultUdpTransportMapping utm = null;
- try {
- utm = new DefaultUdpTransportMapping();
- snmp = new Snmp(utm);
- snmp.listen(); // ローカルUDPポートのオープンと待機
- // SNMP GetBulk
- ResponseEvent response = snmp.getBulk(pdu, comTgt);
- // レスポンスPDU
- PDU resPdu = response.getResponse();
- if ( resPdu != null && resPdu.getErrorStatus() == SnmpConstants.SNMP_ERROR_SUCCESS ) {
- // レスポンスPDUに含まれるバーバインド数
- int numVarBinds = resPdu.size();
- for (int i=0; i<numVarBinds; i++) {
- VariableBinding var = resPdu.get(i);
- if ( !var.isException() ) {
- System.out.println(var.getOid() + " -> " + var.getVariable().toString());
- } else {
- System.out.println(var.getOid() + " -> " + "has excepton syntax!");
- }
- }
- } else {
- if (resPdu == null) {
- // レスポンスPDUがnullの場合はタイムアウトです。
- System.out.println("request timeout.");
- } else {
- System.out.println(resPdu.getErrorStatusText());
- }
- }
- // ローカルUDPポートのclose
- snmp.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
<実行結果>
1.3.6.1.2.1.1.1.0 -> Hardware: x86 Family 6 Model 15 Stepping 6 AT/AT COMPATIBLE - Software: Windows 2000 Version 5.1 (Build 2600 Multiprocessor Free)
1.3.6.1.2.1.1.2.0 -> 1.3.6.1.4.1.311.1.1.3.1.1
1.3.6.1.2.1.1.3.0 -> 0:03:12.31
1.3.6.1.2.1.1.4.0 ->
1.3.6.1.2.1.1.5.0 -> PANZERII
<説明>
1)リクエスト送信準備(1~16行目)
まず、GetBulkはSNMPv2以降ですので、8行目でバージョンにv2(c)を指定しています。
次に、10~16行目でGetBulkリクエストPDUを生成しています。
G etBulkリクエスト特有のパラメータとしてMaxRepetitionsとNonRepeatersがあります。
MaxRepetitionsは一括繰り返し取得回数を表すパラメータで、サンプル・コードでは、
".1.3.6.1.2.1.1"; // mib-2.system以降の5オブジェクトを一括取得するという意図で、
pdu.setMaxRepetitions(5)を設定しています。
※MaxRepetitionsで指定できる数字に上限はありませんが、実際には、
エージェント側の最大PDUサイズに依存し、それを超える場合には反映されません。
(SNMP Getで説明したTooBigエラーと同じ理由です)
NonRepeaters(一括繰り返し取得しないバーバインドのPDU内index)は、
サンプルコードでは一括取得したいので、0(無し)にしています。
NonRepeatersを0にする運用は少ないんじゃないじゃ無いかと思うんですが、
一番最後に使用例を説明します。
2)リクエストの送信・レスポンスの受信(18行目)
systemグループ(".1.3.6.1.2.1.1")のsystem.sysDescr.0~sysName.0まで
5オブジェクトを一括取得しています。
5オブジェクトを一括取得しています。
<NonRepeatersの使いどころ>
僕自身このパラメータを実際の運用で使ったことは無いのですが、使いどころを
考えてみたいと思います。
考えてみたいと思います。
もし、システムのホスト名(system.sysName.0)とインタフェースの
物理アドレス(ifTable.ifEntry.ifPhysAddress.$, $:ifIndex)を一括で
取得したいとなった場合、リクエストPDUの準備は次のようになります。
PDU pdu = new PDU();
pdu.setType(PDU.GETBULK);
// add varbind(index:1). system.sysContact.0 (for system.sysName.0)
pdu.add( new VariableBinding( new OID(".1.3.6.1.2.1.1.4.0") ) );
// add varbind(index:2). ifTable.ifEntry.ifPhysAddress
pdu.add(new VariableBinding( new OID(".1.3.6.1.2.1.2.2.1.6") ) );
pdu.setMaxRepetitions(10); // 一括繰り返し取得数
pdu.setNonRepeaters(1); //繰り返し取得しないバーバインドのindex。この例では1。
まず、system.sysName.0(1.3.6.1.2.1.1.5.0 )を取得したいのですが、
GetBulkでは指定したOID以降という意味になるので、その前のOIDである
".1.3.6.1.2.1.1.4.0"(system.sysContact.0)を指定しています。
次に、ifPhysAddressのOIDを設定しています。
インタフェースが幾つあるか事前にはわかりませんので、10以下を前提に
繰り返しで一括取得します。
最後にpdu.setNonRepeaters(1)ですが、sysName.0はエージェント側では
オブジェクト(インスタンス)を1つしか管理していないことが分かっており、
繰り返し取得する必要はなく、そのバーバインドのインデックスである1を
指定しています。
結果は次の通りです。
1.3.6.1.2.1.1.5.0 -> PANZERII
1.3.6.1.2.1.2.2.1.6.1 ->
1.3.6.1.2.1.2.2.1.6.2 -> 00:50:56:c0:00:08
1.3.6.1.2.1.2.2.1.6.3 -> 00:50:56:c0:00:01
1.3.6.1.2.1.2.2.1.6.4 -> 00:1c:23:17:d5:9b
1.3.6.1.2.1.2.2.1.6.5 -> 00:1b:77:cf:40:dd
1.3.6.1.2.1.2.2.1.6.65543 -> 7a:79:05:2e:82:37
1.3.6.1.2.1.2.2.1.7.1 -> 1
1.3.6.1.2.1.2.2.1.7.2 -> 1
1.3.6.1.2.1.2.2.1.7.3 -> 1
1.3.6.1.2.1.2.2.1.7.4 -> 1
sysName.0とifPhysAddressの一覧が取得出来ました。
尚、実際には僕のPCには10個もネットワーク・インタフェースは無いので、
レスポンスにifTable.ifEntry.ifAdminStatus(.1.3.6.1.2.1.2.2.1.7)まで
含まれており、自分が欲しい情報か否かは、GetNetxで説明したIsSubTree
相当の処理を用意して判断します。
<最後に>
実践でGetNext、GetBulkを利用するケースとしてはMIBテーブルのフェッチが
多くなるのではないかと思います。
この時、GetNext/GetBulkではスピード、エージェント側負荷にどの程度の差が
出るのでしょうか?
この話しは別の機会にご説明します。
ダグラス・R. マウロ ケビン・J. シュミット
オライリー・ジャパン
売り上げランキング: 257,278
オライリー・ジャパン
売り上げランキング: 257,278
Java ネットワーク プログラミング 基礎からわかる 完全入門
posted with amazlet at 13.01.12
永嶋 浩
技術評論社
売り上げランキング: 228,941
技術評論社
売り上げランキング: 228,941
Posted by netbuffalo at 14:50│TrackBack(0)│
│実践SNMP+Java