Вызов стороннего API вызывает «слишком много открытых файлов». ошибка из-за количества файлов CLOSE_WAIT

Я использую Bigcommerce PHP SDK в своем приложении. Этот SDK задокументирован здесь:

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

У меня есть скрипт, который перебирает большой массив объектов (1000 объектов). Во время каждой итерации с помощью этого SDK совершается множество звонков в Bigcommerce. Например, в одном файле скрипта может быть вызов для получения продукта для продукта:

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)

Этот список продолжает увеличиваться и увеличиваться до тех пор, пока скрипт не выдаст ошибку «Too many files open», которую я показал выше.

Я предполагаю, что эти CLOSE_WAIT файлы заставляют меня достигать предела количества файлов, которые могут быть открыты. Что я могу сделать, чтобы избавиться от этих файлов? Почему они считаются «открытыми» файлами, если подключение к Bigcommerce уже установлено?

Возможно, я неправильно использую SDK? Другими словами, есть ли способ сделать все звонки с одного Bigcommerce класс, а не создавать новое соединение каждый раз?

1

Решение

Я смог решить эту проблему, изменив configure метод, чтобы не создавать новое соединение каждый раз, когда он вызывается. Новый метод доступен в моей развилке на github:

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

0

Другие решения

Других решений пока нет …