У меня есть основной скребок, который посещает URL-адрес, проверяет ссылку на другой заданный URL-адрес и возвращает текст привязки для любых найденных ссылок. Скребок также возвращает статус http как исходной, так и целевой страницы для каждой ссылки.
Скребок запускается с выделенной машины Windows 7, на которой работает WAMP. 8 гигабайт оперативной памяти (память в этом не проблема, поскольку скребок даже не использует 30% того, что доступно с файлом .ini, установленным для использования столько, сколько он хочет). Поскольку он работает от имени бизнеса, интернет-соединение представляет собой фиксированную волоконно-оптическую линию IP, скорость передачи которой составляет около 50 Мб).
Я использую упаковку для завитков https://github.com/php-curl-class/php-curl-class, и это выполняется через стек WAMP (Apache 2.4.4, PHP 5.4.16) на довольно мощной машине.
Я использую версию cURL:
'version_number' => int 466432
'age' => int 3
'features' => int 3005
'ssl_version_number' => int 0
'version' => string '7.30.0' (length=6)
'host' => string 'i386-pc-win32' (length=13)
'ssl_version' => string 'OpenSSL/0.9.8y' (length=14)
'libz_version' => string '1.2.7' (length=5)
Скребок разбивает URL-адреса на группы по 175, а затем пропускает их через мульти-вывод cURL, выводя результаты в CSV.
Моя проблема заключается в том, что когда скребок запускается в первый раз (около 1000 URL-адресов обрабатывается примерно за 10 минут), доступ к серверу становится немного медленным. Но при повторном запуске сервер перестает отвечать на запросы, и через эту машину невозможно выполнять какие-либо действия в Интернете.
Что меня смущает, так это то, что когда я смотрю Resource Monitor, количество активных TCP-соединений перемещается между 300/500 для первого запуска, а затем не будет перемещаться после 10 активных соединений после этой точки.
Что действительно странно, так это то, что монитор ресурсов показывает, что активны / доступны только 10 TCP-подключений (показано на графике спарклайна), но на вкладке информации о TCP-подключениях показано несколько сотен подключений, запущенных httpd.exe — все под одним и тем же PID но с разными портами.
Почему количество используемых активных TCP-соединений так резко сокращается, в то время как процесс Apache httpd.exe все еще удерживает порты?
Что определяет, сколько активных TCP-подключений может иметь Windows-ПК, и как насчет запросов cURL будет эффективно уменьшать это число?
Вот копия функции, выполняющей вызовы cURL:
private function getUrls_curl ($urls = array(), $statusOnly = FALSE)
{
$curl = new \DAMC\modules\_global\curl();
//set some extra options
$curl->setOpt(CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)');
$curl->setOpt(CURLOPT_TIMEOUT, '300');
$curl->setOpt(CURLOPT_SSL_VERIFYPEER, FALSE);
if ($statusOnly === FALSE)
{
$curl->success( array($this, 'parseUrl') );
$curl->error( array($this, 'error') );
}
else
{
$curl->complete( array($this, 'statusOnly') );
$curl->error( array($this, 'statusOnly') );
}
$curl->get($urls);
$curl->close();
}
$curl->get()
Метод определен в библиотеке, с которой я связан выше, и выполняет curl_multi следующим образом:
public function get($url_mixed, $data=array())
{
if (is_array($url_mixed))
{
$curl_multi = curl_multi_init();
$this->_multi_parent = true;
$this->curls = array();
foreach ($url_mixed as $url)
{
$curl = new Curl();
$curl->_multi_child = true;
$curl->setOpt(CURLOPT_URL, $this->_buildURL($url, $data), $curl->curl);
$curl->setOpt(CURLOPT_CUSTOMREQUEST, 'GET');
$curl->setOpt(CURLOPT_HTTPGET, true);
$this->_call($this->_before_send, $curl);
$this->curls[] = $curl;
$curlm_error_code = curl_multi_add_handle($curl_multi, $curl->curl);
if (!($curlm_error_code === CURLM_OK)) {
throw new \ErrorException('cURL multi add handle error: ' .
curl_multi_strerror($curlm_error_code));
}
}
foreach ($this->curls as $ch)
{
foreach ($this->_options as $key => $value)
{
$ch->setOpt($key, $value);
}
}
do {
$status = curl_multi_exec($curl_multi, $active);
} while ($status === CURLM_CALL_MULTI_PERFORM || $active);
foreach ($this->curls as $ch)
$this->exec($ch);
}
else
{
$this->setopt(CURLOPT_URL, $this->_buildURL($url_mixed, $data));
$this->setOpt(CURLOPT_CUSTOMREQUEST, 'GET');
$this->setopt(CURLOPT_HTTPGET, true);
return $this->exec();
}
}
Дважды проверьте время ожидания вашего curl-запроса (300 секунд) по сравнению с временем ожидания PHPScript (http://php.net/manual/de/function.set-time-limit.php)
Если ваш сценарий останавливается до истечения времени ожидания cURL, вы никогда не получите ответ.
Других решений пока нет …