勉強したことのメモ

Webエンジニア / プログラマが勉強したことのメモ。

PHPで外部のAPIにリクエストする際に並列処理(非同期実行)する方法

  PHP

あるシステムからPHPで外部のAPIにリクエストしたかった。ただ、複数回リクエストする必要があり、curlもしくはfile_get_contentsをループで回すとページの表示速度がかなり遅くなった。curl_multi_initを用いて並列処理(非同期実行)することで改善されたので以下に対応方法をメモ。

 

対応方法

ソースコード

<?php
$url_list = array(
    'https://api.com/?code=1',
    'https://api.com/?code=2',
    'https://api.com/?code=3',
);

$result = getMultiContents($url_list);
var_dump($result);

function getMultiContents( $url_list ) {

    $mh = curl_multi_init();

    $ch_list = array();

    foreach( $url_list as $url ) {
        $ch_list[$url] = curl_init($url);
        curl_setopt($ch_list[$url], CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($ch_list[$url], CURLOPT_TIMEOUT, 1);
        curl_multi_add_handle($mh, $ch_list[$url]);
    }

    $running = null;
    do{
        curl_multi_exec($mh, $running);
    }while( $running );

    foreach( $url_list as $key => $url ) {
        $results[$key]["content"] = curl_multi_getcontent($ch_list[$url]);

        curl_multi_remove_handle($mh, $ch_list[$url]);
        curl_close($ch_list[$url]);
    }

    curl_multi_close($mh);

    return $results;
}

注意点

上記ソースコードというよりもAPI側の問題になるかとは思うが、APIリクエストのレートリミットに注意すること。

速度について

郵便番号のAPIに1ページで3回分リクエストを試したところ、実行速度は並列処理の場合は約0.3秒、普通にループを回した場合は約1秒という結果になった。

また、5回ずつ試したが並列処理の場合は0.27~0.3秒と実行速度の幅が少なく安定していたが、ループの場合は0.8~1.4秒と幅がやや多めと不安定だった。

双方のサーバの回線の太さや混み合い具合によって変わってくるんだろうけどレートリミットの問題が解決できるのであれば並列処理する方が良さそう。

 

リファレンス

curl_multi_init

https://www.php.net/manual/ja/function.curl-multi-init.php

 

参考サイト

https://techblog.yahoo.co.jp/architecture/api1_curl_multi/

 - PHP

  関連記事

MySQLでJOINの高速化
MySQLでJOINの高速化

JOINで無茶苦茶悩んだのでメモ。やりたかった事は、MySQLで テーブルAには ...

PHPでis_fileとfile_existsについて
PHPでis_fileとfile_existsについて

ファイルの存在チェックを行う際に、file_exists関数を 使用していたが、 ...

WordPressでメモリを節約しつつ高速化する設定方法
WordPressでメモリを節約しつつ高速化する設定方法

メモリ1GのVPSを借りてWordpress以外にも、ちょいちょいものを置いてい ...

gzip圧縮とキャッシュをhttpd.confで設定する方法
gzip圧縮とキャッシュをhttpd.confで設定する方法

今まで共用サーバーで使っていたWordPressをVPSに移した。せっかくなので ...

MySQLで日時や日付で範囲検索する際に動作速度を向上させる方法
MySQLで日時や日付で範囲検索する際に動作速度を向上させる方法

MySQLでログ系等の大量にデータが格納されているテーブルから日時や日付で範囲検 ...