Architektura uploadu opartego na chunkach: przewodnik projektowy
Zaprojektuj solidny system uploadu oparty na chunkach. Strategie dzielenia, wznawiane uploady i optymalizacja transferu równoległego.
Architektura uploadu opartego na chunkach dzieli plik na elementy o stałym lub zmiennym rozmiarze i przesyła je niezależnie, dzięki czemu chwilowy problem z siecią nie zmusza do restartu przesyłania 10 GB od zera. Dwa dominujące otwarte standardy to AWS S3 Multipart Upload (minimum 5 MB na część, maksymalnie 10 000 części) oraz wznawialny protokół tus.io (szeroko zaimplementowany). Prawidłowo zaprojektowany system uploadu w chunkach zapewnia od 5 do 10 razy wyższą przepustowość na połączeniach z dużym opóźnieniem, toleruje krótkie przerwy i umożliwia równoległe deszyfrowanie po stronie odbiorcy.
Dlaczego monolityczne uploady zawodzą przy dużej skali
Jedno żądanie HTTP PUT dla pliku 5 GB napotyka pół tuzina sposobów na niepowodzenie. Okna przeciążenia TCP długo się rozwijają, ograniczając przepustowość poniżej pojemności łącza na ścieżkach z dużym opóźnieniem. Przeglądarki ograniczają równoczesne połączenia do 6 na origin, pozostawiając większość pasma niewykorzystaną. Limity czasu żądań po stronie serwera (domyślnie 60 sekund w nginx, 30 sekund w CloudFront dla ruchu niestrumieniowanego) kończą długie uploady. Sieci mobilne przełączają się między stacjami bazowymi i co kilka minut przerywają połączenie. Uploady w chunkach rozwiązują wszystkie te problemy, czyniąc jednostkę pracy małą, niezależnie powtarzalną i przyjazną równoległości.
Wybór rozmiaru chunka
Rozmiar chunka to kompromis. Mniejsze chunki szybciej wracają do normy po awariach i dają precyzyjniejszy postęp, ale dodają więcej narzutu HTTP. Większe chunki amortyzują koszty uzgadniania i TLS, ale marnują pasmo, gdy chunk musi zostać przesłany ponownie. Typowe zakresy: 1 MB do 5 MB dla uploadów mobilnych w sieciach o dużej utracie pakietów, 5 MB do 16 MB dla uploadów z przeglądarki na komputerze, 16 MB do 64 MB dla transferów server-to-server na niezawodnych łączach, 100 MB lub więcej dla S3 Multipart, gdzie limit 10 000 części wymusza większe chunki przy 1 TB plikach. Niektóre systemy adaptują się dynamicznie, zaczynając od małych i zwiększając rozmiar wraz z potwierdzeniem niezawodności połączenia.
Chunking o stałym rozmiarze kontra chunking definiowany przez treść
Chunking o stałym rozmiarze (np. co 8 MB) jest trywialny w implementacji, przyjazny równoległości i obsługuje precyzyjne przesunięcia wznawiania. Chunking definiowany przez treść (CDC), stosowany w rsync i restic, wybiera granice na podstawie ruchomego skrótu, dzięki czemu wstawienia w środku pliku nie przesuwają wszystkich kolejnych granic chunków. CDC doskonale sprawdza się przy deduplikacji w narzędziach backupu, ale dodaje złożoność i koszt CPU bez nagrody przy czystym transferze plików. Dla architektur uploadów chunking o stałym rozmiarze wygrywa prostotą i mapuje czysto na części S3 multipart lub przesunięcia tus.io.
Protokoły wznawianych uploadów
Protokół tus.io, zaimplementowany w tusd (Go), tus-js-client, Uppy i wielu frameworkach serwerowych, używa HTTP PATCH z nagłówkiem Upload-Offset do dołączania chunków. Żądanie HEAD zwraca bieżące przesunięcie na serwerze, więc klient wie, gdzie wznowić po przerwaniu sieci. S3 Multipart Upload używa innego modelu: zainicjuj upload, by uzyskać UploadId, prześlij każdą część (indeksowaną od 1), następnie wyślij żądanie CompleteMultipartUpload z listą ETagów. Klienci mogą wysłać zapytanie ListParts, by zobaczyć, co zostało przesłane. Oba protokoły zachowują stan między restartami klienta i elegancko przeżywają przerwy połączenia.
Równoległość uploadów
Równoczesne przesyłanie chunków dramatycznie zwiększa przepustowość na połączeniach z dużym opóźnieniem. HTTP/1.1 ogranicza do 6 równoczesnych połączeń na origin w przeglądarkach; HTTP/2 multipleksuje wiele strumieni przez jedno połączenie, ale nadal podlega oknom sterowania przepływem. Typowy harmonogram uploadów kolejkuje chunki i wysyła od 4 do 8 równolegle, z ograniczaniem przepływu, gdy serwer sygnalizuje 429 lub 503. Zbyt duża równoległość wyzwala kształtowanie przepustowości przez ISP i limity połączeń middleboxów; zbyt mała pozostawia pasmo niewykorzystane. Empirycznie, 4 równoległe strumienie na łączu domowym i 8 do 16 na gigabitowym światłowodzie trafiają w optymalny punkt dla większości obciążeń.
Stan po stronie klienta i metadane wznawiania
Wznawialne uploady wymagają, by klient pamiętał wystarczająco dużo stanu, by wznowić po zawieszeniu przeglądarki lub wyłączeniu laptopa. IndexedDB, część standardu Web Storage, przechowuje manifesty uploadów z hashem pliku, liczbą chunków i informacją, które chunki się powiodły. Kluczuj manifest przez hash SHA-256 pliku, by ponowne dodanie tego samego pliku kontynuowało od miejsca, w którym skończono. Czyść nieaktualne manifesty starsze niż 7 dni, by uniknąć bałaganu.
Obsługa chunków po stronie serwera
Serwer musi składać chunki w kompletny plik lub — w przypadku S3 Multipart — delegować składanie do S3. Minimalna architektura: akceptuj każde PATCH chunka, zapisuj do tymczasowego bloba kluczowanego przez ID uploadu i indeks chunka, rejestruj przesunięcie w magazynie metadanych jak Redis lub PostgreSQL, a przy CompletePart złóż lub oznacz jako kompletny. Używaj object storage (S3, Cloudflare R2, Backblaze B2) dla blobów chunków zamiast lokalnego dysku, ponieważ load-balansowane backendy nie mogą łatwo współdzielić lokalnego stanu. Zbieraj porzucone uploady po 24 do 72 godzinach, by odzyskać storage.
Weryfikacja integralności na chunk i end-to-end
Weryfikuj każdy chunk hashem przy uploadzie. ETag S3 Multipart to hash MD5 na część. Dla silniejszej integralności oblicz SHA-256 na chunk po stronie klienta i wyślij go w nagłówku; serwer przechowuje go obok chunka i może zweryfikować przy odczycie. Po uploadzie wszystkich chunków oblicz korzeń drzewa Merkle lub strumieniowy hash złożonego pliku i zwróć go do klienta. Klient porównuje ze swoim własnym hashem oryginalnego pliku. Każda niezgodność wyzwala ponowny upload wadliwych chunków.
Interakcja szyfrowania z chunkingiem
Szyfrowanie end-to-end nieco komplikuje chunking. Każdy chunk potrzebuje własnego nonce, by uniknąć ponownego użycia IV w AES-GCM, a granice chunków muszą być częścią schematu uwierzytelniania. Typowe podejście: wyprowadź klucz per-chunk przez HKDF-SHA256 z głównego klucza szyfrowania pliku, używając indeksu chunka jako informacji kontekstowej, następnie zaszyfruj każdy chunk za pomocą AES-256-GCM z zerowym lub rosnącym nonce. Włącz indeks chunka i całkowitą liczbę chunków do AAD, by napastnicy nie mogli łączyć ani zmieniać kolejności chunków. HexaTransfer implementuje właśnie ten wzorzec dla transferów do 10 GB przez niestabilne połączenia.
Obserwowalność systemów opartych na chunkach
Instrumentuj każdy chunk. Metryki do śledzenia: chunki uploadowane na sekundę, opóźnienie uploadów p50/p95/p99, wskaźnik ponownych prób na chunk i wskaźnik porzuconych uploadów. Śledzenie rozproszone przez OpenTelemetry wiąże sesję klienta z obsługą chunków po stronie serwera. Rejestruj zdarzenia strukturalne w JSON, by były przeszukiwalne w Loki, Elasticsearch lub Splunk. Gdy klient zgłasza powolny upload, ślad pokazuje dokładnie, które chunki utknęły i dlaczego.
Wypróbuj bezpłatnie na hexatransfer.com — bez konta, maksymalnie 10 GB.
Wysyłaj duże pliki bezpiecznie z szyfrowaniem end-to-end
Przesyłaj pliki do 10 GB za darmo z szyfrowaniem end-to-end. Bez rejestracji. Twoje pliki są szyfrowane w przeglądarce przed przesłaniem — nikt inny nie może ich odczytać.
Wyślij plik