使用 Memcached 进行会话时打开的文件太多
Too many open files when using Memcached for sessions
我正在使用 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辅助 | grep php
root 3233 0.0 0.2 207464 16164 ? Ss Mar16 0:02 php-fpm: 主进程 (/etc/php5/fpm/php-fpm.conf)
www-数据 3236 0.0 0.8 238796 65796 ? S Mar16 0:50 php-fpm: 池 www
www-数据 3646 0.0 0.7 231176 57808 ? S Mar16 0:42 php-fpm: 池 www
www-数据 7503 0.1 0.7 234820 59920 ? S11:520:34php-fpm: 池 www
ubuntu 8224 0.0 0.0 10436 860 pts/0 S+ 16:53 0:00 grep --color=auto php
2.Checking 任何带有 lsof 的 php5-fpm childs,除其他外,它显示有 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 应用程序发出请求时,都会打开一个到内存缓存服务器的新套接字连接,但它永远不会关闭。因此,最终它在开始失败时达到了极限。我认为可能与超时连接或类似的东西有关,但到目前为止还没有找到任何东西。
重新启动 php5-fpm 似乎 "solve" 问题,但只有在发出另一个 1k 请求之前。
我暂时切换回文件,问题消失了。我也尝试过使用 Memcache
(php5-memcache
) 而不是 Memcached
并且问题已解决,但我宁愿使用 php5-memcached
因为它看起来维护得更好。
关于如何解决这个问题的任何想法?
非常感谢!
如果有用ps,我正在使用的特定 php 版本:
PHP 5.5.9-1ubuntu4.6 (cli) (built: Feb 13 2015 19:17:11)
libmemcached version => 1.0.8
我们遇到了这个问题,我们通过在 config.yml
的内存缓存中缓存元数据来解决这个问题
orm:
default_entity_manager: default
entity_managers:
default:
metadata_cache_driver:
type: memcache
host: localhost
port: 11211
instance_class: Memcache
query_cache_driver:
type: memcache
host: localhost
port: 11211
instance_class: Memcache
否则,如果您更喜欢通过 apc 进行缓存,它也会修复它,我都试过了:
metadata_cache_driver: apc
query_cache_driver: apc
希望这对您有所帮助,有关此问题的更多信息:https://github.com/FriendsOfSymfony/FOSUserBundle/issues/1062#issuecomment-29473883
好的,多亏了这个我找到了解决方案:
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 的包装器 class。简单的解决方法就是注释掉这一行,暂时避免使用持久连接:
#arguments:
# persistent_id: %session_memcached_prefix%
这解决了问题,尽管它并不理想。
我希望它可以帮助您节省一些时间并避免头痛!
谢谢大家的帮助。
我正在使用 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辅助 | grep php
root 3233 0.0 0.2 207464 16164 ? Ss Mar16 0:02 php-fpm: 主进程 (/etc/php5/fpm/php-fpm.conf)
www-数据 3236 0.0 0.8 238796 65796 ? S Mar16 0:50 php-fpm: 池 www
www-数据 3646 0.0 0.7 231176 57808 ? S Mar16 0:42 php-fpm: 池 www
www-数据 7503 0.1 0.7 234820 59920 ? S11:520:34php-fpm: 池 www
ubuntu 8224 0.0 0.0 10436 860 pts/0 S+ 16:53 0:00 grep --color=auto php
2.Checking 任何带有 lsof 的 php5-fpm childs,除其他外,它显示有 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 应用程序发出请求时,都会打开一个到内存缓存服务器的新套接字连接,但它永远不会关闭。因此,最终它在开始失败时达到了极限。我认为可能与超时连接或类似的东西有关,但到目前为止还没有找到任何东西。
重新启动 php5-fpm 似乎 "solve" 问题,但只有在发出另一个 1k 请求之前。
我暂时切换回文件,问题消失了。我也尝试过使用 Memcache
(php5-memcache
) 而不是 Memcached
并且问题已解决,但我宁愿使用 php5-memcached
因为它看起来维护得更好。
关于如何解决这个问题的任何想法?
非常感谢!
如果有用ps,我正在使用的特定 php 版本:
PHP 5.5.9-1ubuntu4.6 (cli) (built: Feb 13 2015 19:17:11)
libmemcached version => 1.0.8
我们遇到了这个问题,我们通过在 config.yml
的内存缓存中缓存元数据来解决这个问题 orm:
default_entity_manager: default
entity_managers:
default:
metadata_cache_driver:
type: memcache
host: localhost
port: 11211
instance_class: Memcache
query_cache_driver:
type: memcache
host: localhost
port: 11211
instance_class: Memcache
否则,如果您更喜欢通过 apc 进行缓存,它也会修复它,我都试过了:
metadata_cache_driver: apc
query_cache_driver: apc
希望这对您有所帮助,有关此问题的更多信息:https://github.com/FriendsOfSymfony/FOSUserBundle/issues/1062#issuecomment-29473883
好的,多亏了这个我找到了解决方案:
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 的包装器 class。简单的解决方法就是注释掉这一行,暂时避免使用持久连接:
#arguments:
# persistent_id: %session_memcached_prefix%
这解决了问题,尽管它并不理想。 我希望它可以帮助您节省一些时间并避免头痛! 谢谢大家的帮助。