MemcachedSessionHandlerで持続的接続を行うとESTABLISHEDが大量に発生する問題

December 27, 2016,
tags: php symfony


このエントリーをはてなブックマークに追加

3年前にsymfony2のMemcachedSessionHandlerの不具合についてというタイトルで記事を書きましたが間違っていました。。
今回は正しい方法を記載していきます。

ESTABLISHEDが大量に発生するのか?

Qiitaのほうに記事を書きました。

持続的接続の場合は、一度接続処理を行ったらPHPスクリプトが終了されても接続が持続されます。 おそらくfpmやapacheなりを再起動するまでは接続され続けます。

つまり、毎回接続するとどんどん持続的接続がされてしまいます。 よくあるSymfonyでのMemcachedSessionHandlerを使った接続のサンプルが以下のものになります。 この場合は毎回AddServerされるのでESTABLISHEDが大量に発生します。

// app/config/services.yml

services:
    session.memcached:
        class: Memcached
        arguments:
            persistent_id: %session_memcached_prefix%
        calls:
            - [ addServer, [ %session_memcached_host%, %session_memcached_port% ]]

    session.handler.memcached:
        class:     Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcachedSessionHandler
        arguments: [@session.memcached, { prefix: %session_memcached_prefix%, expiretime: %session_memcached_expire% }]

どう対処するのか?

いくつか対処法はあると思いますが、僕の場合はWrapperクラスを用意しています。

class MemcachedWrapper
{
    /**
     * @var \Memcached
     */
    private $instance;

    /**
     * @param $name
     * @param array $servers
     */
    public function __construct($name, array $servers)
    {
        if (class_exists('\\Memcached')) {
            $this->instance = new \Memcached($name);
            if ($this->instance->isPristine()) {
              $this->instance->addServers($servers);
            }
        }
    }

    /**
     * @param $name
     * @param $args
     * @return mixed
     */
    public function __call($name, $args)
    {
        if (is_object($this->instance)) {
            return call_user_func_array([$this->instance, $name],$args);
        }
    }

}

そしてservices.ymlを修正します。

services:
    session.memcached:
        class: MemcachedWrapper
        arguments:
            - %session_memcached_prefix%
            - [ %session_memcached_host%, %session_memcached_port% ]
    session.handler.memcached:
        class:     Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcachedSessionHandler
        arguments: [@session.memcached, { prefix: %session_memcached_prefix%, expiretime: %session_memcached_expire% }]

これで正しくmemcachedの持続的接続が実現できると思います!

comments powered by Disqus