我正在使用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] 举报,一经查实,本站将立刻删除。