Сокращённые ссылки
«Сокращённый» URL-адрес
может выглядеть примерно вот так: https://ts.dz/qp7h3zi
. Здесь ts.dz
– это домен
приложения или компании, а последняя часть – уникальный идентификатор (токен).
Длина
токена обычно варьируется от 6 до 9 символов. Для создания безопасного URL, берутся цифры 0-9
и буквы латинского алфавита в нижнем регистре a-z
. То есть общий набор возможных вариантов каждого символа состоит из 36 элементов.
Ниже показано количество уникальных комбинаций, которые могут быть сгенерированы
в зависимости от длины токена.
Длина токена | Уникальные комбинации | Диапазон |
6 | 2,176,782,336 | > 2 млрд |
7 | 78,364,164,096 | > 78 млрд |
8 | 2,821,109,907,456 | > 2 трлн |
9 | 101,559,956,668,416 | > 100 трлн |
Из приведённой таблицы следует, что длины токена из 7 символов достаточно, чтобы получить свыше 78 миллиардов уникальных комбинаций.
Как работают сокращённые ссылки
Работа со ссылками состоит из двух частей:
- Генерация коротких URL – обработка запроса на создание короткого URL.
- Перенаправление с короткого URL на оригинальный –необходимо описать, как обрабатывать короткий URL после клика юзера, чтобы перенаправить его на исходный длинный URL-адрес.
Генерация коротких URL-адресов
Служба сокращения ссылок действует следующим образом:
- Сервис принимает длинный URL, пришедший в
POST
-запросе. - Сервис проверят, нет ли уже такого URL в базе данных. Если входящий длинный URL уже существует в системе, то в ней остался и сгенерированный короткий вариант.
- Если длинного URL нет в базе данных или срок действия сокращённой ссылки истёк, необходимо создать новый токен и отправить короткий URL в качестве ответа, сохранив результат в базе данных.
- Сервис отправляет короткий URL в качестве ответа. Статус
HTTP 201
, если создана новая запись или200
, если запись уже была в базе данных.
Перенаправление
Когда пользователь кликает по сокращённой ссылке, запрос отправляется сервису сокращения URL-адресов, а он перенаправит его на необходимый «реальный» адрес:
- Сервис принимает короткий URL в виде
GET
-запроса. - Сервис проверяет, имеется ли данный токен в базе данных. Если токена не существует, генерируется ответ
HTTP 404 NOT FOUND
. - Если токен присутствует в базе данных, возвращается соответствующих результат. Если время токена истекло, ответом будет
HTTP 498
. - Если всё в порядке, возвращается
LOCATION header
и происходит перенаправление (HTTP 302
) по длинной ссылке.
Как генерируются токены
Логика генерирования уникальных случайных токенов довольно хитрая. Служба сокращения URL должна гарантировать, что токен назначен только одному URL-адресу. Иначе может произойти некорректное перенаправление.
Надёжной библиотекой, генерирующей уникальные токены, является Hashids. Она позволяет создавать короткие, уникальные идентификаторы из цифр и букв для всех распространённых языков программирования. Объём кода очень мал, и нет никаких внешних библиотечных зависимостей.
Зашифруем для примера строку "this is my
salt"
:
Hashid | Токен | Короткая ссылка |
1 | 3joed16 | https://test.com/3joed16 |
2 | 8lop31w | https://test.com/8lop31w |
3 | l6o3k1n | https://test.com/l6o3k1n |
4 | leo2418 | https://test.com/leo2418 |
Как обрабатывается большое число обращений
Библиотеку Hashids можно использовать для распределённой генерации сокращённых ссылок. Входящее значение для
Hashids – число типа long
или его аналог в используемом языке программирования. На основании переданного числа генерируется уникальный токен. Чтобы управлять диапазоном передаваемых чисел, можно использовать, например, инструмент Zookeeper.
Каждый узел распределённой системы при запуске запрашивает у Zookeeper новый диапазон чисел. При создании новой короткой ссылки сокращательный софт увеличивает порядковый номер (исходя из диапазона Zookeeper) и передаёт его в Hashids, и библиотека генерирует уникальный токен. Этот токен, как и ранее, сохраняется в БД вместе с полным URL.
Как только узел исчерпает диапазон чисел, он запрашивает у Zookeeper новый интервал. Такая архитектура позволяет добавлять любое количество нод приложения, обслуживающих входящий трафик.
Роль Zookeeper заключается в управлении диапазонами, которые уже назначены или запрошены для назначения. Переменная со счётчиком является атомарной, таким образом, любая нода приложения, работающая на чтение и запись не конфликтует с другими.
Атомарные счётчики можно реализовать и с помощью DynamoDB, MySQL или любой другой СУБД, поддерживающей работу с атомарностью, например, Redis.
Полная схема работы
Примечание: на диаграмме добавлен кэш для повышения производительности приложения, поскольку недавно созданными укороченными URL можно управлять из кэша, а не ходить каждый раз в БД. Записи в кэше могут быть переконфигурированы по истечении срока действия.
Итак, полная схема работы простого сокращателя ссылок:
- Сокращательный софт работает в кластере. Всякий раз, когда ноды запускаются или добавляются в кластер, они обращаются к Zookeeper.
- Zookeeper по запросу выделяет уникальный диапазон номеров для каждой ноды.
- Запрос на сокращение URL поступает к балансировщику нагрузки, который делегирует работу нодам приложения.
- Приложение проверяет, существует ли запись соответствия длинного URL короткому в базе данных или кэше. Если существует и если короткий URL всё ещё действителен, то возвращается
HTTP 200 OK
. - Если длинного URL нет в базе данных, то приложение использует следующий доступный номер из диапазона, выделенного Zookeeper на шаге 2, и генерирует новый токен в библиотеке Hashid. С помощью токена создаётся короткий URL, а вся сопутствующая информация сохраняется в базу данных. Короткий URL отправляется обратно клиенту со статусом
HTTP 201 CREATED
. - При каждом щелчке по короткому URL-адресу запрос снова попадает к балансировщику и передаётся свободной ноде для сокращения адреса.
- Приложение проверяет, имеется ли длинный URL в кэше. Если да, то переходит к шагу 9, если нет – к десятому шагу.
- Если в кэше запись отсутствует, приложение проверяет базу данных. Если там запись есть, переходит к шагу 9, а если нет – к десятому шагу.
- После нахождения длинного URL, на который клиент должен быть перенаправлен, приложение отвечает
HTTP 302
с длинным URL-адресом. Это действие перенаправляет клиента из короткого URL на фактическое местоположение искомой страницы. - Если ни в кэше, ни в БД токен не найден, нода отвечает со статусом
HTTP 404 NOT FOUND
.
Дополнительный технический раздел: как Библиотека программиста обрабатывает сокращённые ссылки
В Библиотеке программиста после выхода очередной публикации автоматически для каждой из социальных сетей создаётся собственная сокращённая ссылка.
Наш обработчик сокращённых ссылок написан на php. Для новой статьи создаётся сущность Transition
, которая содержит переходы из каждой платформы. У неё есть длинная ссылка на статью, уникальный токен, количество переходов, название платформы и время последнего перехода, не считая остальных служебных полей вроде id.
В приложении есть специальный эндпоинт, отвечающий за обработку переходов по сокращённым ссылкам. Поскольку наше приложение написано на Symfony, у нас есть встроенный ParamConverter
, который достаёт из маршрута токен и с помощью метода findOneBy()
и передаёт в качестве аргумента в наш action click
сущность Transition
.
Далее мы передаём сущность в команду Click\Command
, отдаём обработчику команды и делаем редирект на статью.
Команда – это простая структура данных, которая представляет текущий запрос пользователя.
В обработчике команды мы вызываем метод click
, передавая туда текущую дату в качестве даты последнего перехода, и вызываем flush
, который выполнит запрос в базу данных на обновление кликов.
Так мы учитываем, что пост с публикацией дошёл до каждой из платформ, и знаем, какая статья больше заинтересовала определенную аудиторию, и учитываем в дальнейшей работе над ресурсом.
Комментарии