CacheEventListenerの実装を作ってみる

ダメだ、眠れない、、、。

ということで、今回は、CacheEventListenerのサンプルとして AmountOverflowAlarm を作成してみます。(こんな夜更けに、、、。)

AmountOverflowAlarm

AmountOverflowAlarm クラスとして、キャッシュへの put 後に、以前と現在の要素数を調べ、設定値を超えてたら警告ログを出力するクラスを作成します。

CacheEventAdapter

CacheEventListenerには、8つのメソッドが定義されています。しかし、AmountOverflowAlarm クラスでは put の監視しかする必要がありません。そのため、8つのメソッドをすべて実装するのは面倒です。そのため、CacheEventListener の空実装として、CacheEventAdapter を作成します。

public class CacheEventAdapter implements CacheEventListener {
	public Object clone() throws CloneNotSupportedException { return super.clone(); }
	public void notifyElementEvicted(Ehcache cache, Element element) {}
	public void notifyElementExpired(Ehcache cache, Element element) {}
	public void notifyElementPut(Ehcache cache, Element element) throws CacheException {}
	public void notifyElementRemoved(Ehcache cache, Element element) throws CacheException {}
	public void notifyElementUpdated(Ehcache cache, Element element) throws CacheException {}
	public void notifyRemoveAll(Ehcache cache) {}
	public void dispose() {}
}

ehcache-amountOverflowAlermSample.xml

このサンプル用の、Ehcacheの定義ファイルです。

<ehcache>
	<defaultCache />
	
	<!-- 
		このキャッシュは、要素数が1000件超えることがないと考えた上で設定されています。 
		しかし、サービスが拡大して、そのうち1000件を超えるかもしれない、、、。
		そうなると、パフォーマンスチューニングを見直さなくてはならないなぁ。
	-->
	<cache
		name="testCache"
		maxElementsInMemory="1000"
		eternal="true"
		overflowToDisk="false"
	>
		<!-- とうことで、900件を超えるタイミングで、警告ログを出します。 -->
		<cacheEventListenerFactory
			class="AmountOverflowAlarmFactory"
			properties="threshold=900"
		/>
	</cache>
</ehcache>

AmountOverflowAlarm

これが、今回の主役です。CacheEventListener で定義されているメソッドのうち、notifyElementPut メソッドのみ使用しています。警告ログを出す要素数閾値 は、threshold にセットします。キャッシュにputされるたびに notifyElementPut メソッドが呼び出されて、メモリ上の要素数が threshold を超えた場合には警告ログが出力されます。

public class AmountOverflowAlarm extends CacheEventAdapter {
	private static final Log LOG = LogFactory.getLog(Cache.class.getName());
	private long threshold;
	private long lastAmount = -1;

	public AmountOverflowAlarm(long threshold) {
		setThreshold(threshold);
	}

	public void setThreshold(long threshold) {
		this.threshold = threshold;
	}

	public void notifyElementPut(Ehcache cache, Element element) throws CacheException {
		// Get current number of cache elements
		long amount = cache.getMemoryStoreSize();
		
		// Alert
		if (lastAmount < threshold && amount >= threshold) {
			LOG.warn("Number of elements in cache '" + cache.getName() + "' is over " + threshold + ".");
		}
		
		// Save current amount
		this.lastAmount = amount;
	}
}

AmountOverflowAlarmFactory

定義ファイル上でキャッシュに CacheEventListener を設定するためにはファクトリが必須となるため、AmountOverflowAlarmFactory を作成します。

public class AmountOverflowAlarmFactory extends CacheEventListenerFactory {
	public CacheEventListener createCacheEventListener(Properties properties) {
		return new AmountOverflowAlarm(Long.parseLong(properties.getProperty("threshold")));
	}
}

AmountOverflowAlermSample

AmountOverflowAlerm のサンプルプログラムです。定義ファイル ehcache-amountOverflowAlermSample.xml で CacheManager を設定し、testCache にデータを1000件投入します。

/**
 * CacheEventListenerのサンプル
 * キャッシュ "testCache" に対して、データを1000件投入します。
 */
public class AmountOverflowAlermSample {

	public static void main(String[] args) {
		URL url = ClassLoader.getSystemResource("ehcache-amountOverflowAlermSample.xml");
		CacheManager cm = new CacheManager(url);
		
		// キャッシュを取得する。
		Cache test = cm.getCache("testCache");
		
		// テストデータを1000件投入。
		for (int i=0; i<1000; i++) test.put(new Element(new Object(), new Object()));		
	}
}

結果。

900件を越えたタイミングで警告ログが出力されました。

2008/04/22 9:09:51 AmountOverflowAlarm notifyElementPut
警告: Number of elements in cache 'testCache' is over 900.

めでたしめでたし。