English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

A Brief Analysis of the Solution to Backend and Interface Access Timeout in PHP

[HTTP Access]

There are many ways to access HTTP, mainly including: curl, socket, file_get_contents(), and other methods.

If the server on the other end does not respond for a long time, we are in trouble, as it is easy to kill the entire server, so we also need to consider the timeout issue when accessing HTTP.

[CURL Access HTTP]

CURL is a reliable library commonly used for accessing HTTP protocol interfaces, with high performance and some concurrency support features.

CURL:

curl_setopt($ch, opt) can set some timeout settings, mainly including:

*(Important) CURLOPT_TIMEOUT sets the longest second allowed by cURL.

*(Important) CURLOPT_TIMEOUT_MS sets the longest millisecond allowed by cURL. (In cURL 7.16.2was added. From PHP 5.2.3available starting. )

CURLOPT_CONNECTTIMEOUT is the time to wait before initiating a connection. If set to 0, it will wait indefinitely.

CURLOPT_CONNECTTIMEOUT_MS is the time to wait for a connection attempt, in milliseconds. If set to 0, it will wait indefinitely. In cURL 7.16.2was added. From PHP 5.2.3available starting.

CURLOPT_DNS_CACHE_TIMEOUT sets the time to save DNS information in memory, the default is120 seconds.

curl regular second-level timeout:

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $url);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

curl_setopt($ch, CURLOPT_TIMEOUT, 60);   //You only need to set a number of seconds

curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

curl_setopt($ch, CURLOPT_USERAGENT, $defined_vars['HTTP_USER_AGENT']);

curl uses the following for the regular second-level timeout:

curl_setopt($ch, CURLOPT_TIMEOUT, 60);

If curl needs to perform a millisecond timeout, you need to add:

curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);

Or:

curl_setopt($ch, CURLOPT_NOSIGNAL, true); supports millisecond timeout settings

Example of a millisecond timeout for curl:

<?php
if (!isset($_GET['foo'])) {
// Client
    $ch = curl_init('http://example.com/');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_NOSIGNAL, 1);  
//Note that the millisecond timeout must be set
    curl_setopt($ch, CURLOPT_TIMEOUT_MS, 200); 
//Timeout in milliseconds, cURL 7.16.2was added. From PHP 5.2.3Can be used
    $data = curl_exec($ch);
    $curl_errno = curl_errno($ch);
    $curl_error = curl_error($ch);
    curl_close($ch);
    if ($curl_errno > 0) {
        echo "cURL Error ($curl_errno): $curl_error\n";
    } else {
        echo "Data received: $data\n";
    }
} else {
// Server
    sleep(10);
    echo "Done.";
}
?>

Other some tips:

1. According to experience, it is: cURL version >= libcurl/7.21.0 version, millisecond-level timeouts are definitely effective, please note.

2. curl_multi's millisecond-level timeout also has issues... While single access supports ms-level timeouts, curl_multi parallel calls are inaccurate

[Stream processing method to access HTTP]

In addition to curl, we often use fsockopen or file operation functions for HTTP protocol processing, so timeout handling in this area is also necessary.

Generally, connection timeout can be set directly, but stream read timeout requires separate handling.

Handle it yourself:

$tmCurrent = gettimeofday();
$intUSGone = ($tmCurrent['sec' - $tmStart['sec']) * 1000000
+ ($tmCurrent['usec' - $tmStart['usec']);
if ($intUSGone > $this->_intReadTimeoutUS) {
return false;
}

or use built-in stream handling functions stream_set_timeout() and stream_get_meta_data() for processing:

<?php 
// Timeout in seconds 
$timeout = 5; 
$fp = fsockopen("example.com", 80, $errno, $errstr, $timeout); 
if ($fp) { 
    fwrite($fp, "GET"); / HTTP/1.0\r\n"); 
    fwrite($fp, "Host: example.com\r\n"); 
    fwrite($fp, "Connection: Close\r\n\r\n"); 
    stream_set_blocking($fp, true);  
//Important, set to non-blocking mode
    stream_set_timeout($fp,$timeout);  
//Set timeout
    $info = stream_get_meta_data($fp); 
    while ((!feof($fp)) && (!$info['timed_out'])) { 
        $data .= fgets($fp, 4096); 
        $info = stream_get_meta_data($fp); 
        ob_flush; 
        flush(); 
    } 
    if ($info['timed_out']) { 
        echo "Connection Timed Out!"; 
    } else { 
        echo $data; 
    } 
}

file_get_contents timeout:

<?php
$timeout = array(
  'http' => array(
    'timeout' => 5 
//Set a timeout time, unit in seconds
  )
);
$ctx = stream_context_create($timeout);
$text = file_get_contents("http://example.com/", 0, $ctx);
?>

fopen timeout:

<?php
$timeout = array(
  'http' => array(
    'timeout' => 5 
//Set a timeout time, unit in seconds
  )
);
$ctx = stream_context_create($timeout);
if ($fp = fopen("http://example.com/", "r", false, $ctx)) {
 while( $c = fread($fp, 8192)) {
  echo $c;
 }
 fclose($fp);
}
?>

This is the full content of the brief discussion on the solution to the timeout problem of the backend and interface access after PHP processing that the editor has brought to you. Hope everyone will support and cheer for the tutorial~

You May Also Like