
Ubuntu 20 LTS에 serverpilot이 설치된 nginx 스택을 사용하여 WordPress 사이트를 실행하는 서버가 있습니다.
매우 큰 업로드가 nginx 프록시와 PHP 사이의 핸드오프에서 막히는 것 같습니다. 그리고 무슨 일이 일어나는지 확인하기 위해 그냥 찌르지 않고 문제를 해결하는 방법을 알고 있습니다. 앞으로 나아가는 길). 내가 알 수 있는 한, 필요한 시간 제한을 늘리고 모든 디스크 제한을 늘렸지만 분명히 뭔가 빠진 것이 있습니다.
사용 사례의 경우 최대 50GB의 업로드를 허용해야 하며 이는 표준 LAMP 스택을 실행하는 스테이징 환경에서 문제 없이 작동합니다. 2GB 미만의 파일에는 문제가 없지만 그 이상의 파일은 제가 추적할 수 없는 일부 기준에 따라 실패할 수도 있고 그렇지 않을 수도 있습니다. 이전에 문제를 해결하는 동안 파일 복사가 중지되는 시간은 임의적인 것처럼 보였지만(성공 최대 10GB) 현재 구성(아래 참조)에서는 PHP tmp
파일이 2GB에 도달하면 지속적으로 중지됩니다.
/mnt/tmp/[nginx_tmp_path]
매우 큰 파일을 업로드할 때 전체 파일이 존재할 때까지 (예, 사용 가능한 디스크 공간이 충분할 때까지) 들어오는 임시 파일이 디스크 공간을 소비하는 것을 볼 수 있습니다 . 그 후 파일이 php tmp
경로에 복사되는 것을 볼 수 있지만 몇 초 후에 php tmp
파일의 크기 증가가 멈추고 복사 프로세스가 중단됩니다. 결국 600초 제한 시간 중 하나에 도달하고 오류가 기록됩니다(아래 참조). 이 스크린샷에는 약 2GB의 TMP 파일 전송에 걸린 완료된(브라우저/최종 사용자 관점에서) 14.8GB 업로드가 있습니다.
600초 기간이 끝나면 Apache 오류 로그에 다음이 표시됩니다.
(70008)Partial results are valid but processing is incomplete: [client <MY_IP>] AH01075: Error dispatching request to : (reading input brigade), referer: https://<THE_URL>/wp-admin/media-new.php
그리고 nginx 오류 로그에는 다음과 같이 나와 있습니다.
2512066#0: *9 upstream timed out (110: Connection timed out) while sending request to upstream, client: <MY_IP>, server: <INTERNAL_IP>, request: "POST /wp-admin/async-upload.php HTTP/2.0", upstream: "http://127.0.0.1:81/wp-admin/async-upload.php", host: "<THE_URL>", referrer: "https://<THE_URL>/wp-admin/media-new.php"
이러한 메시지는 업로드가 처음 서버에 완전히 도착한 후 10분(파일 복사가 일시 중지/중단된 것으로 나타난 후 9분 이상)이 될 때까지 로그 파일에 나타나지 않는다는 점에 유의하는 것이 중요합니다. 나는 무엇인가 때문에 파일 복사가 중단되고 결국 시간 초과에 도달했다고 확신합니다. 문제가 시간 초과 자체에 있다고는 생각하지 않습니다. 파일 복사가 중지되고 로그 파일에 시간 초과 오류가 나타나는 사이에는 서버에서 증가하거나 비정상적인 활동이 없으며 모든 서비스가 예상대로 작동하고 응답합니다.
현재 구성에서는 PHP tmp
파일이 항상 2097152KB(에 따르면 du -a
)로 커지므로 아직 발견하지 못한 내장 파일 크기 제한에 도달했다고 믿게 됩니다.
관련 nginx 서버 구성 옵션은 다음과 같습니다 server
.
proxy_connect_timeout 600;
proxy_read_timeout 600;
proxy_send_timeout 600;
proxy_max_temp_file_size 51200m;
fastcgi_connect_timeout 600;
fastcgi_read_timeout 600;
fastcgi_send_timeout 600;
fastcgi_request_buffering off;
keepalive_timeout 600;
send_timeout 600;
client_max_body_size 0;
client_body_temp_path /mnt/tmp;
client_body_in_file_only clean;
Apache의 VirtualHost 구성:
RequestReadTimeout header=0 body=0
Timeout 3600
ProxyTimeout 3600
마지막으로 PHP 구성은 다음과 같습니다.
memory_limit = -1
max_execution_time = 0
max_input_time = -1
post_max_size = 50G
upload_max_filesize = 50G
default_socket_timeout = -1
내가 보고 있는 증상의 원인이 무엇인지 알 수 없습니다. 어떤 조언이라도 감사하겠습니다!
추가 참고 사항: 증상으로 인해 관련이 없는 것 같은 느낌이 들지만 혹시라도 그럴 경우에는... 사이트는 WP Rocket을 통해 실행되지만 CloudFlare와 같은 외부 프록시 서비스는 없습니다.
업데이트: nginx 구성에 다음 줄을 추가했습니다.
proxy_http_version 1.1;
proxy_set_header Connection "";
이로 인해 증상이 약간 변경되었지만 문제가 해결되지는 않았습니다. 이 변경으로 인해 동작은 이전에 설명한 대로 되돌아가고 파일 전송은 예측할 수 없는 지점에서 중단됩니다. 아래의 첫 번째 예는 3823176KB에서 중지되었고 두 번째 예는 3264364KB에서 중지되었습니다. 행동의 차이에 대한 이유는 나에게는 이해가 되지 않지만 보고할 가치가 있습니다.
업데이트 2: 나는 이것을 nginx와 php 사이의 파일 핸드오프에서 발생하는 문제라고 확신할 수 있었지만 tmp
, 프로세스를 중단시키는 구체적인 원인을 찾아낼 수는 없는 것 같습니다.
tmp
nginx 구성에 다음 줄을 추가하여 nginx 프록시를 건너뛰고 PHP만 사용할 수 있습니다 .
proxy_buffering off;
proxy_request_buffering off;
이 구성을 사용하면 파일이 직접 들어가고 /mnt/tmp/php<RND_STR>
업로드가 완료되면 애플리케이션이 파일을 적절하게 선택하여 tmp
작업을 완료합니다.
그러나 이렇게 하면 업로드 속도가 사용 가능한 대역폭의 약 1/3로 느려지므로 좋은 해결 방법이 아닙니다. 그러나 이것이 응용 프로그램 문제가 아니라는 것이 입증되었습니다.
그래서 이것이 무슨 일이 일어나고 있는지입니다:
- 사용자가 대용량 파일을 업로드합니다(사용 사례의 최대값은 50GB입니다).
- 파일
tmp
전체가 nginx 위치 에 도착합니다. tmp
nginx에서 PHP로 파일을 복사하려고 시도합니다tmp
. 복사 프로세스는 예측할 수 없는 위치(3GB에서 10GB 사이)에서 몇 초 내에 중단됩니다. [3b] 이때 두tmp
파일 모두를 볼 수 있으며 PHPtmp
파일에는 nginx 파일의 크기와 같아질 때까지 증가해야 하는 바이트 수가 포함되어 있지만tmp
그렇지 않습니다. 두 파일 모두 600초 제한 시간 중 하나에 도달할 때까지(위 참조) 완전히 그대로 유지됩니다. 그런 다음 로그 파일에 오류가 나타나고 두tmp
파일이 모두 사라집니다. [3c] 파일이 3GB 미만이면 매번 작동합니다. 파일이 3GB를 초과하는 경우 때로는 작동하지만 다른 경우에는 작동하지 않습니다. 파일이 작을수록 작동할 가능성이 더 높습니다.- 업로드 속도가 느리다는 점을 제외하면 nginx를 우회하는
tmp
것은 예상대로 완전히 작동합니다.
파일이 불쾌할 정도로 클 때 nginx와 PHP 사이의 파일 핸드오프 중에 뭔가 확실히 중단되고 있으며 tmp
, 그것이 무엇인지 알고 싶습니다.