调用第三方API会导致打开文件过多。" CLOSE_WAIT文件数导致的错误

时间:2015-01-14 00:00:52

标签: php ubuntu curl bigcommerce

我在我的应用程序中使用Bigcommerce PHP SDK。此SDK记录在此处:

https://github.com/bigcommerce/bigcommerce-api-php

我有一个脚本迭代大量的对象(1000个对象)。在每次迭代期间,使用此SDK对Bigcommerce进行了许多调用。例如,在脚本中的一个文件中,这里可能是一个获取产品skus的调用:

Bigcommerce::configure(array(
    'client_id' => BC_CLIENT_ID,
    'auth_token' => BC_AUTH_TOKEN,
    'store_hash' => BC_STORE_HASH,
));

Bigcommerce::getCollection('product/123/skus', 'Sku');

然后在脚本中使用的另一个文件中,有一个调用来检索另一个资源,比如产品的图像:

Bigcommerce::configure(array(
    'client_id' => BC_CLIENT_ID,
    'auth_token' => BC_AUTH_TOKEN,
    'store_hash' => BC_STORE_HASH,
));

Bigcommerce::getCollection('product/123/images', 'Sku');

我遇到的问题是,在此脚本运行一段时间后,我收到一条错误消息,指出打开的文件太多。这是实际错误:

PHP Fatal error:  Uncaught exception 'ErrorException' with message 'include(/var/www/html/app/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/Response.php): failed to open stream: Too many open files' in /var/www/html/app/vendor/composer/ClassLoader.php:386
Stack trace:
#0 /var/www/html/app/vendor/composer/ClassLoader.php(386): Illuminate\Exception\Handler->handleError(2, 'include(/var/ww...', '/var/www/html/a...', 386, Array)
#1 /var/www/html/app/vendor/composer/ClassLoader.php(386): Composer\Autoload\includeFile()
#2 /var/www/html/app/vendor/composer/ClassLoader.php(278): Composer\Autoload\includeFile('/var/www/html/a...')
#3 [internal function]: Composer\Autoload\ClassLoader->loadClass('Symfony\Compone...')
#4 /var/www/html/app/vendor/laravel/framework/src/Illuminate/Exception/WhoopsDisplayer.php(49): spl_autoload_call('Symfony\Compone...')
#5 /var/www/html/app/ve in /var/www/html/app/vendor/composer/ClassLoader.php on line 386

PHP Fatal error:  Uncaught exception 'ErrorException' with message 'include(/var/www/html/app/vendor/symfony/debug/Symfony/Component/Debug/Exception/FatalErrorException.php): failed to open stream: Too many open files' in /var/www/html/app/vendor/composer/ClassLoader.php:386
Stack trace:
#0 /var/www/html/app/vendor/composer/ClassLoader.php(386): Illuminate\Exception\Handler->handleError(2, 'include(/var/ww...', '/var/www/html/a...', 386, Array)
#1 /var/www/html/app/vendor/composer/ClassLoader.php(386): Composer\Autoload\includeFile()
#2 /var/www/html/app/vendor/composer/ClassLoader.php(278): Composer\Autoload\includeFile('/var/www/html/a...')
#3 [internal function]: Composer\Autoload\ClassLoader->loadClass('Symfony\Compone...')
#4 /var/www/html/app/vendor/laravel/framework/src/Illuminate/Exception/Handler.php(191): spl_autoload_call('Symfony\Compone...')
#5 [internal function]: Illuminate\Exception\Hand in /var/www/html/app/vendor/composer/ClassLoader.php on line 386

我已经能够确定在脚本运行时,与Bigcommerce建立的每个连接似乎都算作另一个"文件"那是开放的。我通过运行以下命令来看到这一点:

lsof -uroot | grep 104.236.XX.XXX | wc -l

此命令输出的数字不断增加。如果我实际查看打开的文件,我可以看到状态为CLOSE_WAIT的很长的文件列表,例如:

