AppEngineでsessionを有効にしていると遅くなる
Google App Engineのsession情報はDatastoreを使っているため若干遅い。セッションを使わないアプリならセッションを無効にしておいた方が良い。
appengine-web.xmlにて
※デフォルト(sessions-enabledの記述がない場合)ではセッションは無効になっている。
Datastoreを使うということはDatastoreTimeoutExceptionが発生する可能性があるということ。なので極力切っておいたほうがいいようだ。
あと、jspはセッションがデフォルトでは有効になっているようなので無効にしておいた方がよい。
<%@page pageEncoding="UTF-8" session="false"%>
今日のエントリは全部twitterの情報メモ。
追記
いくつかtwitterでツッコミを頂けたのでjspのセッション無効が意味があるのかをちょっと検証してみた。
検証内容としてはセッションを有効にしている場合にセッションをjspでset,getしていないにも関わらずDatastoreへのアクセスが発生するのかどうか。先に結論を言うとjspのセッションを無効にするのは意味がないと思う。
検証方法はmakeSyncCallをフックしてDatastoreへのアクセスが発生したらログを出力するようにする。AppEngineではDatastoreやMemcacheなどサービスへのアクセスが発生した場合はmakeSyncCallというMethodが実行される仕組みになっている。このmakeSyncCallはApiProxy.setDelegate()を使う事で実行する処理を変更できる。今回使用したソースは下記。
import java.util.concurrent.Future; import java.util.logging.Logger; import com.google.apphosting.api.ApiProxy; import com.google.apphosting.api.ApiProxy.ApiConfig; import com.google.apphosting.api.ApiProxy.ApiProxyException; import com.google.apphosting.api.ApiProxy.Delegate; import com.google.apphosting.api.ApiProxy.Environment; import com.google.apphosting.api.ApiProxy.LogRecord; public class TestDelegate implements Delegate<Environment> { private static final Logger logger = Logger.getLogger(TestDelegate.class.getName()); private static Delegate<Environment> originalDelegate = ApiProxy.getDelegate(); public void setUp() throws Exception { logger.info("setUp"); ApiProxy.setDelegate(this); } public byte[] makeSyncCall(Environment env, String service, String method, byte[] requestBuf) throws ApiProxyException { logger.info("makeSyncCall/" + service + "/" + method); return originalDelegate.makeSyncCall(env, service, method, requestBuf); } public Future<byte[]> makeAsyncCall(Environment env, String service, String method, byte[] requestBuf, ApiConfig config) { logger.info("makeAsyncCall/" + service + "/" + method); return originalDelegate.makeAsyncCall( env, service, method, requestBuf, config); } public void log(Environment env, LogRecord rec) { originalDelegate.log(env, rec); } }
自分のアプリケーションのどこかでnew TestDelegate().setUp();を実行した後のサービスは必ず上記のクラスのmakeSyncCallを経由するようになる。jspにはsession="false"は記載しなかった。この仕組みで検証した結果次のようになった。
■appengine-web.xmlにて
- session変数にアクセスしなかった場合のリクエスト
- makeSyncCall/memcache/Get
- makeSyncCall/memcache/Set
※session変数にアクセスしなくてもmemcacheのアクセスが発生しているが、Datastoreへのアクセスは発生していない。
- session変数にアクセスした場合のリクエスト
- makeSyncCall/memcache/Get
- makeSyncCall/datastore_v3/Put
- makeSyncCall/memcache/Set
※session変数にアクセスするとDatastoreへのアクセスが発生する。
また、appengine-web.xmlにて
そうそう、セッションを使う場合の注意点としてほかにもセッションはDatastoreに登録されるため定期的に削除する必要がある。AppEngineでは下記URLを実行するとセッション情報を消してくれる便利な機能がある。
/_ah/sessioncleanup?clear
セッションを使う場合は下記のようにcron.xmlで60分毎に削除などの設定をしておいた方がいいだろう。
<cron> <url>/_ah/sessioncleanup?clear</url> <description>Session cleanup every 60 minutes</description> <schedule>every 60 minutes</schedule> </cron>
あわせてweb.xmlにて下記のセキュリティ設定もしておいた方がいい。セキュリティ設定をしていない場合は上記のURLを実行されて意図せずセッションを消される恐れがある。
<security-constraint> <web-resource-collection> <url-pattern>/_ah/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>admin</role-name> </auth-constraint> </security-constraint>