ZabbixでJavaアプリケーションを監視し、JMX LLD用にJavaGatewayをカスタマイズする

エントリー



この記事では、 JMXメトリックスの最も便利な低レベル検出のために、 Zabbix JavaGatewayを少しカスタマイズする方法を説明します。 github.com/mfocuz/zabbix_plugins/tree/master/jmx_discoveryでは 、バージョン2.0.11のパッチを入手して、外部スクリプトの例を参照できます。 しかし、まず最初に。



バージョン2.0以降、ZabbixはJMXを介したJavaアプリケーションの監視をネイティブにサポートしています。 しかし、メトリックを収集することに加えて、Zabbixでそれらをボックスから否認できることを誰もが知っているとは限りません。 ドキュメンテーションでは、彼らはこの点を見逃したか、機能がまだ準備ができていないと考えました(ドックで見つけられなかったかもしれませんが?)、しかし、この機能はそこにあり、私の意見では、それは本当に準備ができていません。 動作するかどうかはわかりませんが、テストには至りませんでした。



バージョン2.0.11行157以降のJMXItemChecker.javaクラスのソースコードzabbix_javagw:



else if (item.getKeyId().equals("jmx.discovery”)) { … for (ObjectName name : mbsc.queryNames(null, null)) { logger.trace("discovered object '{}'", name); for (MBeanAttributeInfo attrInfo : mbsc.getMBeanInfo(name).getAttributes()) { logger.trace("discovered attribute '{}'", attrInfo.getName()); if (!attrInfo.isReadable()) { logger.trace("attribute not readable, skipping"); continue; } try { logger.trace("looking for attributes of primitive types"); String descr = (attrInfo.getName().equals(attrInfo.getDescription()) ? null : attrInfo.getDescription()); findPrimitiveAttributes(counters, name, descr, attrInfo.getName(), mbsc.getAttribute(name, attrInfo.getName())); } catch (Exception e) { Object[] logInfo = {name, attrInfo.getName(), e}; logger.trace("processing '{},{}' failed", logInfo); } } } }
      
      







コードからわかるように、ルール検出構成で「jmx.discovery」という名前のキーを設定すると、検出されたすべてのmbeanのすべての属性を返す検出が機能します。

ここで、まず第一に、そのようなリクエストに特別な必要はないことに注意したい。 まず、各mbinの属性に対する要求は個別の要求によって渡され、多くのビンが存在する可能性があるため、このような要求は非常に迅速に機能しません。 次に、ルール検出キーはZabbixの一意の値です。つまり、 jmx.discoveryを使用すると、同じホスト内のJMXメトリックに対して1つのルール検出を作成できます。これは、ほとんどのタスクにはまったく不適切です。 そして第三に、各java mbeanの属性は通常変更されません。つまり、同じビン内のそれらの数と目的は一定です。 これは、アイテムプロトタイプとコードの一部(実際はブレーキ)で設定する方が属性自体が優れていることを意味します。



  for (MBeanAttributeInfo attrInfo : mbsc.getMBeanInfo(name).getAttributes()) { ....... try { (attrInfo.getName().equals(attrInfo.getDescription()) ? null : attrInfo.getDescription()); findPrimitiveAttributes(counters, name, descr, attrInfo.getName(), mbsc.getAttribute(name, attrInfo.getName())); ......
      
      







不要になります。 ただし、 mbeanの数は可変です。 たとえば、 Oracle Coherenceは、クラスタ内の各ノードの下に特定の数のBeanを作成します。 その結果、 nodeIdのみが異なる名前のBeanがあります。 また、たとえば、クラスターを再起動すると、すべてのnodeIdが変更されます。 つまり、 Javaメトリックには動的なmbeanがあります。 ここでLLDを使用しますが、次のとおりです。



1.属性のないmbeanのみが必要です(それらも見つけることができますが、これは不要です)。

2.単一のホストで複数のルール検出を作成できることが重要です。

3.ルール検出のためにさまざまなロジックをエンコードする機能が必要です。



少し前まで、 JMX Discovery www.zabbix.org/wiki/Docs/howto/jmx_discoveryに1つの記事が掲載されました 。 昨年、私は同様のソリューションを使用しました。 最後に:このソリューションの本質は、.jarファイルを外部スクリプトとして実行することです。 その大きなマイナス点は、Pythonがperlやperlなどのインタプリタ言語で通常行われているように、Javaが複数回実行するように設計されていないことです。 このマイナスにより、ソリューションは実質的に機能しなくなります。 2コアの仮想マシンで約20のルール検出を開始すると、タイムアウトによる外部チェックの結果、CPU負荷が棚から落ちたとしましょう。 それが8korであった鉄片の上で、それはきちんと働くように思われました。 しかし、すべて同じですが、N分ごとにJVMバンドルを起動するのは美しい解決策ではなく、松葉杖としか見なせません。



新機能の仕組み



まず、ZabbixサーバーとJavaGatewayがどのように相互作用するかを検討してください。 JMXメトリックを収集するために、ZabbixサーバーはTCPを介してJavaGatewayに接続し、その後、Zabbixプロトコルを使用して必要なデータを要求します。 サイトにはプロトコルの一般的な説明がありますので、もう少し詳しく説明します LLDには彼が必要です。

サーバーへのメッセージとサーバーからの応答は、3つの部分で構成されています。



1.ヘッダーZBXD \ 1

2.メッセージの長さ

3.メッセージはJSON形式です。



次のようになります。



画像



Zabbixコードに最小限の変更を加えたかったので、Zabbixサーバーのコードには触れません。上の図では、Zabbixサーバーをexternalscriptに置き換えて、同じ接続を確立します。 そして、JavaGatewayコードに必要な関数を追加します。 そして今、JavaGateway for LLDとの通信は次のようになります。



画像



つまり、regexpフィールドと新しい種類のリクエスト=“ java jmx lld”が追加されました。



JavaGatewayコードの変更



JMXディスカバリーを便利かつ高速にするために何をする必要がありますか? 開発者が考えたように、JavaGatewayには2つのリクエストリクエストがあり、それらはItemChecker.javaコードにあります。これらは、内部JavaGatewayメトリックのペアを収集するJSON_REQUEST_INTERNAL定数と、JMXメトリックを収集するために使用されるJSON_REQUEST_JMXです。 SocketProcessor.javaコードには次のように表示されます。



 if (request.getString(ItemChecker.JSON_TAG_REQUEST).equals(ItemChecker.JSON_REQUEST_INTERNAL)) checker = new InternalItemChecker(request); else if (request.getString(ItemChecker.JSON_TAG_REQUEST).equals(ItemChecker.JSON_REQUEST_JMX)) checker = new JMXItemChecker(request); ….. JSONArray values = checker.getValues();
      
      







つまり、 チェッカーのタイプを決定します。 3番目のタイプのリクエストJSON_JMX_LLDを追加します。 それに応じて、SocketProcessor.javaのリクエストに対する別の条件:



 …... else if (request.getString(ItemChecker.JSON_TAG_REQUEST).equals(ItemChecker.JSON_JMX_LLD)) checker = new JMXItemDiscoverer(request); …… JSONArray values = checker.getValues();
      
      







これで、サーバーがJSON_JMX_LLDのリクエストを受信すると、 JMXItemDiscovererクラスのインスタンスが作成され、 getValuesメソッドが呼び出されます。 JMXItemDiscovererクラスを追加することは残ります。これにより、検出ルールが便利になります。つまり、使用可能なすべてのビンを要求し、出力で、指定された正規表現のビンのリストを返します。 新しいクラスのコードは、パッチで確認できます。



新しいJavaゲートウェイを構成する



2つのオプションがあります。JavaGateway自体を置き換えることも、別のものを上げることもできます。これはLLDでのみ機能します。 ゲートウェイをPROに変更すると、次のようになります。

1.Zabbix側では、JavaGatewayのみを変更する必要があります。 記事の冒頭のリンクから、zabbix javaゲートウェイバージョン2.0.11のパッチを見つけることができます。 コード2.2と2.0.11を少し比較してみたので、Javaゲートウェイの違いはあまりないので、Javaの基本的な知識があれば、パッチを最新バージョンに転送することは難しくないと思います。

2.次に、パッチをロールアップし、インストールされているバージョンのJava用のJavaGatewayをビルドします。

3.古い.jarの代わりに結果の.jarを取得します。他のすべてのJavaゲートウェイファイルには、構成など何でもそのまま残します。

4.始めます。 同じJavaゲートウェイを受け取りますが、もう1種類の要求を処理できるようになりました。

5.要求自体については、TCPを介してサーバーにしがみついて実際に要求を作成するスクリプトを作成します。 Perlの簡単なJMXDiscovery.pmモジュールをスケッチして、検出スクリプトとjmx_discovery.plスクリプトの検出とモジュールの使用例を簡単に記述できるようにしました(冒頭のリンクにあります)。

6.最後に、ルール検出を作成し、タイプにexternalscriptを指定します。 スクリプトに渡されるパラメーターにより、キーの一意性が確保され、任意の数のルールを作成できます。



LLD用に別のサーバーを作成する場合は、手順3をスキップし、パッチと一緒にアセンブリ後に、 JavaGatewayを別のサービスとして設定します。



おわりに



素早く安定して動作します。



All Articles