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

Breve discussione delle soluzioni per la gestione dei timeout di accesso backend e API in PHP

[Accesso HTTP]

Di solito ci sono molti modi per accedere all'HTTP, tra cui principalmente: curl, socket, file_get_contents() e altri metodi.

Se il server remoto non risponde per un periodo prolungato, ci ritroviamo in una situazione tragica, è facile mandare in tilt tutto il server, quindi anche durante l'accesso HTTP è necessario considerare il problema del timeout.

[Accesso HTTP con CURL]

CURL è una libreria che usiamo spesso per accedere a interfacce HTTP protocol, affidabile, con prestazioni elevate e alcune funzionalità di supporto per la concorrenza.

CURL:

curl_setopt($ch, opt) può impostare alcune impostazioni di timeout, tra cui principali:

(Importante) CURLOPT_TIMEOUT imposta il numero massimo di secondi che cURL è permesso di eseguire.

(Importante) CURLOPT_TIMEOUT_MS imposta il numero massimo di millisecondi che cURL è permesso di eseguire. (Aggiunto in cURL 7.16.2. Disponibile da PHP 5.2.3.)

CURLOPT_CONNECTTIMEOUT è il tempo di attesa prima di stabilire una connessione, se impostato a 0, aspetterà indefinitely.

CURLOPT_CONNECTTIMEOUT_MS è il tempo di attesa per la connessione, espresso in millisecondi. Se impostato a 0, si aspetta in perpetuo. Aggiunto in cURL 7.16.2. Disponibile da PHP 5.2.3 in poi.

CURLOPT_DNS_CACHE_TIMEOUT imposta il tempo di conservazione delle informazioni DNS in memoria, con valore predefinito di 120 secondi.

Timeout secondario in cURL:

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL,$url);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

curl_setopt($ch, CURLOPT_TIMEOUT, 60); // È sufficiente impostare un numero di secondi

curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

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

Utilizzo del timeout secondario in cURL:

curl_setopt($ch, CURLOPT_TIMEOUT, 60);

Se cURL deve avere un timeout in millisecondi, è necessario aggiungere:

curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);

O anche:

curl_setopt ($ch, CURLOPT_NOSIGNAL, true); supporta la configurazione del timeout in millisecondi

Esempio di timeout in millisecondi per 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);  
// Attenzione, è necessario impostare questo per il timeout in millisecondi
    curl_setopt($ch, CURLOPT_TIMEOUT_MS, 200); 
// Timeout in millisecondi, aggiunto in cURL 7.16.2. Disponibile da PHP 5.2.3 in poi
    $data = curl_exec($ch);
    $curl_errno = curl_errno($ch);
    $curl_error = curl_error($ch);
    curl_close($ch);
    if ($curl_errno > 0) {
        echo "Errore cURL ($curl_errno): $curl_error\n";
    }
        echo "Dati ricevuti: $data\n";
    }
}
//Server
    sleep(10);
    echo "Fatto.";
}
?>

Altri suggerimenti:

1. Secondo la nostra esperienza, per la versione di cURL >= libcurl/7.21.0, il timeout in millisecondi è sicuramente efficace, ricordatelo.

2. Il timeout in millisecondi di curl_multi ha problemi anche... Il singolo accesso supporta il timeout in millisecondi, ma curl_multi non è accurato quando si chiamano in parallelo

[Accesso al HTTP tramite gestione del flusso]

Oltre a cURL, usiamo spesso fsockopen o funzioni di operazioni su file per la gestione del protocollo HTTP, quindi la gestione del timeout in questa area è necessaria.

In generale, il timeout di connessione può essere impostato direttamente, ma il timeout di lettura del flusso deve essere gestito separatamente.

Scrivere il proprio codice di gestione:

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

Ora, utilizzare le funzioni di gestione del flusso integrate stream_set_timeout() e stream_get_meta_data():

<?php 
//Timeout in secondi 
$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);  
//Importante, impostare il modello non bloccante
    stream_set_timeout($fp,$timeout);  
//Impostare il 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!"; 
    } 
        echo $data; 
    } 
}

Timeout di file_get_contents:

<?php
$timeout = array(
  'http' => array(
    'timeout' => 5 
//Impostare un tempo di scadenza, unità in secondi
  )
);
$ctx = stream_context_create($timeout);
$text = file_get_contents("http://example.com/", 0, $ctx);
?>

Timeout di fopen:

<?php
$timeout = array(
  'http' => array(
    'timeout' => 5 
//Impostare un tempo di scadenza, unità in secondi
  )
);
$ctx = stream_context_create($timeout);
if ($fp = fopen("http://example.com/", "r", false, $ctx)) {
 while( $c = fread($fp, 8192)) {
  echo $c;
 }
 fclose($fp);
}
?>

Questo è tutto il contenuto dell'approfondimento che ho portato per voi su come risolvere il problema del timeout dell'accesso al backend e alle API in PHP, spero che riceviate molto supporto e apprezzamento per il tutorial di gesticolazione~

Ti potrebbe interessare