为了加速 cURL,我建议为 API 创建特殊类(例如ApiClient
)并使用一个共享的 cURL 处理程序,只为每个请求更改 URL。还切断名称解析请求并使用压缩响应。
我每天需要从一个 API 服务器处理大约 100 万个实体,这限制了我们只能使用一个并发连接。我创建了那个类。我希望它能帮助其他人优化他们的 curl 请求。
class ApiClient
{
const CURL_TIMEOUT = 3600;
const CONNECT_TIMEOUT = 30;
const HOST = 'api.example.com';
const API_TOKEN = 'token';
/** @var resource CURL handler. Reused every time for optimization purposes */
private $ch;
/** @var string URL for API. Calculated at creating object for optimization purposes */
private $url;
public function __construct()
{
$this->url = 'https://' . self::HOST . '/v1/entity/view?token=' . self::API_TOKEN . '&id=';
// Micro-optimization: every concat operation takes several milliseconds
// But for millions sequential requests it can save a few seconds
$host = [implode(':', [ // $host stores information for domain names resolving (like /etc/hosts file)
self::HOST, // Host that will be stored in our "DNS-cache"
443, // Default port for HTTPS, can be 80 for HTTP
gethostbyname(self::HOST), // IPv4-address where to point our domain name (Host)
])];
$this->ch = curl_init();
curl_setopt($this->ch, CURLOPT_ENCODING, ''); // This will use server's gzip (compress data)
// Depends on server. On some servers can not work
curl_setopt($this->ch, CURLOPT_RESOLVE, $host); // This will cut all requests for domain name resolving
curl_setopt($this->ch, CURLOPT_TIMEOUT, self::CURL_TIMEOUT); // To not wait extra time if we know
// that api-call cannot be longer than CURL_TIMEOUT
curl_setopt($this->ch, CURLOPT_CONNECTTIMEOUT, self::CONNECT_TIMEOUT); // Close connection if server doesn't response after CONNECT_TIMEOUT
curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true); // To return output in `curl_exec`
}
/** @throws \Exception */
public function requestEntity($id)
{
$url = $this->url . $id;
curl_setopt($this->ch, CURLOPT_URL, $url);
$data = curl_exec($this->ch);
if (curl_error($this->ch)) {
throw new \Exception('cURL error (' . curl_errno($this->ch) . '): ' . curl_error($this->ch));
}
return $data;
}
public function __destruct()
{
curl_close($this->ch);
}
}
此外,如果您没有限制只能与服务器建立一个连接,则可以使用curl_multi_*
函数。