2012年2月29日水曜日

PlayframeworkでMemcachedがタイムアウトする

PlayでMemcachedを使っているとたまに存在するはずのキーでnullが返ってくることがある。
ソース追ったらPlayのMemcachedImplでgetメソッドの実行に1秒以上かかったらそこでタイムアウトするようになってたよ。。。(--

Memcachedはherokuのアドオンをそのまま使用しているのでおそらくアメリカ東海岸にある。
なので、日本のlocalhostからテストすると割とすぐにタイムアウトしちゃうね。。。
東海岸のherokuサーバー上から使う場合は多分タイムアウトすることはないと思うけど。

ちなみにMemcachedImplのタイムアウトコードはハードコードなんで設定を変更することもできない。
対策としては

A. localhostではMemcachedを使わない設定にする
B. 近場に別のMemcachedを立てて、localhostからはそれを使うようにする

の二つが考えられるけど、Aは実行コードが変わるのであまり気が進まないし、Bは面倒くさい。
どうしたもんだろ?

ていうか問題はそこじゃなくて、Cacheを使う際に「存在するはずのキーでnullが返ってくることはありえる」ということをちゃんと認識しておくことなんだよな。

2012年2月16日木曜日

PlayのControllerはJavaじゃない。その1

Playはとても面白いフレームワークだと思う。
ソースもまぁまぁ読んだけど、「やりすぎ。。。」と思うくらい作りこんであるところと「え?こんなあっさりした実装で良いの???」と思う部分のバランスがなんだか不思議な感じ。
久々にソースを読んで感心もしたし、徹頭徹尾ユーザーが「簡単に」Webアプリを作れるように工夫を凝らしていると思う。

そんな中でコントローラは特にやりすぎな方の例でJavaを長くやってきた身からするとそんなんありかよ?と思う部分がかなりある。
ここではそういう部分についていくつか書いておきたい。

まずはその1

staticオブジェクトにアクセスしているのにスレッドセーフ
PlayではHTTPアクションをControllerクラスのサブクラスを作ってそこにstaticメソッドとして定義する。
例えばHelloworldならこんなメソッド定義になる。

public static void hello() {
    renderText("Hello world");
}

とても簡単。
しかし、見ての通りパラメータやセッションなどの情報はどこからも渡されていない。
パラメータについてはメソッドの引数として定義すればそれがそのまま使えたりもするんだけれど、sessionやparamsオブジェクトにはstatic変数を介してアクセスできる。

public static void hello2() {
    String name = params.get("name");
    renderText("Hello " + name);
}

ちょっと待て!って思うよね?
HTTPリクエストなんかはマルチスレッドでパラに動くはずなのにstatic変数なんか使ったらスレッドセーフにならないじゃん。

ところが、これなんとClassLoaderレベルで小細工していてClassロード時にstatic変数をThreadLocalな変数に差し替えている。
つまりコードを見る限り明らかにstatic変数なんだけど、実行時には自動的にThreadLocal変数になっているという荒技。。。(--

もう、この時点でJavaではないと思う。(^^;;;

2012年2月7日火曜日

Herokuのシングルdynoの動作

herokuでは2台以上のdynoを契約すると(つまり課金すると)その上で動いているアプリケーションはidle状態になることなく動き続ける(らしい)けれど、シングルの時には2時間程度リクエストのない状態が続くとアプリは停止し、次にリクエストが来た時にまたスタートアップする仕組みになっています。

逆に言えば定期的にリクエストが来てさえいれば動き続けるわけでherokuアプリ上からcronアドオンなり、独自スレッドなりで1時間に1回程度自分自身に対してHttpRequestを投げてやればidleになることはありません。

監視されているのはHttpRequestだけなので、独自スレッドで定期的にDBへの読み書き処理を行っていてもHttpRequestが来なければ容赦なく落とされます。
夜間バッチなどの処理を組む場合には注意が必要かもしれません。(2台契約しろという話かもしれないけれど、その場合は複数のホストで処理が同時に実行される可能性を考慮せねばならずやっぱり注意が必要)

ちなみに1度idleになったあとに再起動した時にはIPが変わります。というか再起動時には必ずIPが変わっているっぽいです。
スラグのコンパイル&コピーがいつ行われているのかわかりませんが、この辺もスラグサイズをあまり大きくするなという注意事項の要因のひとつでしょうね。

2012年2月1日水曜日

Groovyのテンプレートエンジンが落ちる

GroovyのテンプレートエンジンをJavaコードから使おうとしているんだけど、180Kのテンプレートを渡すとClassFormatErrorで落ちちゃうよ。。。(--

GroovyはテンプレートをJavaのバイトコードにコンパイルするのでその過程でJavaの64K制限(具体的に何が制限されているのか良くわからないけど)に引っかかるらしい。

Velocityの方が軽いし便利だったな。。。(--