![]() ![]() ![]() ![]() 簡単に拡張できる軽量なモニタリングフレームワークの構築この記事のURLhttp://japan.internet.com/developer/20051122/25.html
著者:Narendra Venkataraman
海外internet.com発の記事
はじめに開発者はたびたび、一連のアプリケーションのモニタリングを行い、障害発生時には復旧策を実行しなければならない、という状況に直面します。私の場合は、さまざまなOS上に分散した複数のコンポーネントから成るマルチレイヤの電子通信バックエンドシステム用のモニタリングサーバを設計する必要性に迫られました。要求分析を行った結果、わざわざJMXを使って解決するほどの事例ではないことがわかりました。そこで、拡張やカスタマイズが容易にできる軽量なJavaフレームワークを実装し、そのうえでモニタリングシステムを構築することにしたのです。 本稿では、このフレームワークを使用して、データベース、アプリケーション、Webサーバのようなさまざまなバックエンドプロセスのモニタリングを行う方法と、プロセスの再起動、ディスク使用領域オーバー時のクリーンアップ、障害情報のレポートおよびログの生成のような修復処理を呼び出す方法を紹介します。本稿のダウンロードサンプルには、フレームワークのソースコードとサンプルクライアントが含まれています。 モニタリングコンポーネントの基本モニタリングの対象となるあらゆるコンポーネントに共通する属性を次に示します。
「正常」「異常」「モニタリング不可」の3つのいずれかの値をとります。
プロセスがダウンした場合、この処理を実行することで回復が行われます。ただし、すべてのコンポーネントが障害から回復できるわけではありません。たとえば、回復不可能かつクリティカルなプロセスがダウンした場合にシステムにできるのは、アラームを発することくらいです。
どの程度の頻度でコンポーネントのモニタリングを行うかを表します。頻度カウンタは設定可能なパラメータです。コンポーネントの種類に応じて、秒単位または分単位で値を指定します。
モニタリングされるコンポーネントのクリティカル性の高さを定めます。「高」「中」「低」の3つのレベルのいずれかに設定します。なお、モニタリングの頻度は低くてもクリティカル性の高いコンポーネントが存在しうることに注意してください。
フレームワークのもとで 図1のクラス図に示すように、このフレームワークは4つのクラスと1つのインターフェイスで構成されます。このフレームワークを呼び出すクライアントコードには、 モニタリングが必要なコンポーネントには、すべてこの public interface Info { //checks the status //returns true if ok //throws Exception if it could not be monitored public boolean isOk() throws Exception; //handles corrective action public boolean process(); } このフレームワークでは、次の2つのバックグラウンドスレッドが使われています。
リスト1 StatusMonitorクラス
public class StatusMonitor extends Thread { private final int monInterval; //in milliseconds private final Monitorable[] monArray; public void run() { while(true) { for(int cnt = 0; cnt < Integer.MAX_VALUE; cnt++) { //iterate through the array for(int i = 0; i < monArray.length; i++) { //check if counter expired if((cnt % monArray[i].getCounter()) == 0) monArray[i].monitor(); } } try { sleep(monInterval); } catch(InterruptedException ie) {} } } } モニタリング可能オブジェクトは リスト2 Monitorableクラス
public class Monitorable { private int counter; private byte criticality; private byte prevStatus; private StatusManager manager; private Info info; public void monitor() { byte currentStatus = NOT_OK; try { if(info.isOk()) { currentStatus = Monitorable.OK; } } catch(Exception ex) { currentStatus = Monitorable.COULD_NOT_BE_MONITORED; } //call setchanged if there is change in status //or if status is not ok or cud not be monitored if((currentStatus != prevStatus) || currentStatus != StatusManager.OK) { synchronized(this) { prevStatus = currentStatus; } manager.setChanged(this); } } //return the last monitored status public synchronized byte getStatus() { return prevStatus; } //recovery action public void execute() { info.process(); } } モニタリング可能オブジェクトは、 モニタリング可能オブジェクトによって リスト3 StatusManagerクラス
public class StatusManager extends Thread { //add to the queue and //notify that the status of monitorable has changed public synchronized void setChanged (Monitorable monitorable) monQueue.add(monitorable); notifyAll(); } //get the Monitorable object from the queue public synchronized Monitorable getMonitorable() { // return the object from the queue while(monQueue.isEmpty()) { try { wait(); } catch(Exception ex) {} } return (Monitorable) monQueue.remove(0); } //report or execute corrective action private void processChange() { Monitorable monitorable = getMonitorable(); //take corrective action if(monitorable.getStatus() == NOT_OK) { monitorable.execute(); } //log or report the status } public void run() { while(true) processChange(); } } 今回の例では、 このフレームワークの起動クラスである 同期化 フレームワークの利用 ここでは、Apache Webサーバのプロセスを監視し、ダウン時にはプロセスを再起動するという例を考えてみましょう。そのために、 リストされたプロセスの1つ1つに対して「apache.exe」プロセスが実行中であるかどうかをチェックするための public class ProcessInfo implements Info { ProcessInfo(String processName, String execName){ ..} //check if process is running or not boolean isOk() throws Exception {..} //re-launch process boolean process() {..}; } 現状のJavaでは、プロセス一覧、ディスク使用量、CPU負荷、ネットワーク接続状況などを取得するための手段はAPIレベルではサポートされていません。私のプロジェクトでは、こうした情報取得のための関数をOS別にC言語で書き、JavaのコードからアクセスできるようにJNIラッパを用意しました。かなり効率的ではありますが、JNIによる呼び出しがJVMプロセスのコンテキスト内で実行されるため、この解決法は少々危険だといえます。 代わりに、ネイティブ関数にアクセスするための別のプロセスを用意することもできるでしょう。本稿のダウンロードサンプルには、「CheckProcess.exe」というWin32アプリケーションが含まれています。このアプリケーションは、プロセス名をコマンドラインパラメータとして取得し、そのプロセスが実行中か否かに応じてTRUEまたはFALSEを標準出力に書き出します。 public boolean isOk() throws Exception { String[] cmdArray = new String[] {“CheckProcess.exe”, “apache.exe”}; Process proc = Runtime.getRuntime().exec(cmdArray); BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream())); String status = br.readLine(); if(status.equals("TRUE")) return true; return false; } 続いて、 public class TestClient { public static void main(String[] args) throws Exception { ProcessInfo p = new ProcessInfo(“apache.exe”, “<Path>/apache.exe”); int counter = 10; //10 seconds byte criticality = LWMFramework.HIGH; LWMFramework lwmf = new LWMFramework(); //set minimum monitorable frequency 1 second lwmf.setMonitorInterval(1); //add info object lwmf.add(p, counter, level); //start the framework lwmf.start(); Thread.currentThread().join(); } } フレームワークの拡張 このフレームワークはいろいろな方法で拡張することができます。1つの方法として、リモートプロセス、CPU負荷、帯域利用率といったさまざまなコンポーネントを監視するための新しい リスト4 XMLによる設定(「Monitor.xml」)
<MonitorServer interval="1" > <!-- The interval determines unit value of counter in seconds, if this value is 60 then minimum frequency of monitoring is 60 sec or 1 min !--> <MONITORABLE name = "Apache Webserver" class = "ProcessInfo" counter = "1000" criticality = "HIGH"> <!-- ProcessInfo specific configuration !--> <process name="apache.exe" exec="C:/Apache.exe"/> </MONITORABLE> <MONITORABLE name = "Tomcat" class = "ProcessInfo" counter = "1000" criticality = "HIGH"> <process name="tomcat.exe" exec="path../tomcat.exe"/> </MONITORABLE> <MONITORABLE name = "C Drive" class = "FileSystemInfo" counter = "100000" criticality = "HIGH"> <filesystem path="C:" threshold="80" exec="C:/../diskcleanup.exe"/> </MONITORABLE> <MONITORABLE name = "app server" class = "ConnectivityInfo" counter = "1000" criticality = "HIGH"> <connectivity host="198.168.1.10"/> </MONITORABLE> <MONITORABLE name = "LocalMachine" class = "CPUInfo" counter = "10000" criticality = "LOW"> <Threshold value="80"/> </MONITORABLE> </MonitorServer> ここでは、モニタリング可能オブジェクトのそれぞれが、1つのXMLノードとして表され、名前、カウンタ、クリティカル性およびクラスといった共通の属性を持っています。このクラス属性は、 このフレームワークをさらに拡張し、レポートや統計情報を生成するサードパーティアプリケーションとのインターフェイスを実装することもできます。また、 JMXの軽量な代替手段ここで紹介したモニタリングフレームワークは簡単に拡張でき、とりわけサーバ側アプリケーションのモニタリングで大いに役立ちます。この軽量なフレームワークは、既存の管理ツールを完全に置き換えるものではありません。むしろ、そうした管理ツールを補完するものであり、HP OpenViewのようなハイエンドの管理ソフトウェアに簡単に統合することができます。 著者紹介Narendra Venkataraman(Narendra Venkataraman)
Hewlett-Packard社電子通信部門の上級デベロッパ。
japan.internet.comのウエブサイトの内容は全て、国際法、日本国内法の定める著作権法並びに商標法の規定によって保護されており、その知的財産権、著作権、商標の所有者はインターネットコム株式会社、インターネットコム株式会社の関連会社または第三者にあたる権利者となっています。
本サイトの全てのコンテンツ、テキスト、グラフィック、写真、表、グラフ、音声、動画などに関して、その一部または全部を、japan.internet.comの許諾なしに、変更、複製、再出版、アップロード、掲示、転送、配布、さらには、社内LAN、メーリングリストなどにおいて共有することはできません。 ただし、コンテンツの著作権又は所有権情報を変更あるいは削除せず、利用者自身の個人的かつ非商業的な利用目的に限ってのみ、本サイトのコンテンツをプリント、ダウンロードすることは認められています。 |