【发布时间】:2015-03-21 13:54:07
【问题描述】:
我有一个基本的抓取工具,它访问一个 URL,检查指向另一个给定 URL 的链接,并返回任何找到的链接的锚文本。抓取工具还会返回每个链接的源页面和目标页面的 http 状态。
刮板正在运行 WAMP 的专用 Windows 7 机器上运行。 8 gigs 的 RAM(内存不是问题,因为刮板甚至没有使用 .ini 文件集可用的 30% 的内容,以便尽可能多地使用)。由于它是代表企业运行的,因此互联网连接是一条固定的 IP 光纤线路,传输速度约为 50mb)。
我使用的 curl 包装器是 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。
我的问题是,当爬虫第一次运行时(大约 10 分钟处理 1000 个 URL 左右),访问服务器变得有点慢。但是当第二次运行时,服务器变得无响应,并且无法通过该机器进行任何互联网活动。
让我感到困惑的是,当我观看资源监视器时,第一次运行时活动 TCP 连接的数量在 300/500 之间移动,然后在那之后不会超过 10 个活动连接。
真正奇怪的是,资源监视器显示只有 10 个 TCP 连接处于活动状态/可用(通过迷你图显示),但 TCP 连接信息选项卡显示 httpd.exe 正在运行数百个连接 - 全部在相同的 PID 下使用不同的端口。
为什么在 Apache httpd.exe 进程仍在占用端口的情况下,正在使用的活动 TCP 连接数量大幅减少?
什么定义了 Windows PC 可以拥有多少活动 TCP 连接,以及 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();
}
}
【问题讨论】:
-
您应该包括可能相关的其他详细信息,例如操作系统、Apache、PHP 和 cURL 版本。不确定它是否会有所作为,但您可以尝试直接通过 CLI 而不是 Apache 运行。
-
该示例代码中也没有与
curl_multi_相关的代码? -
@JeremiahWinsley 添加了信息。
-
@RiggsFolly 我包含了实际执行 cURL GET 请求的方法。
-
需要更多信息。你的硬件到底是什么。 i386 win32 很少告诉我们有关硬件的信息。什么Windows版本?经验?赢7?赢8?赢2008服务器?有多少内存?您的互联网连接速度有多快?您是否在托管设施的专用 Windows 机器上运行?还是在家里?如果您在家中从盒子中刮擦,请不要。在专用的 Windows 服务器上执行此操作。您最不想要的就是您的 ISP 关闭您的帐户。