Topics
Enterprise Architecture
Alex Ruiz著
2006年5月19日
スケーラビリティ、信頼性、高いパフォーマンスは、最新のJ2EEアプリケーションにおいては不可欠な要件です。クライアントの種類に関係なく、通 常、リクエストの処理には、控えめに言っても、異種データソースからの情報収集や複雑な計算の実行など、パフォーマンスに対して悪影響を与えるアクション が含まれています。キャッシングは、エンタープライズアプリケーションのパフォーマンスを向上させる必須プラクティスの1つです。どのアプリケーションに も、アプリケーション固有のキャッシング要件があります。この要件は、パフォーマンスの低下を発生させないように、常に調整しておかなければなりません。 エンタープライズアプリケーションには、アプリケーションのコードに触れることなく、キャッシング機能を追加したり調整するための簡単な方法が必要です。 この記事では、Springベースのアプリケーションのためのコードフリーのキャッシングフレームワークである、 Springのための宣言的キャッシングサービスを紹介します。
簡単に言うと、キャッシングには、取得操作が高くつくようなデータの一時的な保管が含まれます。その結果、元々のデータソースからの余分なデータ取 得がなくなり、クライアントへの素早い応答が可能になります。たとえば、アプリケーションサーバとデータベースが同じ場所に配置されておらず、ネットワー ク上の通信が伴う場合、キャッシングによって、アプリケーションサーバからデータベースへの呼び出しを回避すれば、絶大なパフォーマンス向上が可能です。 キャッシングによって、データベースの作業負荷が削減でき、ネットワークの帯域幅に制限されないので、アプリケーションの応答時間は著しく改善されます。
分散システムは、キャッシングサービスのための絶好のターゲットです。リモート呼び出しは、特に速度が遅く、貴重なネットワーク帯域幅を消費するの で、パフォーマンスの問題が発生します。リモートサービスへの呼び出しは、パラメータを、ネットワークを介して転送可能な形式(XML、バイトストリーム など)にマーシャリングしてリクエストを作成することから始まります。一旦、リクエストが受信されると、サーバー側では、処理を開始するために、マーシャ リングを解除する必要があります。サービスによって生成された応答にも、同様の手続きが適用されます。これによって、さらにオーバヘッドが加わります。 キャッシングを利用すると、リモート呼び出しがなくなるか、少なくとも削減できるので、分散アプリケーションのパフォーマンスが劇的に向上します。
このような利点がある一方、キャッシングによって、エンタープライズアプリケーションの設計、開発、デプロイがかなり複雑になります。ビジネス要件 についての明確な知識なしに、キャッシングを適用するべきではありません。また、キャッシングを適用するかどうかの判断は、テスト結果、その他の確固たる 証拠に裏づけされていなければなりません。
キャッシングのための基本的なガイドラインを以下に示します。
独自のキャッシュを実装するのは、簡単な作業ではありません。スレッド管理、古くなったデータの削除、クラスタリングサポートなどの複雑な問題を処 理しなければなりません。最近では、オープンソースと商用の両方で、高品質なサードパーティ製のキャッシュ実装が数多く提供されています。これらを利用す ると、キャッシュを作成したり、独自のキャッシュを保守するというもっと重要な作業の負担を軽減できます。
Springフレームワークは オープンソースのアプリケーションフレームワークで、プレーンなJavaオブジェクトにエンタープライズサービスやその他の機能を提供します。 Springを利用して作成されるアプリケーションのほとんどが、データ中心型の多層エンタープライズアプリケーションで、複数の同時実行ユーザを持ちま す。このようなアプリケーションも、リモートEJB、Webサービス、CORBAなどのリモート技術を使用して、外部システムを統合する場合があります。 エンタープライズアプリケーションは、基幹業務にとって重要なので、高いパフォーマンスが期待されます。
Springのための宣言的キャッシングサービスは、Springを利用したアプリケーションのための宣言的キャッシングを提供 します。宣言的キャッシングには、プログラミングが一切含まれません。このため、キャッシングサービスの適用や調整を、かなり簡単に素早く行うことができ ます。キャッシングサービスの設定は、Spring IoCコンテナの中ですべて実行することができます。宣言的キャッシングには以下の特徴があります。
宣言的キャッシングとその利点を理解するために、以下のコード部分を見ていきましょう。これは、顧客IDが与えられると、データソースから顧客情報を取得するという顧客マネージャの簡単な実装です。パフォーマンスを向上させるために、データアクセスレイヤから取得した
Customerオブジェクトは、プログラムでCoherenceキャッシュに保存されます。さらに、古くなったデータの保管を防ぐために、1人の顧客の情報が更新されると、顧客情報を含むキャッシュはフラッシュされます。
public class CustomerManager {
private CustomerDao customerDao;
private CacheKeyGenerator keyGenerator;
public Customer load(long customerId) {
validateCustomerId(customerId);
Customer customer = null;
Serializable key = keyGenerator.generateKey(customerId);
NamedCache cache = getCache();
customer = (Customer) cache.get(key);
if (customer == null) {
customer = customerDao.load(customerId);
cache.put(key, customer);
}
return customer;
}
public void update(Customer customer) {
customerDao.update(customer);
Serializable key = keyGenerator.generateKey(customer.getId());
NamedCache cache = getCache();
cache.remove(key);
}
private NamedCache getCache() {
return CacheFactory.getCache("customerCache");
}
// rest of class implementation
}
キャッシュの使用によって、アプリケーションのパフォーマンスは向上しますが、余分な(不必要な)複雑さが加わります。キャッシュのプログラムでの使用によって、以下の問題が発生します。
CacheFactory、または、少なくともそれをシミュレートするオブジェクトが必要です。
CustomerManagerクラスを、異なるキャッシングニーズを持つアプリケーションや、キャッシングの必要がないアプリケーションで再利用するのは困難(または不可能)です。
宣言的キャッシングは、キャッシングが実行される仕組みをカプセル化し、キャッシュ実装への依存性をJavaコードから除去します。宣言的キャッシングを導入すると、前の例のメソッドは、以下のようにコア要件だけを実装したものになります。
public class CustomerManager {
private CustomerDao customerDao;
public Customer load(long customerId) {
validateCustomerId(customerId);
return customerDao.load(customerId);
}
public void update(Customer customer) {
customerDao.update(customer);
}
// rest of class implementation
}
以下のXML部分は、Javaコードではなく、Spring IoCコンテナで、
CustomerManagerインスタンス用にキャッシングサービスをどのように設定するかを示しています。
<bean id="
customerDaoTarget"
class="org.springmodules.cache.samples.dao.CustomerDao" />
<!-- Properties -->
</bean>
<coherence:proxy id="customerDao" refId="
customerDaoTarget">
<coherence:caching methodName="load" cacheName="customerCache" />
<coherence:flushing methodName="update" cacheNames="customerCache" />
</coherence:proxy>
<bean id="customerManager"
class="org.springmodules.cache.samples.business.CustomerManager" />
<property name="customerDao" ref="customerDao" />
</bean>
宣言的キャッシングのコンフィグレーションは、キャッシング機能を、アプリケーションのコア要件から効果的に分離します。そして、前述の問題を解決し、以下のような利点を提供します。