Skip to content
isdnetworks
Go back

파일이 커지면 깨지는 것들

(수정됨)

포팅 중인 서비스의 영상 업로드가 작은 파일로는 잘 됐는데 큰 파일을 올리자 여러 곳에서 걸렸다. 걸리는 자리가 한 곳이 아니었다.

Table of contents

Open Table of contents

배경 — 계층마다 있던 제한

nginx 의 client_max_body_size 와 PHP 의 upload_max_filesize 와 post_max_size 가 각각 따로 있었다. nginx 공식 문서대로 본문이 그 값을 넘으면 413 이 돌아간다. PHP 매뉴얼대로 post_max_size 는 upload_max_filesize 보다 커야 한다.

memory_limit 은 파일을 통째로 읽으면 그만큼 쓴다. 연결은 업로드 도중에 max_execution_time 에 걸렸다. 오브젝트 스토리지에도 단일 PUT 으로 올릴 수 있는 크기 제한이 있었다. 다섯 곳을 다 손대야 통과하는 구조였다.

막힌 지점 — 하나씩 순서대로 나타난다

이 문제가 답답한 것은 제한이 한 번에 다 보이지 않는다는 점이다. 앞의 것을 고쳐야 다음 것이 드러난다.

그래서 브라우저에서 저장소까지 경로 전체를 그려 놓고 각 계층의 제한을 한 번에 확인했다. 하나씩 걸릴 때마다 찾으면 그 횟수만큼 배포와 재현이 반복된다.

조치 — 통째로 읽지 않는 방식

메모리 문제는 설정으로 풀리지 않아서 코드를 바꿔야 했다. file_get_contents 로 통째로 읽어 넘기던 것을 fopen 과 stream_copy_to_stream 으로 흘려보내게 했다.

memory_limit 을 늘리는 것은 임시방편이고 파일이 더 커지면 다시 걸린다. 읽는 방식을 바꾸는 것이 근본 해결이었다.

해 본 것 — 나눠 올리기와 기준

저장소의 단일 요청 제한은 스트림으로도 안 풀렸다. CreateMultipartUpload 와 UploadPart 로 여러 조각으로 나눠 올리는 방식을 썼다. 중간에 실패해도 그 조각만 다시 올리면 되므로 실패에 강해진다.

작은 파일은 단순 PUT 으로 두고 100MB 를 넘는 파일만 나눠 올리는 쪽을 골랐다. 이유는 조각 관리와 실패 처리가 붙어 복잡해지는 경로를 큰 파일에만 태우고 싶어서다. 대신 업로드 경로가 둘이 되어 시험할 조합이 늘어나는 것을 감수했다.

주의 — 미완료 조각의 정리

한동안 돌리고 저장소를 보니 미완료 업로드가 쌓여 있었다. 조각은 올라갔는데 CompleteMultipartUpload 가 안 된 것들이고 그대로 공간과 요금을 쓴다.

일정 기간이 지난 미완료 업로드를 버킷 수명 주기 규칙으로 자동으로 지우게 했다. 나눠 올리기를 도입하면 이 정리 규칙이 반드시 따라와야 하고 안 넣으면 조용히 쌓인다.

진행률은 조각 단위로 계산해 보여 줬다. 조각마다 걸리는 시간이 달라 정확하지는 않지만 멈춘 것처럼 보이지 않는 것이 목적이었다.

정리


Share this post on:

Previous Post
주인이 없는 시스템을 받았을 때
Next Post
큐 구성이 바뀌자 소비가 멈췄다