http://www.opensymphony.com/oscache/
1. フィルターキャッシング
フィルターキャッシングは、動的コンテンツと静的コンテンツ(PDFや画像ファイルなど)をキャッシングするのに使われます。
動的コンテンツでは、特定のJSPやサーブレットの結果をまるごとキャッシングしたい場合などに使用されます。静的コンテンツでは、ファイルをメモリに キャッシングさせることにより、HDDへのアクセスをなくし、高速にファイルをロードすることができます。これはApacheなどにもある機能で、大きい ファイルがある場合や、アクセス数が非常に多い場合に有効です。
サンプルでは、静的コンテンツのキャッシングを使用しています。全てのgifファイルをメモリにキャッシュさせる設定を行い、「profile.gif」という画像をキャッシングしています。
以下にソースと実装方法を記述します。
<filter> <filter-name>CacheFilter</filter-name> <filter-class> com.opensymphony.oscache.web.filter.CacheFilter </filter-class> <init-param> <param-name>time</param-name> <param-value>3600</param-value> </init-param> <init-param> <param-name>scope</param-name> <param-value>application</param-value> </init-param> </filter> <filter-mapping> <filter-name>CacheFilter</filter-name> <url-pattern>*.gif</url-pattern> </filter-mapping>
上記の設定により、1時間(3600秒)の間、applicationのスコープで全てのgifファイルをキャッシングすることができます。この方法ではcom.opensymphony.oscache.web.filter.CacheFilter
というフィルタークラスを使用します。
また、ここでは静的コンテンツの例を取り上げましたが、動的コンテンツをキャッシングする場合には、url-pattern
に特定のJSPやサーブレットのURLを入力すればOKです。
ただしその場合、パフォーマンス改善としては非常に有効ですが、そのコンテンツの項目全てがキャッシングされてしまうため、一部の情報は最新のものを表示 したい場合などには向きません。このサンプルでは、全体をキャッシングするページはないため使用していませんが、画面の仕様によっては非常に有効な使い方 となります。
サンプルアプリケーションを動作させる方は、下の値をカスタマイズしてキャッシングの動作を確認してみて下さい。
time | キャッシュされる期間を秒で設定 |
scope | キャッシュが有効なscopeをsession/applicationの何れかで設定 |
url-pattern | キャッシュ対象のコンテンツのURLパターンを設定 |
2. フラグメントキャッシュ
OSCacheのカスタムタグを使用すれば、JSPの特定の部分をキャッシングすることができます。サンプルでは、「現在の日時」をJSP内のコードで生成しており、これを毎回生成しないようにキャッシングする実装をしています。
以下にソースと実装方法を記述します。「web.xml」に、OSCacheのカスタムタグを使用できるように設定します。
<jsp-config> <taglib> <taglib-uri>http://www.opensymphony.com/oscache</taglib-uri> <taglib-location>/WEB-INF/oscache.tld</taglib-location> </taglib> </jsp-config>
次に、キャッシングしたいJSPの箇所をOSCacheのタグで囲みます。
<cache:cache time="60"> ・・・ jsp content **** </cache:cache>
ここでは、60秒(1分)間キャッシングするという設定をしています。
しかし、「新しく"分"の単位が切り替わる度にキャッシュを破棄したい」という様な場合には不向きです。この場合にはtime
属性ではなく、cron
属性にcron
式を設定します。これはUNIXのスケジューラとして利用されている「cron」の設定方法と同じ様に、キャッシュの期間を設定することができる大変強力で便利なものです。詳細は、OpenSymphonyのサイトを参照して下さい。
上記の例文をcron
式で記述したのが下記になります。
<%@taglib prefix="cache" uri="/WEB-INF/oscache.tld" %> ・・・・・・・・・・ <cache:cache cron="* * * * *"> 現在の日時:<%= new java.text.SimpleDateFormat( "yyyy/MM/dd hh:mm").format(new java.util.Date()) %><br> </cache:cache>
サンプルアプリケーションを動作させる方は、下の値をカスタマイズしてキャッシングの動作を確認してみて下さい。
time | キャッシュされる期間を秒で設定します |
cron | キャッシュされる期間をcron 式で設定します |
3.データキャッシュ
DBから取得した情報などをキャッシングするには、JSPではなくサーブレットで処理する必要があります。com.opensymphony.oscache.base.Cache
クラスを利用して実装することが可能です。サンプルでは、Profile
というデータクラスを生成しそのインスタンスをキャッシングしています。
以下にソースと実装方法を記述します。
public static final String PROFILE_CACHE_KEY = "profile_cache_key"; public static final String CACHE_OBJECT_KEY = "__oscache_cache"; //cache.propertiesに定義 /** * @param req * @param res * @throws ServletException * @throws IOException */ public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException{ Cache cache = (Cache)getServletContext() .getAttribute(CACHE_OBJECT_KEY); Profile profile = null; try{ //キャッシュからプロフィールを取得 profile = (Profile)cache.getFromCache(PROFILE_CACHE_KEY,30); }catch(NeedsRefreshException nre){ //キャッシュに存在しない or キャッシュの期限切れ profile = new Profile(); profile.setName ("山田 太郎" ); profile.setAge ("18" ); profile.setComment ("はじめまして" ); profile.setCacheDate(new SimpleDateFormat( "yyyy/MM/dd hh:mm:ss").format(new Date())); //キャッシュに登録 cache.putInCache (PROFILE_CACHE_KEY,profile); } req.setAttribute("profile",profile); req.getRequestDispatcher( "profile.jsp" ).forward(req,res); }
Cache
クラスはOSCacheのキャッシュシステムそのものを表現したクラスです。この
クラスを利用して、キャッシュシステムにオブジェクトを格納したり、取り出したりすることができます。このクラスのインスタンスはサーブレットコンテキス
トに格納され、そのキー名は「oscached.properties」に記述されているcache.key
(デフォルトでは"__oscache_cache")となります。
キャッシュに格納されたオブジェクトを取り出すには、
getFromCache(key名,キャッシュの期間(/秒))
逆に格納するには
putInCache(key名,キャッシュ対象Object)
を使用します。上記処理では、30秒でキャッシュが破棄されることになります。
getFromCache()
を実行する場合は、NeedsRefreshException
がthrowされる可能性があります。これはcacheが存在しない場合やキャッシュの有効期限切れの場合にthrowされる例外ですので、必ずそれを想定して例外処理を実装して下さい。
サンプルではその例外をcatchすると、新しいオブジェクトを生成しています。ここは通常のシステムであればDBからの取得処理になることが多いはずです。
サンプルアプリケーションを動作させる方は、下の値をカスタマイズしてキャッシングの動作を確認してみて下さい。
getFromCach の第二引数 | キャッシュされる期間を秒で設定します |
oscached.propertiesの設定方法
ここまでは、特に「oscache.properties」の設定について触れていませんでした。サンプルやテストで動作させる程度であれば特に初期設定でも問題有りませんが、状況に応じて独自の設定をすることが望ましいのは言うまでもありません。
ここでは、主なプロパティを一覧で紹介したいと思います。
プロパティ名 | 説明 |
cache.memory | メモリにキャッシュするか?(falseならHDにキャッシュ) |
cache.key | サーブレットコンテキストに格納されているCache オブジェクトのキー名 |
cache.capacity | キャッシュのサイズ |
cache.path | キャッシュが保存されるディレクトリパス |
cache.unlimited.disk | ディスクへのキャッシングを無制限に行うか?(falseなら行わない) |
まとめ
今回はOSCacheを用いたWEBコンテンツのキャッシングについて紹介しました。しかし、「キャッシングの有効性は理解したが、実務のどの場面で使用したらいいか分からない。」といった方も多いのではないでしょうか?
まず、Webのパフォーマンスチューニング全般に言えることですが、最初にしなければいけないことは、どのページを表示する時/どの処理を行う時に遅い と、ユーザが不満を持っているかを調べることです。これを行わずに、闇雲にキャッシング処理を入れたところで自己満足で終わってしまいます。
そして、その処理やページの一部分をキャッシングしても問題ないかを考えてみて下さい。
例えば、非常に複雑なSQLで統計情報を取得し、CVSでダウンロードするような処理があったとします。これを、「その時点での最新の統計」ではなく、 「10分ごとに最新になる統計」という仕様にして、「データキャッシュ」または「フィルターキャッシュ」を利用し、10分間キャッシングすることができれ ば、WEBサーバーとデータベースサーバーの負荷が軽減されるはずです。
他にも、非常にアクセスが多い人気サイトなどの場合、日記の様な コンテンツの更新をすると、「更新を受け付けました。更新が反映されるまでには数分程度かかります。」などと表示して、キャッシュを使っている例も見受け られます。こういったものも、「データキャッシュ」を使えば実装することが可能です。
以上、長くなりましたが、OSCacheはOpenSymphonyのサイト(英語)以外ではあまりドキュメントが存在しないため、この記事がこれから使ってみようという方のお役に立てば幸いです。
댓글 없음:
댓글 쓰기