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

Breve análise sobre a solução para o problema de tempo de espera excessivo ao acessar o backend e a interface em PHP

【Acesso HTTP】

Nós temos muitos métodos para acessar HTTP, principalmente: curl, socket, file_get_contents() e outros.

Se a outra parte do servidor não responder, ficamos em uma situação trágica, é fácil matar todo o servidor, então também precisamos considerar o problema de timeout ao acessar HTTP.

[Acesso HTTP via CURL]

CURL é uma biblioteca de lib que usamos frequentemente para acessar interfaces de protocolo HTTP, confiável, com alto desempenho e algumas funções de suporte a concorrência.

CURL:

curl_setopt($ch, opt) pode configurar algumas configurações de tempo limite, incluindo principalmente:

*(Importante) CURLOPT_TIMEOUT define o número máximo de segundos permitido para a execução do cURL.

*(Importante) CURLOPT_TIMEOUT_MS define o número máximo de milissegundos permitido para a execução do cURL. (No cURL 7.16.2foi adicionado. A partir do PHP 5.2.3Disponível a partir de agora. )

CURLOPT_CONNECTTIMEOUT é o tempo de espera antes de estabelecer a conexão, se definido como 0, espera infinitamente.

CURLOPT_CONNECTTIMEOUT_MS é o tempo de espera para tentar conectar, em milissegundos. Se definido como 0, espera infinitamente. No cURL 7.16.2foi adicionado. A partir do PHP 5.2.3Disponível a partir de agora.

CURLOPT_DNS_CACHE_TIMEOUT configura o tempo de armazenamento de informações de DNS na memória, o valor padrão é120 segundos.

Tempo limite normal em segundos para curl:

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL,$url);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

curl_setopt($ch, CURLOPT_TIMEOUT, 60);   //Basta configurar um número de segundos

curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

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

Uso de tempo limite normal em segundos para curl:

curl_setopt($ch, CURLOPT_TIMEOUT, 60);

Para que o curl possa usar tempo limite em milissegundos, é necessário adicionar:

curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);

ou:

curl_setopt ($ch, CURLOPT_NOSIGNAL, true); é compatível com configuração de tempo limite em milissegundos

Exemplo de tempo limite de milissegundos para 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);  
//Atenção, o tempo limite em milissegundos deve ser configurado
    curl_setopt($ch, CURLOPT_TIMEOUT_MS, 200); 
//milissegundos de timeout, cURL 7.16.2foi adicionado. A partir do PHP 5.2.3Pode usar
    $data = curl_exec($ch);
    $curl_errno = curl_errno($ch);
    $curl_error = curl_error($ch);
    curl_close($ch);
    if ($curl_errno > 0) {
        echo "Erro do cURL ($curl_errno): $curl_error\n";
    } else {
        echo "Dado recebido: $data\n";
    }
} else {
// Servidor
    sleep(10);
    echo "Concluído.";
}
?>

Outras dicas:

1. Segundo a experiência, é: cURL versão >= libcurl/7.21.0 versão, o timeout de milissegundos é definitivamente eficaz, lembre-se disso.

2. O timeout de milissegundos do curl_multi também tem problemas ... A única chamada suporta timeout de milissegundos, curl_multi não é preciso para várias chamadas paralelas

[Acesso ao HTTP por meio de tratamento de fluxo]

Além do curl, também usamos frequentemente fsockopen, ou funções de operação de arquivo para lidar com o protocolo HTTP, então, o tratamento de timeout nessa área também é necessário.

O timeout de conexão pode ser configurado diretamente, mas o timeout de leitura de fluxo precisa ser tratado separadamente.

Escreva seu código para lidar:


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

ou use as funções de manipulação de fluxo integradas stream_set_timeout() e stream_get_meta_data() para lidar com:

<?php 
// Timeout em segundos 
$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, "Conexão: Fechar\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, unit is 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, unit is 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 solving the timeout problem of the backend and interface access after PHP processing brought to you by the editor. I hope everyone will support and cheer for the tutorial ~

Você também pode gostar