简体   繁体   English

如何加速php中的cURL?

[英]How to speed up cURL in php?

I'm trying to get embed tweet from Twitter.我正在尝试从 Twitter 嵌入推文。 So, I'm using cURL to get the json back.所以,我使用 cURL 来取回 json。 I wrote a little test but the test takes around 5 seconds as well as when I run locally.我写了一个小测试,但测试需要大约 5 秒以及我在本地运行时的情况。 So, I'm not sure what am I doing wrong here.所以,我不确定我在这里做错了什么。

public function get_tweet_embed($tw_id) {

    $json_url = "https://api.twitter.com/1/statuses/oembed.json?id={$tw_id}&align=left&omit_script=true&hide_media=false";

    $ch = curl_init( $json_url );
    $start_time = microtime(TRUE);
    $JSON = curl_exec($ch);
    $end_time = microtime(TRUE);
    echo $end_time - $start_time; //5.7961111068726

    return $this->get_html($JSON);
}

private function get_html($embed_json) {
    $JSON_Data = json_decode($embed_json,true);
    $tw_embed_code = $JSON_Data["html"];
    return $tw_embed_code;
}

When I paste the link and test it from the browser it's really fast.当我粘贴链接并从浏览器测试它时,它真的很快。

The best speed up I've ever had was reusing the same curl handle.我曾经拥有的最好的加速是重复使用相同的卷曲手柄。 Replace $ch = curl_init( $json_url );替换$ch = curl_init( $json_url ); with curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_URL, $url); . . Then outside the functions have one $ch = curl_init();然后在函数外面有一个$ch = curl_init(); . . You'll need to make $ch global in the functions to access it.您需要在函数中将$ch设为全局才能访问它。

Reusing the curl handle keeps the connection to the server open.重用 curl 句柄保持与服务器的连接打开。 This only works if the server is the same between requests, as yours are.这仅在请求之间的服务器相同时才有效,就像您的一样。

The final solution for speed up is this加速的最终解决方案是这样的

curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 );

Regards问候

尝试设置curl_setopt($ch, CURLOPT_ENCODING, '')它启用 gzip 压缩

To speed up cURL I recommend create special class for API (eg ApiClient ) and use one shared cURL handler, only change URL for every request.为了加速 cURL,我建议为 API 创建特殊类(例如ApiClient )并使用一个共享的 cURL 处理程序,只为每个请求更改 URL。 Also cut off requests for name resolving and use gzipped response.还切断名称解析请求并使用 gzip 响应。

I needed to process about 1 million entities every day from one API-server that limits us to use only one concurrent connection.我每天需要从一个限制我们只能使用一个并发连接的 API 服务器处理大约 100 万个实体。 I created that class.我创建了那个类。 I hope it will help others in optimising their curl requests.我希望它能帮助其他人优化他们的 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);
    }
}

Also if you don't have limitations to have only one connection with server you can use curl_multi_* functions.此外,如果您没有限制只能与服务器建立一个连接,您可以使用curl_multi_*函数。

With respect to environment, I've observed in PHP that cURL typically runs very fast in most environments except in places where there is low CPU and there is slower network performance.关于环境,我在 PHP 中观察到,cURL 通常在大多数环境中运行得非常快,除了在 CPU 低且网络性能较慢的地方。 For example, on localhost on my MAMP installation, curl is fast, on a larger amazon instance, curl is fast.例如,在我的 MAMP 安装的 localhost 上,curl 很快,在较大的亚马逊实例上,curl 很快。 But on a small crappy hosting, i've seen it have performance issues where it is noticeably slower to connect.但是在一个糟糕的小型主机上,我发现它存在性能问题,连接速度明显变慢。 Though, i'm not sure exactly why that is slower.虽然,我不确定为什么会变慢。 Also, it sure wasn't 5 seconds slower.此外,它肯定不会慢 5 秒。

to help determine if its PHP or your environment, you should try interacting with curl via the command line.为了帮助确定是 PHP 还是您的环境,您应该尝试通过命令行与 curl 交互。 At least that you'll be able to rule out PHP code being the problem if its still 5 seconds.至少,如果它仍然是 5 秒,您将能够排除 PHP 代码是问题。

Try试试

CURLOPT_TCP_FASTOPEN => 1

... to activate TCP-Fast-Open. ... 激活 TCP-Fast-Open。

It was added to cURL 7.49.0, added to PHP 7.0.7.它已添加到 cURL 7.49.0,添加到 PHP 7.0.7。

Try using with --ipv4 parameter.尝试使用--ipv4参数。

This will force curl to use only ipv-4 and ignore ipv-6 which is still not very compatible with some devices and slows down the process.这将强制 curl 仅使用 ipv-4 并忽略与某些设备仍然不太兼容并减慢进程的 ipv-6。 Adding --ipv4 to my curl command reduced the cost from 8 seconds to 4 seconds.--ipv4添加到我的 curl 命令将成本从 8 秒减少到 4 秒。 Which is %50 faster.这是 %50 快。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM