WebページにRSSフィードを表示させるため、
PHP内で simplexml_load_file() を使ってRSSフィードを取得していたところ、
画面の応答が遅れる現象が発生しました。
調査したところ、フィード取得先のサーバが応答を返さずタイムアウトしているログを発見。
どのくらいでタイムアウトしたか確認すると、なんと simplexml_load_file() にはタイムアウト設定がありませんでした。
php.ini の ‘default_socket_timeout’ の値 x 2 がタイムアウト秒数となるようです。
‘default_socket_timeout’ は(デフォルトのまま) 60秒なので、応答が返らなかった場合、タイムアウトまで 120秒間も 処理できない状態となっていたようです。
テスト用ファイルを用意しておく
30秒遅延させ、フィードを返すphpファイルをサーバに置いておきます。
sleep(30); // 30秒待ってから表示
echo '<?xml version='1.0' encoding='utf-8'?>
<?rss>
<?channel>
<?item>
<?link>http://example.com/mypage
<?pubDate>Mon, 27 Jun 2011 19:34:00 +0100
<?/item>
<?item>
<?/item>
<?/channel>
<?/rss>
';
simplexml_load_file()のタイムアウトを短くする
方法は3つあります。
default_socket_timeoutの値を変更
最も簡単です。
ini_set('default_socket_timeout', 5);
var_dump(simplexml_load_file('https://nijoen.net/xxx.php')); // テスト用ファイル
実際にタイムアウトする秒数は「default_socket_timeout」の2倍になります。
これ以外にもタイムアウトに影響する要素があるから、のようですが、よくわかりませんでした。
stackoverflow
実行してみると、5 x 2 = 10秒でタイムアウトしました。
simplexml_load_file(https://nijoen.net/xxx.php): failed to open stream: HTTP request failed!
stream_context_createを使用
手軽かつ真っ当な手法。
‘http’オプションは、httpsから始まるURLに対しても有効です。
$ctx = stream_context_create(['http'=>['timeout'=>5]]);
var_dump(file_get_contents('https://nijoen.net/xxx.php', false, $ctx));
curlを使用
長くなりますが、他の箇所とも統一でき、エラー処理もきちんとできます。
// curl
$ch = curl_init('https://news.yahoo.co.jp/pickup/rss.xml');
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );//データではなく文字列で返却
curl_setopt( $ch, CURLOPT_TIMEOUT, 5 );//タイムアウト(秒)
$res = curl_exec($ch);
if (! curl_errno($ch))
{
if ( curl_getinfo($ch, CURLINFO_HTTP_CODE) !== 200)
{
exit('エラー');
}
}
curl_close($ch);
var_dump($res);
まとめ
取得できたら表示する、エラー処理も必要ない!という場合には「default_socket_timeout」が簡単。
それ以外であれば「curl」で実装しておけば問題なさそうです。