微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

symfony – 使用Memcached进行会话时打开的文件太多

我正在使用ubuntu Nginx PHP5-fpm symfony2,我最近从文件切换到Memcached(PHP5-memcached)进行会话.
从那以后,我开始在一段时间后得到500个响应代码错误.这是错误日志中的样子(无法打开流:打开太多):

"PHP message: PHP Warning:  simplexml_load_file(.../vendor/friendsofsymfony/user-bundle/FOS/UserBundle/Resources/config/doctrine/User.orm.xml): Failed to open stream: Too many open files in .../vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.PHP on line 736
PHP message: PHP Warning:  simplexml_load_file(): I/O warning : Failed to load external entity ".../vendor/friendsofsymfony/user-bundle/FOS/UserBundle/Resources/config/doctrine/User.orm.xml" in .../vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.PHP on line 736
PHP message: PHP Warning:  include(.../vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/MappingException.PHP): Failed to open stream: Too many open files in .../vendor/composer/ClassLoader.PHP on line 382

经过一些研究,我发现它似乎与Memcached在会话中的使用有关:

>那些运行的PHP5-fpm进程:

ps aux | grep PHP

root 3233 0.0 0.2 207464 16164? Ss Mar16 0:02 PHP-fpm:master process(/etc/PHP5/fpm/PHP-fpm.conf)
www-data 3236 0.0 0.8 238796 65796? S Mar16 0:50 PHP-fpm:pool www
www-data 3646 0.0 0.7 231176 57808? S Mar16 0:42 PHP-fpm:pool www
www-data 7503 0.1 0.7 234820 59920? S 11:52 0:34 PHP-fpm:pool www
ubuntu 8224 0.0 0.0 10436 860 pts / 0 S 16:53 0:00 grep –color = auto PHP

2.使用lsof检查任何PHP5-fpm子项,它显示有1k打开文件描述符指向具有已建立连接的Memcache实例:

sudo lsof -p 3236

…
PHP5-fpm 3236 www-data  672u  IPv4             107781      0t0    TCP hostname:54403->memcacheIp:11211 (ESTABLISHED)
PHP5-fpm 3236 www-data  673u  IPv4             108827      0t0    TCP hostname:54411->memcacheIp:11211 (ESTABLISHED)
PHP5-fpm 3236 www-data  674u  IPv4             107800      0t0    TCP hostname:54418->memcacheIp:11211 (ESTABLISHED)
... 

超过一千个这样的条目,我认为当它到达1024时开始失败,这是打开文件描述符的限制:

ulimit  -n
1024

问题是这是一个QA环境,不会用于超过1或2个并发用户,因此所有这些打开文件描述符都不是活动会话.我注意到每次我向symfony2应用程序发出请求时,都会打开一个到memcache服务器的新套接字连接,但它永远不会关闭.所以,最终它在开始失败时达到极限.我认为可能是与超时连接有关的东西或类似的东西,但到目前为止还没有找到任何东西.

重新启动PHP5-fpm似乎“解决”了这个问题,但只有在发出另外1k个请求之前.

我暂时切换回文件,问题就消失了.此外,我尝试使用Memcache(PHP5-memcache)而不是Memcached,问题解决但我宁愿使用PHP5-memcached,因为它似乎更好地维护.

有关如何解决这个问题的任何想法?

非常感谢你!

如果它有帮助,我正在使用的特定PHP版本:

PHP 5.5.9-1ubuntu4.6 (cli) (built: Feb 13 2015 19:17:11) 
libmemcached version => 1.0.8

解决方法:

好的,我已经找到了解决方案,感谢:

http://php.net/manual/en/memcached.construct.php(见@Tobias评论)

这个https://gist.github.com/K-Phoen/4327229(见@cmenning评论)

我使用Memcached和sessions.yml如下:

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% }]

事实证明,如果为Memcached提供persistent_id参数,它将保持请求之间的连接.来自PHP.net:

persistent_id

By default the Memcached instances are destroyed at the end of the
request. To create an instance that persists between requests, use
persistent_id to specify a unique ID for the instance. All instances
created with the same persistent_id will share the same connection.

问题是如果你使用persistent_id(性能更好),你必须在调用addServer之前检查是否已经添加了服务器,否则它将添加一个新服务器&创建一个新的连接,即使它是相同的服务器(它不检查欺骗.
像这样的东西:

        $instance = new Memcached($persistent_id);

        // Add server if no connections listed. 
        if (!count($instance->getServerList())) {
            $instance->addServers($server);
        }

但是为此你需要创建一个Memcached的包装类.简单的解决方法就是注释掉这一行,并避免暂时使用持久连接:

    #arguments:
    #  persistent_id: %session_memcached_prefix%

解决了这个问题,即使它并不理想.
我希望它可以帮助您节省一些时间,避免头痛!
谢谢大家的帮助.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