11
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

GuzzleでTimeoutを1秒未満に設定する

Last updated at Posted at 2017-02-09

Guzzleでタイムアウトを1秒未満に設定したい時に必要となる記述を残しておきます。

前提条件

  • Guzzle 6系
  • PHP 5.6系

解決方法

curlのオプション CURLOPT_NOSIGNALtrue にします。

use GuzzleHttp\Client;

$request_params = ['hoge' => 'foo'];
$guzzle_client = new Client(['base_uri' => 'http://example.com/']);
$http_response = $guzzle_client->request(
    'POST',
    '/api',
    [
        'timeout' => 0.1,  // 100msec
        'curl'    => [CURLOPT_NOSIGNAL => true],   // これが要!
        'json'    => $request_params
    ]
);
var_dump($http_response->getBody());

背景説明

内部的には、Guzzle→PHP→libcurlという流れで実行されています。libcurlは(少なくとも)Linux環境において、ディストリビューションが提供する標準のものを利用すると、タイムアウトはカーネルが提供するシグナル SIGALRM を使います。

しかし、 SIGALRM は秒単位でしか設定できないことが、今回の問題のポイントです。ですので、1秒未満になると切り捨てられてまともに動きません。

そこで、libcurlにてシグナルを使わないよう設定をした上で、タイムアウトを設定すると、シグナルに頼らずタイムアウトを観測できるようになり、問題が解決します。

なお、Guzzleのタイムアウトの設定は CURLOPT_TIMEOUT ではなく CURLOPT_TIMEOUT_MS を使っていて、Guzzleとしては1秒未満の値を定義することはできます。ここ、私が勘違いしていたところでした。

謝辞

@do-aki@github さんに助言いただきました。どうもありがとうございました!

参考文献

11
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?