01Przegląd projektu
keepix.cloud jest gospodarzem mediów dla produktów, które muszą obsługiwać pliki innych osób: zdjęcia katalogowe w sklepie, zdjęcia recenzji na rynku, wideo z instrukcją w aplikacji. Wysyłasz oryginał w jednym podpisanym żądaniu, a odpowiedź już zawiera gotowe adresy — nazwany zestaw wariantów WebP dla obrazu, drabinę HLS dla wideo. Pliki są serwowane z własnej subdomeny klienta, więc czytelnik widzi ich markę i nigdy nas nie widzi.
Założenie jest takie, że media to nie funkcja, którą budujesz raz na projekt. Każdy produkt, który pozwala ludziom na przesyłanie czegokolwiek, kończy się pisaniem tego samego po raz kolejny: zmiana rozmiaru, konwersja formatu, schemat nazewnictwa, polityka pamięci podręcznej, usuwanie metadanych, ścieżka do usunięcia wszystkiego o tej osobie. Napisane po raz piąty, jest napisane źle po raz piąty — a części, które się psują (wyciekający tag GPS, SVG, który okazał się skryptem) zawodzą cicho, bez błędu i bez linii logu.
Więc zbudowaliśmy usługę wokół jednego pomysłu: adres jest deklarowany przez usługę i przechowywany przez klienta, nigdy obliczany po stronie klienta. Ta jedna decyzja eliminuje najczęstszy sposób, w jaki integracje mediów się psują — strona, która renderuje się idealnie z dziurą tam, gdzie powinna być zdjęcie produktu.
Zaprojektowaliśmy i zbudowaliśmy cały produkt: pipeline przyjmowania, model wariantów, drabinę wideo, model wielo-najemcy z własnymi domenami i kluczami podpisującymi, rozliczenia metrowe, pulpit nawigacyjny, publiczny kontrakt API i dokumentację. Poniżej znajduje się, jaki problem rozwiązuje, jak jest złożony i które decyzje inżynieryjne podjęlibyśmy w ten sam sposób ponownie.
02Kontekst i problem
Przechowywanie przesłanego zdjęcia jest łatwe. Utrzymanie ścieżki multimedialnej, która pozostaje poprawna przez lata, pod obciążeniem, w różnych produktach i plikach innych osób, nie jest. Kiedy rozłożyliśmy zadanie, pułapki szybko się ujawniły.
- Arbitralne szerokości to pułapka.Adres URL taki jak
?w=473wygląda elastycznie i w rzeczywistości jest dwoma problemami jednocześnie: pamięcią podręczną, która nigdy się nie nagrzewa, ponieważ każda strona prosi o nieco inną liczbę, oraz darmowym sposobem dla każdego, aby zająć procesor, prosząc o tysiąc szerokości z rzędu. - Obliczony adres łamie się cicho.Reguła "id → shard → path", wbudowana w kod klienta, przetrwa dokładnie do pierwszej zmiany układu po drugiej stronie. Wtedy strona nadal się renderuje, a produkt po prostu ma dziurę tam, gdzie była jego fotografia — żadnego błędu, nic w logu.
- Metadane to wyciek, którego nikt nie zauważa.Współrzędne GPS czyjegoś domu znajdujące się w EXIF zdjęcia recenzji nie generują błędu, nie łamią strony i nie docierają do monitorowania. To tylko wyciek, gdy ktoś na to spojrzy.
- SVG to nie obrazek.To jest wykonywalny znacznik. Akceptowane jako obraz i serwowane z własnej domeny klienta, skrypt wewnątrz niego działa w imieniu tej domeny.
- Usunięcie musi być udowodnione.Prośba o usunięcie zgodnie z RODO, odpowiedziana przez oznaczenie wierszy jako usunięte, podczas gdy bajty pozostają na dysku, to usunięcie, które się nie wydarzyło.
- Wideo to zestaw, a nie plik.Jedno przesłanie musi stać się odtwarzalną drabiną, ramką plakatu i zapasowym rozwiązaniem — i żadne z tego nie może się zdarzyć w ramach żądania, które zaakceptowało plik.
- Fakturowanie musi być uczciwe przy małych kwotach.Gigabajt może kosztować mniej niż cent; zaokrąglanie do pełnych centów pochłania cały metrowany rachunek i sprawia, że faktura staje się fikcją.
Był jeszcze jeden wymóg, który ukształtował cały projekt: usługa nie może w ogóle wychodzić do internetu. Gospodarz mediów, który pobiera obraz z adresu zewnętrznego w imieniu klienta, wie, kto o co prosił i przekazuje tę wiedzę do dowolnego CDN, którego użył. keepix nie zna żadnego zewnętrznego adresu, co jest cechą kodu, a nie obietnicą na stronie cenowej.
03Cele projektu
Zadanie przekształciło się w listę celów, których trzymaliśmy się na każdym etapie:
- Jedno żądanie w, zakończone adresy na wyjściu.Klient wysyła oryginał i natychmiast otrzymuje z powrotem adresy do przechowania — żadnego drugiego połączenia, żadnego czekania na zakończenie pracy dla obrazów.
- Nazwana, skończona zbiór wariantów. Trzy szerokości dla obrazów i cztery formy dla wideo, zadeklarowane dla każdego rodzaju pliku, aby pamięć podręczna była ciepła, a procesor nie był do wynajęcia.
- Własna domena klienta. Pliki serwowane z
img.theirdomain, z usługą niewidoczną w pasku adresu. - Cache, który można przechowywać na zawsze. Adres zawiera hash treści, więc wymiana pliku zmienia jego adres i dociera do czytelnika od razu.
- Bezpieczeństwo wbudowane w ścieżkę. Typ określany przez analizę, skanowanie wirusów, które odrzuca zamiast przepuszczać, ponowne kodowanie na każdym obrazie, usunięte metadane, SVG odrzucane na obu końcach.
- Możliwe do udowodnienia usunięcie. Jedno żądanie od własnego klienta
owner_ref, a odpowiedź, która podaje, ile obiektów i plików zostało przesłanych. - Wielu najemców z prawdziwą izolacją.Własne domeny, własne rodzaje i warianty, własne limity, dwa klucze do podpisywania, aby rotacja nie powodowała przestojów.
- Rozliczenia na podstawie zużycia, które możesz sprawdzić.Przechowywanie jako średnia, a nie szczyt, ruch jako bajty faktycznie dostarczone, operacje liczone jedna po drugiej — rozbite na dni w panelu.
- API, które przyznaje, co zrobiło.Każda odpowiedź mówi, co zostało zrobione, a co pominięte, a także istnieje suchy punkt końcowy do uzgadniania w celu sprawdzenia migracji w partiach.
04Co zrobiliśmy
keepix dzieli się na kilka wyraźnych części, z których każda ma jedno zadanie:
- Przyjęcie. Jeden podpisany punkt końcowy akceptuje oryginał z jego rodzajem, kluczem i listą pożądanych wariantów. Obrazy wracają gotowe w tej samej odpowiedzi; wideo trafia do kolejki, a odpowiedź to potwierdza.
- Pipeline przetwarzania. Wykrywanie typu, skanowanie wirusów, ponowne kodowanie, usuwanie metadanych, budowanie wariantów — w ustalonej kolejności, której nie można pominąć w ramach żądania.
- Dostawa. Oddzielny host bez sesji, bez JavaScript i bez
Set-Cookie, serwujący pliki bezpośrednio z dysku z rocznym niezmiennym cache'em. - API najemcy. Podpisane HMAC-SHA256, z punktami końcowymi do rozwiązywania adresów, uzgadniania w partiach, eksportowania inwentarza, usuwania obiektu i wymazywania wszystkiego, co należy do osoby.
- Panel sterowania.Foldery, przeciągnij i upuść, wyszukiwanie według tytułu, opisu i tagów — oraz wykorzystanie rozbite na dni. Działa w pełni bez JavaScript; skrypt dodaje wygodę, a nie możliwość pracy.
- Fakturowanie.Pakiety plus opłata za nadwyżkę, trzymana w setnych części centa, z zatrzymywaniem przyjęć zamiast cichego wydawania pieniędzy na darmowym planie.
- Zasoby.Warstwa rynku, na której najemcy mogą kupować i sprzedawać swoją pracę, dzieląc tę samą przestrzeń magazynową i ścieżkę dostawy.
Wszystko poniżej to bliższe spojrzenie na decyzje wewnątrz tych elementów — tych, które byłyby kosztowne do zmiany później.
05Architektura rozwiązania
Usługa to trzy przestrzenie z fizycznie oddzielnymi punktami wejścia, a to rozdzielenie jest kręgosłupem całego projektu:
- Publiczna dostawa — brak API. Serwer WWW wyszukuje plik na dysku i go serwuje. Nie znaleziono oznacza 404, a nie "generuj na bieżąco". Na tej ścieżce nie ma kodu wykonywalnego, dlatego host dostarczający może przenosić
default-src 'none'; sandboxi mieć to na myśli. - Prywatne API najemcy. Każde żądanie podpisane; podpis obejmuje metodę, ścieżkę z jej ciągiem zapytania, znacznik czasu i hash ciała. Podpisanie ścieżki bez zapytania pozostawiłoby
rodzajikluczunsigned — wymienny, i nikt by tego nie zauważył. - API administracyjne dla panelu sterowania, na własnym punkcie dostępu z własnymi poświadczeniami.
Odpowiedzi są zawsze w formacie JSON i zawsze w języku angielskim, z jedną formułą na kod odmowy — więc ta sama awaria jest odczytywana tak samo w logach każdego klienta, niezależnie od języka, w którym mówi ich produkt.
Wewnątrz, pamięć dzieli się na zimne drzewo przechowujące oryginały, które nigdy nie są udostępniane na zewnątrz, oraz drzewo wariantów, które jest udostępniane. Zachowanie oryginału to to, co umożliwia stworzenie nowego wariantu rok później bez proszenia klienta o ponowne przesłanie czegokolwiek — i to również dlatego "nie udostępniamy pliku, który wysłałeś" może być absolutną zasadą, a nie zazwyczaj.
06Życie pliku
Plik przechodzi przez ustaloną sekwencję, a kolejność jest kluczowa:
- Typ jest określany przez analizę — na podstawie treści, a nie na podstawie rozszerzenia ani tego, co mówi klient. Rozszerzenie pliku wyjściowego jest przypisane przez usługę.
- Skanowanie wirusów jest uruchamiane i może zostać odrzucone. Jeśli skaner jest niedostępny, przyjmowanie odpowiada
503zamiast przepuszczać plik. Ciche przepuszczenie pliku, gdy kontrola jest wyłączona, to kłamstwo o wykonanej pracy, a to jest rodzaj kłamstwa, które ujawnia się dopiero znacznie później. - Obraz jest ponownie kodowany. Żaden bajt pliku, który dotarł, nie jest nigdy zwracany.
- Metadane nie przetrwają ponownego kodowania. EXIF i GPS znikają z powodu sposobu, w jaki ścieżka jest zbudowana, a nie dlatego, że osoba, która przesłała, pamiętała, aby je usunąć.
- Warianty są budowane i ich adresy są zwracane w tej samej odpowiedzi.
SVG nie jest akceptowane ani serwowane — nigdy, ani w drodze do, ani w drodze z. Sprawdzenie odbywa się dwukrotnie, na zadeklarowanym typie zawartości i na pierwszych bajtach pliku, ponieważ dla SVG detektor typu często po prostu mówi "tekst". To, co jest serwowane, to WebP, JPEG, PNG, MP4, lista odtwarzania HLS i jej segmenty; wszystko inne to 415.
Przyjęcie jest idempotentne: ten sam sha256 pod tym samym kluczem nie powtarza pracy i zwraca te same adresy. Ponowne próby po zerwaniu połączenia są zatem darmowe, co ma znaczenie, gdy plik ma dwa gigabajty, a sieć to telefon.
07Nazwane warianty, nie dowolne szerokości
Obrazy mają trzy nazwane szerokości — miniatura 400, karta 1000, pełna 1400, wszystkie w formacie WebP o jakości 82 — i prosisz o wariant po nazwie. Zestaw jest skończony i zadeklarowany dla każdego rodzaju pliku. To jest decyzja, na której opiera się cały serwis, i eliminuje klasę problemów zamiast błędu.
Dwie zasady regulują, kiedy wariant może legalnie nie wystąpić, a obie istnieją, aby uniknąć kłamstwa wobec czytelnika:
- Nic nie jest rozciągane. Jeśli oryginał jest węższy niż szerokość wariantu, wariant pozostaje w rozmiarze oryginału, a odpowiedź mówi o tym szczerze — pola
wihzawierają rzeczywiste liczby. Powiększona kopia wygląda jak błąd serwisu, a tak by było. - Identyczne kopie nie są przechowywane dwukrotnie.Jeśli dwie szerokości produkują dokładnie ten sam plik, drugi adres nie jest tworzony. Dwa identyczne pliki bajtowe pod dwoma adresami to dwa pobrania tej samej rzeczy na czyjś telefon.
Co oznacza, że odpowiedź musi być odczytana, a nie zakładana: możesz poprosić o dwie wersje i otrzymać jedną, z pominiętym blokiem wyjaśniającym dlaczego. Uczyniliśmy to normalną, oczekiwaną odpowiedzią, a nie przypadkiem skrajnym, ponieważ integracja napisana w oparciu o optymistyczny kształt łamie się przy pierwszym małym obrazie, który użytkownik przesyła.
Dodanie nowej wersji później nie wymaga ponownego przesyłania czegokolwiek: jest budowane z oryginału w zimnym drzewie. To jest cały powód, dla którego oryginał jest przechowywany.
08Wideo: drabina HLS, plakat i podgląd
Jedno przesłanie wideo staje się zestawem, ponieważ to jest to, czego naprawdę potrzebuje odtwarzacz: drabina HLS z maksymalnie trzema krokami jakości (640, 1280 i 1920 px), plakat klatka zrobiona w 10% czasu trwania, cichy podgląd klipu z pierwszych sekund do podglądu i automatycznego odtwarzania w feedzie, oraz progresywny MP4 jako alternatywa dla starszych klientów.
Krok szerszy niż oryginał nie jest robiony, z tego samego powodu, dla którego rozciągnięty obraz nie jest: powiększona kopia wygląda jak błąd usługi. Plakat jest robiony w jednej dziesiątej czasu trwania, a nie na pierwszej klatce, ponieważ pierwsza klatka prawdziwego wideo bardzo często jest czarna.
Przetwarzanie wideo nie odbywa się w ramach żądania, które zaakceptowało plik — trafia do kolejki, a odpowiedź to potwierdza. Odpowiedź przyjęcia jest szczera co do tego, które części są gotowe teraz, a które są w toku, dzięki czemu klient może przechować to, co ma, i zapytać ponownie później, zamiast blokować ekran przesyłania użytkownika podczas transkodowania.
09Własna domena i wieczna pamięć podręczna
Pliki są serwowane z własnej subdomeny najemcy — img.theirdomain — na którą najemca wskazuje usługę za pomocą rekordu A. Czytelnik widzi swoją markę i swój adres, a w ogóle nie widzi keepix. W darmowym planie domena jest współdzielona; obie drogi działają w ten sam sposób.
Najemca może podłączyć tyle domen, ile chce, ale dokładnie jedną kanoniczną jedną, a to ograniczenie jest celowe: z dwoma kanonicznymi domenami jeden plik ma dwa adresy, co oznacza dwie pamięci podręczne i te same bajty pobrane dwa razy na ten sam telefon czytelnika.
Nagłówki dostawy są takie same dla każdego najemcy i nie zmieniają się: roczna niemutowalny pamięć podręczna, nosniff, default-src 'none'; sandbox, liberalna polityka CORS do odczytu, a nie pojedynczy Set-Cookie. Wieczna pamięć podręczna jest bezpieczna dokładnie dlatego, że adres zawiera hash treści: zmień bajty, a adres zmienia się razem z nimi, więc zastąpiony obrazek dociera do czytelnika natychmiast, zamiast czekać na TTL.
I dokładnie dlatego adres nie może być obliczany po stronie klienta. Jest zwracany przez usługę, przechowywany obok rekordu, do którego należy, i ponownie żądany przez resolve jeśli kiedykolwiek zaginie.
10Przyjęcie: typ, skanowanie wirusów, metadane
Wszystko w usłudze to plik, który ktoś wysłał — zdjęcie w recenzji, film instruktażowy. Zasady przyjmowania są napisane dla ich dobra, a nie dla samej formy, a każdy z nich istnieje, ponieważ alternatywa cicho zawodzi.
Określenie typu przez analizę a nie przez rozszerzenie nie jest pedanterią: rozszerzenie to jedyna rzecz, którą przesyłający w pełni kontroluje.Odmowa, gdy skaner jest wyłączony kosztuje dostępność i kupuje gwarancję, że "zeskanowane" oznacza zeskanowane.Ponowne kodowanie każdego obrazu oznacza, że starannie przygotowany plik nigdy nie dociera do czytelnika w swojej oryginalnej formie.Usuwanie metadanych podczas ponownego kodowania oznacza, że nie można o tym zapomnieć.
Po stronie dostawy gwarancje są strukturalne, a nie proceduralne. Host dostawy nie ma sesji, nie ma JavaScriptu i nie ma żadnego kodu wykonywalnego na ścieżce; treść wychodzi z polityką bezpieczeństwa treści, która uniemożliwia przeglądarce uruchomienie czegokolwiek, nawet jeśli coś niebezpiecznego się dostało. Dwie niezależne warstwy, ponieważ interesujące awarie to te, w których pierwsza warstwa była źle skonfigurowana i nikt tego nie zauważył.
Dziennik dostawy, z adresami czytelników, żyje 24 godziny. Nic w usłudze nie potrzebuje go dłużej, co sprawia, że jego dłuższe przechowywanie to po prostu gromadzenie śladów innych ludzi.
11Usuwanie wszystkiego o osobie
Każdy obiekt niesie ze sobą owner_ref — cokolwiek najemca nazywa właścicielem tego pliku. Dla obrazów katalogowych jest pusty: nie dotyczą one osoby. Dla zdjęć recenzji i filmów użytkowników jest wymagany.
Jedno żądanie usuwa wszystko pod nim, a odpowiedź nazywa liczbę: ile obiektów i ile plików zostało przesłanych. Ta liczba jest punktem końcowym. Brama danych osobowych powinna sprawdzać wykonanie, a nie zamiar — wiersz oznaczony jako usunięty, podczas gdy bajty wciąż leżą na dysku, to usunięcie, które nie miało miejsca, i nie będzie miało miejsca, dopóki ktoś na to nie spojrzy.
Usunięcie usuwa rekordy i bajty jednocześnie, a nie według harmonogramu, i zabiera ze sobą opóźnione kopie wcześniejszych wersji. To również jest element, który sprawia, że keepix jest użyteczny jako produkt z własnymi obowiązkami wynikającymi z RODO: proces usuwania w kodzie klienta może wywołać go w linii i odczytać liczbę z powrotem, zamiast ufać, że jakieś zadanie czyszczące gdzieś to załatwi.
Klucze podpisujące działają w ten sam sposób.Najemca zawsze ma używane dwa, ponieważ przy jednym kluczu rotacja oznacza przestój — a przestój to powód, dla którego rotacja jest odkładana w nieskończoność. Sekret jest pokazywany raz przy wydaniu i nigdy nie jest oddawany z powrotem do panelu sterowania: możliwość podpisania żądania to prawo do zapisu w czyimś magazynie.
12Podpisane API i uzgadnianie
Każde prywatne żądanie niesie cztery nagłówki — najemca, identyfikator klucza, znacznik czasu i podpis — a podpis to HMAC-SHA256 nad metodą, pełną ścieżką z zapytaniem, znacznikiem czasu i hashem ciała. Okno czasowe wynosi 300 sekund. Identyczne podpisane żądanie powtórzone w tej samej sekundzie jest odrzucane jako powtórka, co jest ochroną działającą zgodnie z zamierzeniem, a umowa mówi to wyraźnie, zamiast pozostawiać integratorów do odkrywania tego.
Zestaw punktów końcowych jest mały, a każdy z nich odpowiada na rzeczywiste pytanie operacyjne:
wstaw— zaakceptuj oryginał;wstaw-wariant— zaakceptuj już gotową kopię bez ponownego kodowania, aby przenieść to, co klient już ma. Ponowne kodowanie gotowej kopii oznacza utratę jakości bez powodu.resolveirozwiąż-partię(do 1000 kluczy) — jakie adresy ma ten klucz. To narzędzie naprawcze: jeśli rekord jest zgubiony, pytasz, a nie zgadujesz.uzgodnij— sucha kontrola, do 1000 rekordów na raz, która nic nie zmienia i odpowiadaok/brakujący/niedopasowanie/oczekującyna rekord plus podsumowanie partii.inwentarz— eksport, który wykonuje porównanie w drugą stronę, lista usługi w porównaniu do listy klienta, stronicowana według samego klucza, aby strona nie przesuwała się podczas akceptacji w trakcie działania.obiekt,wymaż,kwota,ping, i niepodpisanyhealthzktóry mówi, że front end działa i nic więcej — żadna wersja, żaden stan bazy danych.
Rekoncyliacja zasługuje na osobną uwagę, ponieważ jest to punkt końcowy, który uzasadnia cały kontrakt. Po dużej migracji istnieje dokładnie jedno pytanie, które ma znaczenie: czy wszystko przeszło. Odpowiadanie na nie plik po pliku oznacza tyle samo żądań, ile jest plików, więc nikt tego nie robi — a migracja jest uznawana za zakończoną na podstawie tego, że skrypt przesyłania nie zawiódł. Rekoncyliacja w partiach sprawia, że uczciwa odpowiedź jest wystarczająco tania, aby ją uzyskać.
13Panel, użycie i fakturowanie
Panel to biblioteka bez żadnego kodu: foldery, przeciąganie plików myszą, wyszukiwanie według tytułu, opisu i tagów. Działa w pełni bez JavaScriptu — skrypt dodaje wygodę, a nie możliwość pracy. To nie jest nostalgia; to najtańszy sposób, aby zapewnić, że panel pozostaje użyteczny przy słabym połączeniu i pozostaje testowalny bez silnika przeglądarki.
Użytkowanie liczone jest od początku miesiąca i podzielone na dni: ile pamięci, ile ruchu dostawczego i ile operacji przypada na każdą datę, ile pakietu zostało wykorzystane i co przyszło dodatkowo. Podział ma większe znaczenie niż suma — rachunek, którego nie można przypisać do dnia, to rachunek, z którym nie można dyskutować.
Trzy decyzje dotyczące fakturowania zasługują na wymienienie:
- Przechowywanie to średnia z okresu, a nie szczyt.Pojedynczy dzień z dużym przesyłem nie powinien wpływać na cenę całego miesiąca.
- Ruch dostawy to bajty, które faktycznie zostały dostarczone, pobrane z dziennika serwera — a nie "rozmiar pliku × liczba żądań", co zawyża każde żądanie zakresu i każde porzucone pobieranie.
- Stawki są utrzymywane w setnych części centa.Gigabajt może kosztować mniej niż cent; zaokrąglanie do pełnych centów zjadłoby całą fakturę metrową i cicho przekształciłoby rachunek w fikcję.
W darmowym planie nie ma w ogóle fakturowania metrowego: przyjęcie zatrzymuje się zamiast cicho zaczynać wydawać pieniądze klienta. Usługa, która sama decyduje o obciążeniu kogoś, kto nigdy nie wprowadził karty, to usługa, której nikt nie poleca dwa razy.
14Stos technologiczny
Wybraliśmy stos dla usługi, której gorącą ścieżką jest serwer WWW przekazujący plik:
- PHP 8.4 dla API i panelu sterowania — dojrzały, wystarczająco szybki na tej ścieżce i tani w utrzymaniu, co ma znaczenie dla produktu z darmowym poziomem.
- Dedykowany host dostarczający bezpośrednio z dysku, bez żadnego kodu aplikacji w ścieżce żądania.
- WebP dla obrazów o stałej jakości, H.264 + AAC w HLS dla wideo z progresywnym zapasowym MP4.
- Kolejkado pracy z wideo, więc transkodowanie nigdy nie znajduje się w żądaniu przesyłania.
- HMAC-SHA256podpisywanie żądań z dwoma aktywnymi kluczami na najemcę i oknem czasowym 300 sekund.
- Zimne drzewo oryginałówpoza serwowaną ścieżką, co sprawia, że nowe warianty i odbudowy są możliwe później.
Usługa jest celowo konserwatywna w tym, na czym polega. Nie wykonuje żadnych własnych żądań wychodzących, nie używa zewnętrznego CDN i nie przechowuje żadnych danych o użytkownikach klienta poza najemcą, kluczem, rodzajem, liczbą bajtów i wariantami. Każda zależność, której nie masz, to zależność, która nie może zepsuć twoich mediów w wtorek.
15Projektowanie i UX
Publiczna strona miała jedno zadanie: uczynić produkt infrastrukturalny zrozumiałym dla inżyniera, który go rzeczywiście zintegrował. Dlatego pierwszy ekran pokazuje prawdziwe żądanie i prawdziwą odpowiedź — adresy wracające w JSON — zamiast ich abstrakcji. Integrator decyduje w około trzydzieści sekund, czy usługa multimedialna pasuje do ich kodu, a decyduje, patrząc na kształt odpowiedzi.
Reszta strony jest napisana w ten sam sposób. Każda funkcjonalność jest podana razem z jej ograniczeniem: nazwane warianty idlaczego arbitralne szerokości są odrzucane; wieczna pamięć podręcznaihash w adresie, który czyni go bezpiecznym; punkt końcowy do usuwaniainumer, z którym odpowiada. Dokumentacja, która tylko wymienia, co usługa może zrobić, pozostawia czytelnika do odkrywania granic w produkcji.
W panelu to samo zasada przekształca się w podstawę bez JavaScript i codzienny podział użycia: nic na ekranie, czego czytelnik nie może sprawdzić, i nic, co przestaje działać, gdy skrypt nie ładuje się.
16Jak pracowaliśmy
Projekt przebiegał w etapach, z każdym kończącym się czymś demonstracyjnym:
- Najpierw umowa.Napisaliśmy umowę API — schemat podpisu, punkty końcowe, kody odmowy, kształty odpowiedzi — przed wdrożeniem, ponieważ umowa jest częścią, na którą klienci budują, i częścią, która jest kosztowna do zmiany.
- Przyjęcie i warianty.Rura, w ustalonej kolejności, z dwoma zasadami o nie rozciąganiu i nie przechowywaniu duplikatów wbudowanymi od samego początku.
- Dostawa.Oddzielny host, zestaw nagłówków, adresowanie oparte na zawartości, które czyni wieczną pamięć podręczną bezpieczną.
- Wideo.Drabina, plakat i podgląd, oraz kolejka, która ciągle transkoduje z żądania przesyłania.
- Wielu najemców.Domeny, rodzaje, warianty, limity i model rotacji z dwoma kluczami.
- Fakturowanie i pulpit nawigacyjny.Mierzone liczenie z codziennym podziałem, a następnie interfejs biblioteki na tym.
- Prawdziwa migracja.Przenieśliśmy żywy katalog na usługę i zrekompensowaliśmy go w partiach — w ten sposób punkt końcowy rekonsyliacji zyskał swoją formę.
Ostatni etap był wart więcej niż jakiekolwiek wewnętrzne testy. Przeniesienie setek tysięcy prawdziwych plików ujawniło rzeczy, których zestaw testów nie wykrywa: obiekty, które usługa zaakceptowała i zgubiła, rekordy, których przechowywany adres się rozmył, oraz różnicę między sprawdzeniem, które weryfikuje hashe, a sprawdzeniem, które jedynie potwierdza istnienie wiersza. Weryfikacja, gdy nie ma nic do zweryfikowania, zgłasza sukces — więc sprawiliśmy, że tryb słaby informuje, w jakim trybie się znajduje.
17Wynik
To, co powstało, to host mediów, na którym produkt może polegać: jedno podpisane żądanie w, zakończone adresy na zewnątrz, serwowane z domeny klienta z pamięcią podręczną, która może być przechowywana na zawsze.
- Nazwane warianty i drabina HLS, zbudowane raz i przechowywane na zawsze za adresem z hashem treści.
- Własna subdomena klienta: czytelnik widzi swoją markę, a nie naszą.
- Bezpieczeństwo wbudowane w ścieżkę przyjmowania — analizowany typ, odrzucenie skanowania wirusów, ponowne kodowanie, usunięte metadane, SVG odrzucone na obu końcach.
- Usunięcie, które odpowiada liczbą, aby brama danych osobowych mogła sprawdzić wykonanie zamiast zamiaru.
- Wielu najemców z własnymi domenami, własnymi sufitami i rotacją dwóch kluczy bez przestojów.
- Rozliczenia metrowe trzymane w setnych części centa, rozbite na dni, oraz darmowy plan, który zatrzymuje się zamiast wydawać.
18Wnioski
keepix to przypadek, w którym większość inżynierii poszła w decyzję, co usługa ma odrzucić. Brak arbitralnych szerokości, brak obliczonych adresów, brak SVG, brak żądań wychodzących, brak zachowywania oryginalnych bajtów na serwowanej ścieżce, brak rozliczeń w darmowym planie. Każde z tych działań eliminuje całą klasę awarii zamiast radzić sobie z jedną.
Główna lekcja, którą przekażemy do następnego projektu infrastrukturalnego: sprawić, by szczera odpowiedź była tania do uzyskania. Rekonsyliacja w partiach, użycie rozbite na dni, usunięcie, które zwraca liczbę, odpowiedź przyjęcia, która wskazuje, co zostało pominięte — w każdym przypadku alternatywą nie była błędna odpowiedź, ale brak odpowiedzi, a brak odpowiedzi to to, na co zespoły cicho się godzą.
Jeśli potrzebujesz usługi medialnej pod własną domeną, pipeline'u plików, który musi być bezpieczny z przesyłkami innych osób, lub produktu z API na pierwszym miejscu, gdzie umowa ma większe znaczenie niż ekrany, to jest to rodzaj pracy, który wykonujemy od początku do końca.



