source

풀 URL 사용 시 PHP file_get_contents가 매우 느리다

gigabyte 2022. 11. 19. 11:39
반응형

풀 URL 사용 시 PHP file_get_contents가 매우 느리다

HTML 페이지에서 PDF 파일을 생성하는 스크립트(원래 작성하지 않은 스크립트)를 사용하고 있습니다.문제는 처리 시간이 1-2분 정도로 매우 오래 걸린다는 것입니다.처음에는 잘 작동했지만 지난 몇 주 동안 속도가 느려졌습니다.

스크립트가 호출합니다.file_get_contentsphp 스크립트에서 결과를 서버의 HTML 파일로 출력하고 해당 파일에서 pdf generator 앱을 실행합니다.

나는 문제를 좁힌 것 같다.file_get_contents로컬 패스가 아닌 풀 URL로 콜합니다.

사용할 때

$content = file_get_contents('test.txt');

거의 순식간에 처리됩니다.그러나 전체 URL을 사용하는 경우

$content = file_get_contents('http://example.com/test.txt');

처리에 걸리는 시간은 30~90초입니다.

서버에만 국한된 것이 아니라 http://www.google.com 등의 외부 URL에 접속할 때 속도가 느립니다.로컬에서 파일을 호출하면 작동하지 않는 쿼리 문자열 변수가 있기 때문에 스크립트가 풀 URL을 호출한다고 생각합니다.

나도 노력했어fopen,readfile,그리고.curl모두 마찬가지로 느렸습니다.이 문제를 해결할 방법이 없을까요?

주의: 이것은 PHP 5.6.14에서 수정되었습니다.aConnection: closeHTTP/1.0 요구에서도 헤더는 자동적으로 송신됩니다.「commit」를 참조해 주세요.

file_get_contents 스크립트가 느린 원인을 파악하는데 어려움을 겪었습니다.

Wireshark를 사용하여 분석한 결과 리모트 웹 서버가 TCP 접속을 15초까지 닫지 않는 문제(즉, "킵얼라이브")가 있었습니다.

실제로 file_get_contents는 "connection" HTTP 헤더를 전송하지 않으므로 원격 웹 서버는 기본적으로 이것이 keep-alive 연결이라고 간주하고 15초까지 TCP 스트림을 닫지 않습니다(표준값이 아닐 수 있습니다.서버의 conf에 따라 다릅니다).

일반 브라우저에서는 HTTP 페이로드 길이가 응답 Content-Length HTTP 헤더로 지정된 길이에 도달하면 페이지가 완전히 로드된 것으로 간주됩니다.file_get_contents는 이 기능을 하지 않기 때문에 유감입니다.

솔루션

솔루션을 알고 싶으시면 다음과 같이 하십시오.

$context = stream_context_create(array('http' => array('header'=>'Connection: close\r\n')));
file_get_contents("http://www.something.com/somepage.html",false,$context);

다운로드가 완료되면 접속을 닫도록 리모트서버에 지시하는 것 뿐입니다.file_get_contents는 응답 Content-Length HTTP 헤더를 사용하여 직접 접속할 수 있을 만큼 인텔리전트하지 않기 때문입니다.

외부 콘텐츠를 가져오려면 curl()을 사용합니다.이거는 Curl()보다 훨씬 빠르기 때문입니다.file_get_contents 해결될지는 .이것으로 문제가 해결될지는 모르겠지만 시도해 볼 만합니다.

또, 서버의 속도는, 파일 취득에 걸리는 시간에 영향을 주는 것에 주의해 주세요.

다음은 사용 예를 제시하겠습니다.

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://example.com/test.txt');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
curl_close($ch);

서버의 DNS가 너무 느리기 때문에 다음과 같이 시도해 보십시오.

교체하다

echo file_get_contents('http://www.google.com');

~하듯이

$context=stream_context_create(array('http' => array('header'=>"Host: www.google.com\r\n")));
echo file_get_contents('http://74.125.71.103', false, $context);

나도 같은 문제가 있었어

은, 「타임 을 「타임 아웃」으로 입니다.$optionsmanager.manager로 하다

$options = array(
    'http' => array(
        'header'  => implode($headers, "\r\n"),
        'method'  => 'POST',
        'content' => '',
        'timeout' => .5
    ),
);
$context = stream_context_create(array('http' => array('header'=>'Connection: close\r\n')));
$string = file_get_contents("http://localhost/testcall/request.php",false,$context);

