ゴミ収集車にはめられた

この記事はだいぶ前に書かれたものなので情報が古いかもしれません

ゴミ収集……英語で言うとガベージコレクションですか。プログラムには、そう呼ばれる機能があるんですよ。ってか、僕もつい最近知った。

ガベージコレクションは、動的に確保したメモリ領域のうち、不要になったものを領域を解放する機能なんだそうです。まあ、ぶっちゃけ言葉の上では何言ってるか分かりますが、実際的なところはよく分かっていません。


CakePHPでのタイムアウト設定

CakePHPで管理画面なんかを作るとき、たいていはAuthコンポーネントを使ったりすると思うんですけど、そのセッション時間の設定を、core.phpでしますよね。

core.phpに書いてある以下の部分でセッションが切れるまでの時間を設定できます。

Configure::write('Session.timeout', '120');
Configure::write('Security.level', 'medium');

Session.timeoutってのは、文字通りタイムアウトの秒を設定する項目なんですが、じゃあここを120にしたらタイムアウトまでの時間が120秒になるのかというとそんなことはなくて、その下のSecurity.levelによって変わってきます。Security.levelは「high」「medium」「low」の3つが指定できて、その指定によって最終的なタイムアウトの時間は↓な感じになります。

'high' =>  'Session.timeout' x 10
'medium'  => 'Session.timeout' x 100
'low'  => 'Session.timeout' x 300

上記の例だとSession.timeoutが120でSecurity.levelがmediumなので、120 x 100 = 12000秒になるってことですね。12000秒っていったら、3時間ちょいってとこかしら。つまりこの設定だと、一度ログインしたら3時間くらいはログインが切れない状態になる……

はずなんですが!

何か前にもこんな言い方した記事があったような気がしたな……まあそれはいい。

実際、こうやってある程度長めの時間を設定しているにもかかわらず、20分くらいでログインが切れちゃったりする場合がありました。Security.levelをlowにすると問題は解決するとか、そういう話も聞いたことがあったので試してみましたが、一向に解決しない。

で、最終的に辿り着いたのがガベージコレクションでした。


ガベージコレクションの設定

phpinfo()とかでサーバーの設定を見てみると、セッションの設定のところにこんなのがあると思うんですよ。

session.gc_maxlifetime

どうやらこいつがサーバー上でのセッションの有効期限になるようです。

例えばこれが1200秒に設定されている場合、セッションが生成されてから1200秒以上、つまり20分以上経っているものについては、ゴミ収集の対象になってしまうということみたいですね。

こいつが曲者だったようです。

CakePHPでセッションのタイムアウト時間を3時間に設定していても、こいつが20分だと、20分の方が優先されるみたいで、有効期限切れでゴミ収集車に収集されてしまう可能性がある、要はセッションが切れてしまうという現象が起きてしまうようです。

だから、CakePHPでタイムアウト設定を12000秒にするには、こいつも12000秒に書き換えてあげないといけない。そんなに難しいものではなくて、設定自体は一文で済む。bootstrap.phpにでも書いとけば良い。

ini_set('session.gc_maxlifetime', 12000);

これで実際に12000秒経つまでタイムアウトしなくなった。少なくとも僕がやった限りでは。


実際に消されるかは量子力学的問題

量子力学の話をする気は全くなくて……というかただの確率の話でしかないんですが、実際にゴミ収集されるかどうかってのは、確率で決まっているそうなんです。つまり20分経ったからと言って、確実に消されるわけでもないらしい。

さっきのsession.gc_maxlifetime以外にも、サーバーではこんなような設定項目もあります。

session.gc_divisor
session.gc_probability

この二つが実際に何を意味するものなのかは詳しく調べてないので分かりませんが、実際にゴミ収集が行われる確率は、この2つの項目によって決まるみたいです。計算方法は至ってシンプル。

session.gc_probability / session.gc_divisor

つまり、session.gc_probabilityが1でsession.gc_divisorが100だったら、1/100……1%の確率でセッションが消されるってことですね。

ちなみに発動のタイミングはsession_start()の時らしいです。つまり誰かがサイトにアクセスして、session_start()が呼ばれた時に、1%の確率で不要と判断されているセッションが消される、という解釈になるようです。

まあ、正直なところ僕はそこまで深く理解していないので、もっとちゃんとした文献を漁りたい方は、こちらの記事などを参考にされると良いと思います。


しかしこんな設定があったとはなぁ……。

ってか、そういうことならcore.phpの設定とか、意味ないじゃんとか思っちゃうよね。いや、全く無意味とは言わないですけどね。core.phpの設定もあれはあれで、結構いろいろ頑張ってるんだよ、きっと。

でもこれを知らない俺みたいなやつは、何で設定時間延ばしてるのに切れちゃうんだよ~って、困惑するしかないですよね。

何にしても、解決して良かったさ。

まだコメントはいただけてないみたい……
もしかしたら何か関連しているかも?