php       14005 root    5u     IPv4            1792827      0t0     TCP 104.236.XX.XXX:58077->192.200.169.163:https (CLOSE_WAIT)
php       14005 root    7u     IPv4            1793002      0t0     TCP 104.236.XX.XXX:58078->192.200.169.163:https (CLOSE_WAIT)
php       14005 root    8u     IPv4            1793003      0t0     TCP 104.236.XX.XXX:58079->192.200.169.163:https (CLOSE_WAIT)
php       14005 root    9u     IPv4            1793004      0t0     TCP 104.236.XX.XXX:58080->192.200.169.163:https (CLOSE_WAIT)
php       14005 root   10u     IPv4            1793005      0t0     TCP 104.236.XX.XXX:58081->192.200.169.163:https (CLOSE_WAIT)
php       14005 root   11u     IPv4            1793006      0t0     TCP 104.236.XX.XXX:58082->192.200.169.163:https (CLOSE_WAIT)
php       14005 root   12u     IPv4            1793007      0t0     TCP 104.236.XX.XXX:58083->192.200.169.163:https (CLOSE_WAIT)
php       14005 root   13u     IPv4            1793008      0t0     TCP 104.236.XX.XXX:58084->192.200.169.163:https (CLOSE_WAIT)
php       14005 root   14u     IPv4            1793093      0t0     TCP 104.236.XX.XXX:58085->192.200.169.163:https (CLOSE_WAIT)
php       14005 root   15u     IPv4            1793094      0t0     TCP 104.236.XX.XXX:58086->192.200.169.163:https (CLOSE_WAIT)
php       14005 root   16u     IPv4            1793095      0t0     TCP 104.236.XX.XXX:58087->192.200.169.163:https (CLOSE_WAIT)
php       14005 root   17u     IPv4            1793170      0t0     TCP 104.236.XX.XXX:58088->192.200.169.163:https (CLOSE_WAIT)
php       14005 root   18u     IPv4            1793234      0t0     TCP 104.236.XX.XXX:58089->192.200.169.163:https (CLOSE_WAIT)
php       14005 root   19u     IPv4            1793242      0t0     TCP 104.236.XX.XXX:58090->192.200.169.163:https (CLOSE_WAIT)
php       14005 root   20u     IPv4            1793315      0t0     TCP 104.236.XX.XXX:58091->192.200.169.163:https (CLOSE_WAIT)
php       14005 root   21u     IPv4            1793328      0t0     TCP 104.236.XX.XXX:58092->192.200.169.163:https (CLOSE_WAIT)
php       14005 root   22u     IPv4            1793389      0t0     TCP 104.236.XX.XXX:58093->192.200.169.163:https (ESTABLISHED)
php       14005 root   23u     IPv4            1793390      0t0     TCP 104.236.XX.XXX:58094->192.200.169.163:https (ESTABLISHED)
php       14005 root   24u     IPv4            1793458      0t0     TCP 104.236.XX.XXX:58095->192.200.169.163:https (ESTABLISHED)
php       14005 root   25u     IPv4            1793464      0t0     TCP 104.236.XX.XXX:58096->192.200.169.163:https (ESTABLISHED)
php       14005 root   26u     IPv4            1793465      0t0     TCP 104.236.XX.XXX:58097->192.200.169.163:https (ESTABLISHED)

此列表会继续变得越来越长,直到脚本出现错误并且打开太多文件"我在上面显示的错误。

我的假设是这些CLOSE_WAIT文件导致我达到可以打开的文件数量的限制。有什么办法可以摆脱这些文件吗?为什么他们被考虑"开放"文件如果与Bigcommerce的连接已经完成?

也许我错误地使用了SDK?换句话说,是否有办法让所有调用都来自单个Bigcommerce类而不是每次都创建一个新连接?

1 个答案:

答案 0 :(得分:0)

我能够通过改变configure方法来解决这个问题,以便在每次调用时都不创建新连接。新方法可以在github上的fork中找到:

https://github.com/flyingL123/bigcommerce-api-php