Щоб побудувати скорочувач URL, вам потрібні чотири речі: місце для зберігання відповідності між коротким кодом і URL призначення, спосіб генерувати унікальний код для кожного нового посилання, обробник перенаправлень, що шукає код і повертає HTTP-перенаправлення, та кеш перед пошуком, тому що читань набагато більше, ніж записів. Це весь основний механізм, і ви можете розгорнути його за одну другу половину дня.
Пастка - це думати, що версія за другу половину дня є продуктом. Перенаправлення, що працює на вашому ноутбуці, і сервіс скорочення URL, який витримує те, що сторонні люди вказують його на шкідливе ПЗ, атакують трафіком і очікують чотири дев'ятки доступності - це різні інженерні завдання. Перше - алгоритм. Друге - операційне зобов'язання.
Цей покроковий посібник чесно будує ядро, а потім витрачає більшість часу на частину, яку пропускають туторіали з проектування систем: що ще потрібно побудувати після того, як перенаправлення запрацює. Якщо спочатку хочете концептуальний вступ, стаття як працюють скорочувачі URL охоплює механіку без коду.
Коротка версія: що насправді робить скорочувач URL#
Скорочувач URL - це пошук за ключем-значенням в оболонці HTTP-перенаправлення. Ключ - це короткий код, значення - довгий URL, і вся робота полягає в тому, щоб перетворити example.com/aB3x9 на 302, що вказує на вихідну адресу.
Модель даних - одна таблиця:
CREATE TABLE links (
id BIGSERIAL PRIMARY KEY,
short_code TEXT NOT NULL UNIQUE,
long_url TEXT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE UNIQUE INDEX idx_links_short_code ON links (short_code);
Через неї проходять два шляхи. Шлях запису приймає довгий URL, генерує короткий код і вставляє рядок. Шлях читання приймає короткий код, шукає рядок і повертає перенаправлення. Читань домінує у співвідношенні, що зазвичай становить близько 1000 до 1, тому майже вся ваша інженерна увага повинна бути зосереджена на тому, щоб зробити пошук швидким і дешевим. Унікальний індекс на short_code - це те, що перетворює пошук на пошук за індексом замість повного сканування. Ось і весь основний механізм.
Генерація короткого коду: base62, випадковий або хеш#
Короткий код - це місце, де живе цікаве рішення. У вас є три реалістичні стратегії, і вони обмінюються довжиною, передбачуваністю та складністю обробки колізій.
Base62 унікального ID - класика. Беремо ID рядка з автоінкрементом і кодуємо його в base62, 62 символи a-z, A-Z та 0-9. Коди короткі, вони ніколи не колізіюють, тому що кожен ID унікальний, і стають на один символ довшими приблизно кожні 62 рази у обсязі. Недолік у тому, що вони послідовні та вгадувані, тому кожен може обходити ваш простір імен.
const alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
// encode turns a positive integer ID into a base62 short code.
func encode(id uint64) string {
if id == 0 {
return string(alphabet[0])
}
var b []byte
for id > 0 {
b = append(b, alphabet[id%62])
id /= 62
}
// reverse, since we built the digits least-significant first
for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
b[i], b[j] = b[j], b[i]
}
return string(b)
}
Випадкові рядки вирішують проблему вгадуваності. Генеруємо короткий випадковий код, наприклад за допомогою бібліотеки nanoid, і перевіряємо його на унікальний індекс перед збереженням. При семи символах base62 у вас трильйони можливостей, тому колізії рідкісні, але ви все одно маєте обробляти рідкісну вставку, яка не проходить обмеження унікальності, повторюючи спробу з новим кодом.
Хешування URL - третій варіант і зазвичай найгірший. Хеш довгого URL є детермінованим, що звучить зручно, але вам все одно потрібно його обрізати, вам все одно трапляються колізії, і однакові URL відображаються в однакові коди, що витікає інформацію. Більшість продакшн-сервісів вибирають base62 для внутрішніх ID або випадкові коди для публічних. Власні або брендові слаги, коди, які користувач вводить вручну, перевіряються на той самий унікальний індекс перед тим, як їх приймають.
Шлях перенаправлення: 301 проти 302 і чому це визначає вашу аналітику#
Статус-код перенаправлення - не косметичний вибір. Він вирішує, чи побачите ви коли-небудь другий клік.
301 Moved Permanently повідомляє браузерам і проксі, що переміщення постійне, тому вони кешують його. Після першого відвідування браузер може надсилати майбутні кліки безпосередньо на призначення, не торкаючись вашого сервера. Чудово для чистої швидкості, але фатально для аналітики, тому що кліки, які ви найбільше хочете рахувати, - це ті, що ніколи до вас не доходять. HTTP-семантика описана в RFC 9110, який визначає як постійні, так і тимчасові перенаправлення.
302 Found або 307 Temporary Redirect запитується знову кожного разу. Браузер звертається до вашого сервера при кожному кліку, що означає: ви можете рахувати кожне відвідування і можете змінювати призначення пізніше, не борючись зі застарілими кешами. Для скорочувача посилань, чия вся цінність полягає в редагованих посиланнях і даних кліків, це правильний стандарт. Витрата - один мережевий туди-назад на клік, що влучення в кеш робить незначним.
Практичне правило: вибирайте 302, якщо немає конкретної причини хотіти посилання замороженим і кешованим назавжди. Стаття 301 vs 302 redirects детально розбирає компроміс, а types of redirects охоплює решту сімейства 3xx, включно з тим, коли мають значення 307 і 308.
Зберігання і кешування: проектування для співвідношення читань до записів 1000:1#
Оскільки читань набагато більше, ніж записів, база даних - не ваше вузьке місце, а ваша стратегія кешування. Схема - кеш із наскрізним читанням: при кліку спочатку перевіряємо кеш у пам'яті, і лише у разі промаху звертаємося до бази даних, записуючи результат назад у кеш для наступного разу.
func resolve(ctx context.Context, code string) (string, error) {
if url, ok := cache.Get(code); ok {
return url, nil // hot path: served from memory
}
url, err := db.LookupLongURL(ctx, code)
if err != nil {
return "", err
}
cache.Set(code, url) // populate for the next click
return url, nil
}
У продакшні це зазвичай стає двома рівнями: невеликий внутрішній кеш для найгарячіших посилань, підкріплений спільним сховищем у пам'яті, таким як Redis, щоб кожен екземпляр сервера міг скористатись пошуком, який вже виконав будь-який інший. База даних, джерело правди, торкається лише при справжньому холодному промаху. Правильно налаштуйте цей рівень, і один скромний сервер обробляє величезний обсяг кліків. Стаття стратегія кешування для URL-перенаправлень детально розбирає рішення щодо виселення та розміру, а основний матеріал про досягнення p95 нижче 15ms охоплює, як виглядає налаштований шлях перенаправлення під навантаженням.
Якщо ви краще не запускатимете нічого з цього, API Elido дає вам рівень перенаправлення, кеш і доставку всередині ЄС з p95 нижче 15ms при влученні в кеш, за одним викликом. Починайте безкоштовно і оминайте операційні турботи.
Підрахунок кліків без уповільнення перенаправлення#
Помилка, що вбиває затримку перенаправлення, - це запис кліку в базу даних усередині обробника перенаправлення. Зробіть це, і кожен відвідувач чекатиме запису аналітики, перш ніж отримає своє перенаправлення.
Розв'яжіть їх. Обробник негайно видає перенаправлення, потім надсилає подію кліку в довговічний журнал або чергу повідомлень як роботу "вистрелив і забув". Окремий споживач читає цей потік і записує події в аналітичне сховище за своїм розкладом. Відвідувач ніколи не чекає, і запит звітності, що сканує мільйони рядків кліків, ніколи не конкурує з шляхом перенаправлення за ресурси. Стовпцева аналітична база даних набагато краще обробляє ці агрегатні запити, ніж рядкове сховище, ось чому події кліків зазвичай потрапляють кудись відмінним від таблиці посилань. Стаття прийом кліків за принципом "вистрелив і забув" деталізує сторону черги, а стаття чому стовпцеве сховище перевершує Postgres для аналітики кліків пояснює вибір сховища. Аналітика Elido слідує цій формі, тому кліки доступні для запиту за секунди, не додаючи мілісекунди до перенаправлення.
Що ще потрібно побудувати: важкі 80 відсотків#
Ось частина, яку пропускають туторіали з проектування систем. Робоче перенаправлення - це, можливо, п'ята частина реального сервісу скорочення URL. Решта - це все, що перетворює демо на щось, що можна розмістити у публічному інтернеті.
- Сканування на зловживання і безпеку. Публічний скорочувач стає мішенню для фішингу протягом кількох годин після запуску. Вам потрібно перевіряти призначення за стрічкою загроз, такою як Google Safe Browsing, і повторно сканувати, тому що чистий URL при створенні може згодом стати шкідливим. Контрольний список безпеки скорочувача URL - це повний перелік.
- Обмеження швидкості та ідемпотентність. Відкритий ендпоінт створення відразу атакують скриптами. Вам потрібні обмеження на ключ і ідемпотентність, щоб повторний запит не створював дублюючих посилань. Механіка - в статті обмеження швидкості API та ідемпотентність.
- Власні домени з TLS. Брендовані посилання означають видачу сертифікатів для доменів, якими ви не володієте, на вимогу, без ручних кроків.
- Дані кліків, безпечні відповідно до GDPR. У момент, коли ви фіксуєте кліки, ви обробляєте персональні дані. Скорочення IP-адрес і документування збереження є обов'язковими в ЄС, як пояснює стаття GDPR для скорочувачів URL.
- Висока доступність. Ваше перенаправлення тепер знаходиться на критичному шляху кожного посилання, яким хтось будь-коли поділився. Простой ламає чужий контент, тому планка доступності вища, ніж для більшості застосунків.
Нічого з цього не є екзотичним. Це просто багато тривалої роботи, яка ніколи не закінчується, і це чесна причина, чому більшість команд зупиняються на MVP і сягають до чогось підтримуваного.
Будувати, купувати або самостійно хостити#
Будувати самостійно - найкращий спосіб зрозуміти перенаправлення, кодування та кешування, і для закритого внутрішнього інструменту MVP може бути все, що вам коли-небудь знадобиться. Будуйте його. Ви дізнаєтеся більше за вихідний день, ніж від будь-якої підготовки до співбесід.
Для всього публічного або бізнес-спрямованого чесно зважте обслуговування. Перенаправлення безкоштовне; обробка зловживань, TLS для власних доменів, аналітичний конвеєр і чергування чергувань - ні. Якщо вам потрібен контроль без написання з нуля, ви можете самостійно хостити існуючий сервіс, і Elido надає шлях самостійного хостингу саме для цього, а стаття про варіанти з відкритим кодом розставляє їх поруч. Якщо ви краще передасте це повністю, рішення для розробників і стаття швидкий старт з API та SDK дадуть вам продакшн-рівень перенаправлення без вищезазначеного невирішеного списку.
Читайте також у блозі#
- Як працюють скорочувачі URL - концептуальний вступ, без коду.
- Досягнення p95 нижче 15ms для перенаправлень - основний інженерний матеріал про налаштований шлях перенаправлення.
- Стратегія кешування для URL-перенаправлень - двоступеневий кеш у деталях.
- Прийом кліків за принципом "вистрелив і забув" - розв'язка аналітики від перенаправлення.
- Самостійно хостовані скорочувачі URL - варіанти з відкритим кодом, якщо ви краще не будуватимете з нуля.
Спробуйте Elido
Вставте URL - отримайте коротке посилання
Без реєстрації. Посилання живе 30 днів. Зареєструйтесь, щоб зберегти назавжди.
Безкоштовно, без реєстрації · 2 на день