2018. 9. 21. 00:03ㆍ서버 프로그래밍
AWS S3와 같은 분산 병렬 처리를 위한 파일 시스템에는 기본적으로 append와 같은 파일 수정 기능이 없다. 따라서, 실시간으로 수신되는 작은 크기의 데이터를 일정 크기로 버퍼링 하면서 업로드할 수 있는 방법이 필요하다. 구글링 하다보면 자주 걸리는 블로그에서 "멀티파트 업로딩"이라는 힌트를 얻었다.
S3에는 파일을 업로드 할때, multipart uploading이라는 기능을 제공한다. 파일을 하나의 Connection에서 쭈욱 올리는 것이 일반적인 방법이라면 파일을 여러개의 블럭으로 나눠서 동시에 여러개의 Connection을 통해서 업로드 하는 방법이다. 이 경우 업로드가 Parallel하게 이루어지기 때문에 상당 부분의 성능 향상을 가지고 올 수 있다.
친절하게 Python의 boto3를 이용하여 멀티파트 업로딩을 구현한 예제가 있다. resource가 아니라 client 객체를 이용하는 것에 주의.
https://gist.github.com/teasherm/bb73f21ed2f3b46bc1c2ca48ec2c1cf5
* 주의할 사항은, 멀티파트 업로드의 경우 각 파트가 최소 5MB 이상이 되어야 하는 제약이 있다. 맨마지막 파트는 5MB 이하라도 상관없다.
https://docs.aws.amazon.com/ko_kr/AmazonS3/latest/dev/qfacts.html
Amazon S3 멀티파트 업로드 제한
다음 표에 멀티파트 업로드의 주요 사양이 나와 있습니다. 자세한 내용은 멀티파트 업로드 개요 단원을 참조하십시오.
항목 | 사양 |
---|---|
최대 객체 크기 | 5TB |
업로드당 최대 부분 개수 | 10,000개 |
부분 번호 | 1 ~ 10,000(포함) |
부분 크기 | 5MB ~ 5GB(마지막 부분은 < 5MB도 가능) |
파트 목록 조회 요청에 대해 반환되는 최대 부분 개수 | 1000 |
멀티파트 업로드 나열 요청에서 반환되는 최대 멀티파트 업로드 개수 | 1000 |
AWS 공식 레퍼런스는 엄청나게 방대하지만 딱히 눈에 들어오도록 만들어져 있지 않아서 그저 참고용일 뿐.
https://aws.amazon.com/ko/premiumsupport/knowledge-center/s3-multipart-upload-cli/
https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/s3-multipart-upload.html
https://docs.aws.amazon.com/ko_kr/AmazonS3/latest/dev/LLlistMPuploadsJava.html
S3에 큰 블록을 저장하는 것은 아무래도 시간이 걸리기 때문에 쓰레드로 구현해야 한다. Python 쓰레드는 다음을 참고했다.
http://www.tutorialspoint.com/python/python_multithreading.htm
#!/usr/bin/python import threading import time exitFlag = 0 class myThread (threading.Thread): def __init__(self, threadID, name, counter): threading.Thread.__init__(self) self.threadID = threadID self.name = name self.counter = counter def run(self): print "Starting " + self.name print_time(self.name, 5, self.counter) print "Exiting " + self.name def print_time(threadName, counter, delay): while counter: if exitFlag: threadName.exit() time.sleep(delay) print "%s: %s" % (threadName, time.ctime(time.time())) counter -= 1 # Create new threads thread1 = myThread(1, "Thread-1", 1) thread2 = myThread(2, "Thread-2", 2) # Start new Threads thread1.start() thread2.start() print "Exiting Main Thread"