Otwierasz elido.me/abc123 i cos musi zamienic ten krotki ciag znakow w pelny adres internetowy, zanim Twoja przegladarka moze cokolwiek zaladowac. Mechanizm jest prostszy, niz wiekszosc ludzi zaklada. Skracacz URL przechowuje mapowanie krotkiego kodu na dlugi docelowy URL. Gdy klikasz krotki link, usluga traktuje kod jak klucz wyszukiwania, znajduje cel i zwraca przekierowanie HTTP, ktore informuje Twoja przegladarke, dokad faktycznie pojsc. Jedno zadanie wchodzi, jedno przekierowanie wychodzi.
To caly pomysl. Wszystko inne to inzynieria wokol trzech wymagan: szybkie wyszukiwanie, krotkie i unikalne kody oraz rejestrowanie klikniec bez spowalniania kogokolwiek. Ten artykul opisuje, jak dzialaja skracacze URL od poczatku do konca, uzywajac architektury brzegowej Elido jako konkretnego przykladu, zachowujac jednoczesnie wyjasnienie prawdziwe dla skracaczy w ogole. Omowimy mapowanie slug-na-URL, sposob generowania krotkich kodow, gdzie zyja dane, wybor przekierowania 301 kontra 302, ktory myli wiecej osob niz cokolwiek innego, jak wygladaja przekierowania HTTP w sieci, dlaczego buforowanie na brzegu ma znaczenie i jak klikniecie jest liczone asynchronicznie.
Jak dzialaja skracacze URL: mapowanie w centrum#
Odstrip infrastrukture, a skracacz URL to magazyn klucz-wartosc z doczona procedura obslugi przekierowania. Kluczem jest slug, krotki kod po domenie. Wartoscia jest cel, dlugi URL, ktory pierwotnie wkleilas.
Gdy tworzysz krotki link, skracacz zapisuje jeden wiersz: ten slug wskazuje na ten cel. Gdy ktos odwiedza krotki link, skracacz odczytuje ten wiersz i dziala na jego podstawie. Tworzenie linkow jest rzadkie; ich odczytywanie jest ciasle. Pojedynczy link marketingowy moze zostac zapisany raz, a nastepnie odczytany kilkaset tysiecy razy w ciagu swojego zycia. Ten stosunek odczytu do zapisu to jedyny najwazniejszy fakt o tym obciazeniu i ksztaltuje kazda decyzje projektowa, ktora nastepuje, zwlaszcza buforowanie.
Mapowanie moze niesc wiecej niz cel. W Elido slug moze zawierac reguly targetowania, wiec jeden krotki link kieruje do roznych celow wedlug kraju, urzadzenia, jezyka lub czasu. To to, co nazywamy inteligentnym linkiem, i nadal jest to to samo wyszukiwanie, tylko z malym przetwarzaniem regul po odczycie. Podstawowy zwiazek nigdy sie nie zmienia: slug wchodzi, cel wychodzi.
Generowanie krotkiego kodu#
Jesli slug jest kluczem, skad pochodzi? Istnieja dwa sprawdzone podejscia i wiekszosc skracaczy uzywa jednego lub mieszanki obu.
Pierwsze to kodowanie base62 identyfikatora bazy danych. Kazdy nowy link otrzymuje auto-inkrementujacy identyfikator calkowity z bazy danych. Kodujesz ten liczbe calkowita w base62, ktory uzywa 62 bezpiecznych URL znakow a-z, A-Z i 0-9. ID 1 staje sie b, ID 125 staje sie dwuznakowym kodem i tak dalej. Base62 jest gesty: trzy znaki obejmuja okolo 238 000 linkow, piec znakow okolo 916 milionow, szesc okolo 56 miliardow. Kody sa krotkie i, poniewaz mapuja jeden do jednego na unikalne identyfikatory, nigdy nie koliduja. Kompromisem jest to, ze sekwencyjne identyfikatory sa do odgadniecia, wiec wiele systemow miesza lub przesuwa przestrzen identyfikatorow przed kodowaniem.
Drugie podejscie to losowe generowanie. Wybierz losowy ciag o stalej dlugosci z tego samego alfabetu, a nastepnie sprawdz baze danych, czy nie jest juz zajety. W przypadku kolizji wygeneruj inny. Kolizje sa niezwykle rzadkie przy sensownych dlugosciach, wiec petla ponownych prob prawie nigdy nie dziala. Losowe slugi nie sa przeliczalne, co jest argumentem bezpieczenstwa przemawiajacym za nimi.
Niestandardowe slugi, markowe jak elido.me/spring-sale, leza na wierzchu obu schematow. Uzytkownik podaje ciag znakow; skracacz waliduje go pod katem dozwolonych znakow i sprawdza unikalnosc w tym samym indeksie przed zapisem. Niezaleznie od tego, czy slug jest generowany czy reczny, trafia w to samo miejsce: unikalna kolumna w bazie danych.
Gdzie zyja dane#
Mapowanie slug-do-celu potrzebuje domu, ktory moze szybko i konsekwentnie odpowiedziec "na co wskazuje ten slug". Dla zrodla prawdy tym domem jest prawie zawsze relacyjna baza danych. Elido uzywa Postgres, ze slugiem przechowywanym jako unikalna zindeksowana kolumna, dzieki czemu wyszukiwanie to pojedynczy odczyt kluczowy, a nie skanowanie tabeli. Postgres przechowuje kanoniczna dokumentacje kazdego linku, uzytkownika i przestrzeni roboczej.
Ale trafianie do Postgres przy kazdym pojedynczym kliknieciu byloby marnotrawstwem, biorąc pod uwage stosunek odczytu do zapisu. Kluczowe wyszukiwanie sluga w Postgres zazwyczaj zajmuje od jednej do trzech milisekund, co brzmi szybko, dopoki nie pomnozyc przez wolumen klikniec viralowego linku i nie pamietac, ze polaczenie z baza danych jest ograniczonym zasobem. Dlatego produkcyjne skracacze umieszczaja cache przed baza danych. Cache to miejsce, gdzie faktycznie obslugiwana jest wiekszosc odczytow; baza danych to rozwiazanie awaryjne dla wszystkiego, czego cache jeszcze nie ma.
Elido uruchamia dwupoziomowa pamiec cache przed Postgres. Pierwszy poziom to wewnatrzprocesowy cache LRU zyjacy wewnatrz binarnego pliku przekierowania, ktory zwraca cel w kilkuset nanosekundach bez zadnego przeskoku sieciowego. Drugi poziom to klaster Redis w tym samym regionie, ktory obsluguje w czasie ponizej milisekundy. Tylko zimne chybienie, slug, ktorego zaden poziom nie widzial ostatnio, przechodzi do wywolania gRPC do api-core, ktory czyta Postgres. Laczny wspolczynnik trafien na obu poziomach cache wynosi okolo 99,4%, wiec baza danych jest uzywana przy mniej wiecej jednym zadaniu na 167. Pelne omowienie zachowania tego cache, w tym jego polityke eksmisji i tryby awarii, mozna znalezc w naszym opisie strategii cache.
Czym tak naprawde jest przekierowanie HTTP#
Gdy skracacz ma juz cel, musi przekazac go przegladarce. Robi to za pomoca przekierowania HTTP, ktore jest po prostu specyficznym rodzajem odpowiedzi. Zamiast zwracac tresc strony z 200 OK, serwer zwraca kod statusu 3xx i naglowek Location podajacy prawdziwy URL. W sieci odpowiedz jest mala:
HTTP/1.1 302 Found
Location: https://shop.example.com/spring-collection
Content-Length: 0
Przegladarka odczytuje kod statusu, widzi naglowek Location i natychmiast wystawia nowe zadanie na ten adres. Dla osoby klkajacej wyglada to jak jedna nawigacja; pod spodem sa dwa zadania, a krotki link dziala jak szybkie wyszukiwanie katalogu posrodku. Semantyka kazdego kodu 3xx jest zdefiniowana w RFC 7231, a przewodnik Mozilli po przekierowaniach HTTP jest najcleyszym praktycznym zrodlem na temat tego, co robi kazdy kod.
Tresc jest pusta, bo nie ma nic do renderowania. Caly ladunek to linia statusu i naglowek. Dlatego przekierowania sa tanie do obsluzenia: nie ma szablonu, nie ma polaczenia z baza danych dla tresci, nie ma znacznikow. Rozwiaz slug, ustaw jeden naglowek, wyslij.
301 kontra 302: wybor, ktory decyduje o Twojej analityce#
Tu skracacze po cichu podejmuja decyzje, ktorej wiekszosc uzytkownikow nigdy nie widzi, ale ktora decyduje o tym, czy ich link jest edytowalny i sledzalny. Kod statusu przekierowania to nie formalnosc. Dwie popularne opcje zachowuja sie bardzo roznie.
301 Moved Permanently informuje przegladarke i kazdy serwer posredni oraz CDN miedzy Toba a serwerem, ze ten krotki link bedzie zawsze wskazywac na to samo miejsce. Wiec je buforuja. 301 jest agresywnie przechowywane. Nastepnym razem, gdy odwiedzajacy kliknie ten krotki link, jego przegladarka moze rozwiazac go z cache i w ogole nie kontaktowac skracacza. To swietne dla zaoszczedzenia round tripu i katastrofalne dla narzedzia do linkow, bo psuja sie dwie rzeczy. Po pierwsze, analityka slepi: klikniecia obslugiwane z cache przegladarki nigdy nie docieraja do serwera, wiec nie sa liczone. Po drugie, cel jest praktycznie zamrozony. Jesli zmienisz, dokad wskazuje link, kazdy, kto juz zbuforowal 301, laduje nadal na starym adresie, az jego cache wygasnie, a tego nie kontrolujesz.
302 Found (i jego surowszy kuzyn 307 Temporary Redirect) informuje przegladarke, ze to tymczasowe: wracaj i pytaj ponownie nastepnym razem. Przegladarka nie buforuje mapowania, wiec kazde klikniecie ponownie odpytuje krotki link z serwera. Ten dodatkowy round trip to dokladnie to, czego chce narzedzie do linkow. Kazde klikniecie dociera do Twojej infrastruktury, wiec kazde jest liczalne, a poniewaz serwer rozwiazuje cel swieze za kazdym razem, mozesz zmienic, dokad prowadzi link, a nowy cel wchodzi w zycie przy nastepnym kliknieciu. Koszt to jeden sieciowy round trip na klikniecie, ktory dobrze zbudowana krawedziowka utrzymuje w jednocyfrowych milisekundach.
Dlatego Elido domyslnie uzywa 302. Edytowalne cele i dokladne dane klikniec to caly sens zarzadzanego linku, a 301 oddaje jedno i drugie dla optymalizacji cache, ktorej zazwyczaj nie chcesz. RFC 7231 precyzuje, ze 301 jest domyslnie buforowalne, podczas gdy 302 nie jest przechowywane, chyba ze naglowki mowia inaczej, co jest dokladnie zachowaniem wymaganym dla tych dwoch przypadkow uzycia. Sa waskie przypadki, gdy trwale przekierowanie jest prawidlowe, np. przy prawdziwej migracji domeny, ale dla sledzalnych, edytowalnych krotkich linkow tymczasowe przekierowanie jest wlasciwym domyslnym.
Buforowanie na krawedzi dla niskiego opoznienia#
Przekierowanie jest synchroniczne i blokujace. Przegladarka odwiedzajacego zatrzymuje sie na krotkim linku, az pojawi sie przekierowanie, i dopiero wtedy moze zaczac ladowac strone, ktora naprawde ma znaczenie. Kazda milisekunda spedzona na rozwiazywaniu sluga to milisekunda dodana do czekania odwiedzajacego. Dlatego powazne skracacze przenosza wyszukiwanie jak najblizej odwiedzajacego.
Elido uruchamia procedury obslugi przekierowania w punktach obecnosci na krawedzi we Frankfurcie, Ashburn i Singapurze, z ruchem kierowanym do najblizszego z nich. Procedura obslugi jest napisana w Go na bazie fasthttp, wybranego, bo jego sciezka zadania bez alokacji sprawia, ze przerwy garbage collection sa przewidywalne pod trwalym obciazeniem. W polaczeniu z pamecia wewnetrzna, utrzymuje to przekierowania na poziomie p95 ponizej 15ms przy trafieniu do cache, mierzone na POP: okolo 4,8ms mediany we Frankfurcie, rosnac do okolo 14ms p95 w Singapurze, gdzie geografia jest szersza. Wiekszosc tego budzetu to fizyczny transport sieciowy, nieunikniona odleglosc miedzy odwiedzajacym a najblizszym POP, ktora jest czescią, ktorej nie mozna zoptymalizowac w oprogramowaniu. Udokumentowalismy pelny budzet opoznien i jak mierzy sie kazdy region w artykule o p95 ponizej 15ms.
Umieszczenie wyszukiwania na krawedzi, a nie na pojedynczym centralnym serwerze, to roznica miedzy przekierowaniem, ktore wydaje sie chwilowe, a takim, ktore dodaje widoczne zatrzymanie. To rowniez dlaczego trasowanie brzegowe anycast bije konfiguracje tylko-DNS dla tego obciazenia, porownanie, w ktore wchodzimy w artykule brzegowe POPy kontra trasowanie tylko-DNS. Krotka wersja: siec obsługuje geografię, a cache obsługuje szybkosc.
Liczenie klikniec bez spowalniania przekierowania#
Skracacz, ktory tylko przekierowywal, bylby usluga przekierowania. To, co czyni go narzedziem do zarzadzania linkami, to fakt, ze liczy kazde klikniecie i mowi, kto klika, skad, na jakim urzadzeniu. Trudna czesc to robienie tego bez zmuszania odwiedzajacego do czekania na to.
Odpowiedzia jest calkowite rozdzielenie tych dwoch. Gdy procedura obslugi przekierowania rozwiazuje slug, natychmiast wyslaje odpowiedz 302. Rejestrowanie klikniec nastepuje pozniej, jako praca fire-and-forget. Procedura obslugi doluza zdarzenie klikniecia - slug, znacznik czasu, skrocone IP, hash user-agenta - do kolejki komunikatow i idzie dalej. Nie czeka na potwierdzenie zapisu. Jesli kolejka jest chwilowo niedostepna, klikniecie jest tracone, a nie opoznienie przekierowania; swiadomie zdecydowalismy, ze utrata klikniec przy awarii infrastruktury jest akceptowalna, a zepsute przekierowanie nie jest.
Elido uzywa Redpanda jako tej kolejki. Oddzielny konsument, click ingester, czyta zdarzenia z kolejki i zapisuje je do ClickHouse, kolumnowej bazy danych zbudowanej do tego rodzaju obciazenia duzej ilosci danych - zapisz i agreguj - ktory jest analityka klikniec. Przekierowanie odwiedzajacego zostalo juz zakonczone millisekund wczesniej; wiersz analityki laduje kilka sekund pozniej, calkowicie poza sciezka goraca. Wyjasniamy projekt kolejki w artykule fire-and-forget ingestion klikniec i dlaczego kolumnowy magazyn bije Postgres w artykule dlaczego uzywamy ClickHouse do analityki klikniec.
To rozdzielenie jest powodem, dla ktorego Twoja analityka moze byc szczegolowa bez bycia wolna. Sciezka przekierowania pozostaje prosta, bo zadne liczenie, scorowanie ani agregacja nie nastepuje, gdy odwiedzajacy czeka.
Sklada sie w calosc#
Skracacz URL, od poczatku do konca, to krotka sekwencja. Tworzysz link, a skracacz przechowuje mapowanie slug-do-celu w Postgres, generujac lub walidujac slug jako unikalny klucz. Odwiedzajacy klika, zadanie laduje na najblizszym brzegowym POP, a procedura obslugi rozwiazuje slug z pamieci wewnetrznej, przechodzac do Redis, a nastepnie do bazy danych tylko przy chybieniu. Zwraca 302 z celem w naglowku Location, dzieki czemu klikniecie jest liczalne, a cel pozostaje edytowalny. Nastepnie odpala zdarzenie klikniecia do kolejki dla oddzielnego konsumenta do przechowywania, bez zmuszania kogokolwiek do czekania.
Kazdy element jest z osobna prosty. Inzynieria tkwi w stosunkach i budzetach: obciazenie z przewaga odczytu, ktore chce cache, sufit opoznien, ktory chce krawedz, i wymog analityczny, ktory chce pozostac poza sciezka goraca. Jesli chcesz na tym bezposrednio budowac, funkcja Smart Links udostepnia warstwe regul, API i SDK pozwalaja tworzyc linki z kodu, a strona rozwiazan dla developerow i dokumenty architektury edge-redirect ida glebiej w poruszajace sie czesci. Jesli oceniasz narzedzie, a nie je budujesz, nasze opisy czym jest skracacz URL i czy skracacze URL sa bezpieczne omawiaja to od strony uzytkownika, a strona cenowa pokazuje, gdzie konczy sie bezplatny poziom.