web-dev-qa-db-ja.com

PHPでcURLを高速化する方法は?

Twitterからツイートを埋め込もうとしています。だから、私はjsonを取り戻すためにcURLを使用しています。ちょっとしたテストを書きましたが、ローカルで実行した場合と同様に、テストには約5秒かかります。だから、私はここで何が間違っているのかわかりません。

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;
}

リンクを貼り付けてブラウザからテストすると、非常に高速です。

12
toy

環境に関しては、PHPで、CPUが少なく、ネットワークパフォーマンスが遅い場所を除いて、ほとんどの環境でcURLが通常非常に高速に実行されることを確認しました。たとえば、ローカルホストで私のMAMPインストールでは、curlは高速で、大規模なAmazonインスタンスでは、curlは高速です。しかし、小さな安っぽいホスティングでは、接続が著しく遅くなるパフォーマンスの問題があることがわかりました。ただし、正確にはわかりません。 なぜそれは遅いです。また、それは確かに5秒遅くはありませんでした。

そのPHPまたはご使用の環境かどうかを判断するには、コマンドラインからcurlを操作してみてください。少なくとも、PHP =まだ5秒の場合、コードが問題になります。

5
Kristian

今までで最高のスピードアップは、同じカールハンドルを再利用することでした。 $ch = curl_init( $json_url );curl_setopt($ch, CURLOPT_URL, $url);に置き換えます。次に、関数の外側に1つの$ch = curl_init();があります。アクセスするには、関数で$chをグローバルにする必要があります。

カールハンドルを再利用すると、サーバーへの接続が開いたままになります。これは、サーバーがリクエスト間で同じである場合にのみ機能します。

18

スピードアップのための最終的な解決策はこれです

curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 );

よろしく

13
CoverUp

curl_setopt($ch, CURLOPT_ENCODING, '')を設定してみてください。gzip圧縮が有効になります。

7
ncs

CURLを高速化するには、API用の特別なクラス(例:ApiClient)を作成し、1つの共有cURLハンドラーを使用して、リクエストごとにURLのみを変更することをお勧めします。また、名前解決のリクエストを遮断し、gzip圧縮された応答を使用します。

1つのAPIサーバーから毎日約100万のエンティティを処理する必要があり、1つの同時接続のみを使用するように制限されていました。そのクラスを作成しました。他の人がカールリクエストを最適化するのに役立つことを願っています。

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);
    }
}

また、サーバーとの接続が1つだけであるという制限がない場合は、curl_multi_*関数を使用できます。

3

Ipv-4のみを使用してみてください。デフォルトでは、curlはipv-6とその低速を使用します。 curlコマンドに--ipv4パラメーターを追加すると、コストが8秒から4秒に低下します

0
mustafa candan

試してみてください

CURLOPT_TCP_FASTOPEN => 1

... TCP-Fast-Openをアクティブにします。

CURL 7.49.0に追加され、PHP 7.0.7に追加されました。

0
Frank