최근 코드를 제출한 후 다른 사람의 환경에서 Firephp에 또 다른 문제가 있는 것을 발견했습니다. '헤더가 이미 전송되었습니다...'라는 메시지가 지난번 Nginx 버퍼를 초과했을 때와 달랐습니다. Nginx 오류 로그를 확인해 보니 오류는 발견되지 않았으며 일부 학생들은 Apache가 PHP 문제라고 의심하면서 동일한 작업을 수행하는 것을 발견했습니다. 하지만 저는 Apache도 사용하고 있는데 문제 없습니다! 우연히 오류 메시지를 표시하지 않는 페이지가 있다는 것을 발견했습니다. 이 페이지의 출력 콘텐츠 크기가 약 1KB인 것을 발견했습니다. PHP의 출력 버퍼가 초과되면 자동으로 버퍼 데이터를 전송하여 후속 Firephp가 실패하게 되는 것으로 의심됩니다. Http 헤더를 통해 디버깅 정보를 보내고 PHP 스크립트 실행을 종료합니다.
템플릿 렌더링 후 출력문을 주석 처리하면 더 이상 오류가 표시되지 않습니다. PHP의 버퍼링된 출력에 문제가 있는 것으로 판단됩니다. 서로 다른 환경에서 php.ini를 비교해보니, 출력_버퍼링 값이 다른 것을 발견했습니다. 저는 값이 On이고, 다른 것들은 기본값이 4096입니다.
PHP 코드
Output buffering is a mechanism for controlling how much output data (excluding headers and cookies) PHP should keep internally before pushing that data to the client. If your application's output exceeds this setting, PHP will send that data in chunks of roughly the size you specify. Turning on this setting and managing its maximum buffer size can yield some interesting side-effects depending on your application and web server. You may be able to send headers and cookies after you've already sent output through print or echo. You also may see performance benefits if your server is emitting less packets due to buffered output versus PHP streaming the output as it gets it. On production servers, 4096 bytes is a good setting for performance reasons. Note: Output buffering can also be controlled via Output Buffering Control functions. Possible Values: On = Enabled and buffer is unlimited. (Use with caution) Off = Disabled Integer = Enables the buffer and sets its maximum size in bytes. Note: This directive is hardcoded to Off for the CLI SAPI Default Value: Off Development Value: 4096 Production Value: 4096 http://php.net/output-buffering output_buffering = On
위의 설명에 따르면, output_buffering이 On 또는 4096일 때 각 요청에서 echo 또는 print를 사용할 때 PHP는 그렇지 않습니다. 실제로는 즉시 출력하지만 특정 크기(예: 4KB)에 도달하거나 스크립트 실행이 종료되면 버퍼 내용을 브라우저에 출력하고 삭제합니다.
HTTP 프로토콜이 콘텐츠를 전송할 때 응답 헤더가 먼저 전송됩니다. 콘텐츠가 출력되기 시작하면 더 이상 응답 헤더를 변경할 수 없습니다. output_buffering이 On이면 PHP는 모든 출력을 캐시하고 요청이 끝날 때까지 기다린 후 콘텐츠를 브라우저에 출력합니다. 따라서 Firephp가 마지막 순간에 Http 응답 헤더를 변경하더라도 여전히 콘텐츠가 없기 때문에 문제가 없습니다. 이 때 출력합니다. output_buffering이 4096(또는 기타 고정 값)이면 PHP 버퍼가 가득 찰 때마다 클라이언트에 출력됩니다. 이때 콘텐츠는 출력되었으며 더 이상 응답 헤더를 사용할 수 없습니다. 헤더를 설정하려고 하면 '헤더가 이미 전송되었습니다' …'라는 메시지가 표시됩니다.
웹서버의 버퍼 출력을 제어하면 Facebook이나 Sina의 Bigpipe와 같이 더 나은 사용자 경험을 제공할 수 있습니다.
이번에는 대부분의 페이지에 디버깅 정보가 많기 때문에 Http 응답 헤더가 크다는 것을 발견했습니다(4KB보다 훨씬 크고 일부는 36KB에 도달함). 출력 메커니즘. 해결 방법: 출력_버퍼링을 On으로 변경하고, 코드에서 ob_start()를 수동으로 변경하고, 로그 디버깅 정보를 줄이세요.