시간: 50976 ms (총 5회 시도 소요 시간)

$ch = curl_init();
$timeout = 5;
curl_setopt($ch, CURLOPT_URL, "http://localhost/testcall/request.php");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
echo $data = curl_exec($ch);
curl_close($ch);

시간: 46679 ms (총 5회 시도 소요 시간)

주의: 요청.php는 mysql 데이터베이스에서 데이터를 가져오는 데 사용됩니다.

명령줄에서 서버의 URL을 가져올 수 있습니까?컬이나 웨젯이 떠오릅니다.통상적인 속도로 URL을 취득하는 경우는, 네트워크상의 문제가 아니고, apache/php 셋업의 문제일 가능성이 높습니다.

API를 API를 file_get_contents60초 정도 걸렸어요그러나 KrisWebDev의 솔루션을 사용하면 약 25초가 소요되었습니다.

$context = stream_context_create(array('https' => array('header'=>'Connection: close\r\n')));
file_get_contents($url,false,$context);

Curl을 사용할 때 고려해야 할 점은 요청을 "스레드"할 수 있다는 것입니다.현재 스레드화가 가능한 PHP 버전에 액세스할 수 없기 때문에 이것은 저에게 큰 도움이 되었습니다.

예를 들어 리모트 서버에서 file_get_contents를 사용하여7개의 이미지를 가져오고 있었는데 요청당 2~5초 정도 걸렸습니다.사용자가 PDF가 생성되기를 기다리는 동안 이 프로세스만 해도 프로세스에 30초 정도의 시간이 더 걸렸습니다.

이것에 의해, 말 그대로 약 1매의 이미지로 시간이 단축되었습니다.또 다른 예에서는 36개의 URL을 1개 실행하는 데 소요된 시간에 검증합니다.무슨 말인지 알 것 같아. :-)

    $timeout = 30;
    $retTxfr = 1;
    $user = '';
    $pass = '';

    $master = curl_multi_init();
    $node_count = count($curlList);
    $keys = array("url");

    for ($i = 0; $i < $node_count; $i++) {
        foreach ($keys as $key) {
            if (empty($curlList[$i][$key])) continue;
            $ch[$i][$key] = curl_init($curlList[$i][$key]);
            curl_setopt($ch[$i][$key], CURLOPT_TIMEOUT, $timeout); // -- timeout after X seconds
            curl_setopt($ch[$i][$key], CURLOPT_RETURNTRANSFER, $retTxfr);
            curl_setopt($ch[$i][$key], CURLOPT_HTTPAUTH, CURLAUTH_ANY);
            curl_setopt($ch[$i][$key], CURLOPT_USERPWD, "{$user}:{$pass}");
            curl_setopt($ch[$i][$key], CURLOPT_RETURNTRANSFER, true);
            curl_multi_add_handle($master, $ch[$i][$key]);
        }
    }

    // -- get all requests at once, finish when done or timeout met --
    do {  curl_multi_exec($master, $running);  }
    while ($running > 0);

그런 다음 결과를 확인합니다.

            if ((int)curl_getinfo($ch[$i][$key], CURLINFO_HTTP_CODE) > 399 || empty($results[$i][$key])) {
                unset($results[$i][$key]);
            } else {
                $results[$i]["options"] = $curlList[$i]["options"];
            }
            curl_multi_remove_handle($master, $ch[$i][$key]);
            curl_close($ch[$i][$key]);

그런 다음 파일을 닫습니다.

    curl_multi_close($master);

나는 그것이 오래된 질문인 것을 알지만 나는 오늘 그것을 발견했고 답변은 나에게 효과가 없었다.IP당 최대 연결 수를 1로 설정할 수 있다고 말하는 사람은 없습니다.그러면 API 요청을 하고 API는 풀 URL을 사용하기 때문에 다른 요청을 합니다.그렇기 때문에 디스크에서 직접 로딩할 수 있습니다.문제를 해결한 나에게:

if (strpos($file->url, env('APP_URL')) === 0) {
    $url = substr($file->url, strlen(env('APP_URL')));
} else {
    $url = $file->url;
}
return file_get_contents($url);

언급URL : https://stackoverflow.com/questions/3629504/php-file-get-contents-very-slow-when-using-full-url

반응형