Горизонтальное масштабирование и stateless-аутентификация

bcrypt.js используется для криптографического хэширования паролей на стороне Node.js и является одним из ключевых инструментов при построении систем аутентификации, которые должны корректно работать в условиях горизонтального масштабирования.

Основная задача библиотеки — преобразование пароля в необратимый хэш с использованием адаптивной функции стоимости (cost factor), которая регулирует вычислительную сложность операции.

= 2^{}

Увеличение значения cost factor экспоненциально повышает время вычисления хэша, что напрямую влияет на устойчивость к перебору, но одновременно увеличивает нагрузку на CPU при аутентификации пользователей.

Влияние bcrypt.js на горизонтальное масштабирование

В распределённой архитектуре приложение обычно разворачивается на нескольких экземплярах (инстансах), за балансировщиком нагрузки. Каждый инстанс выполняет одинаковую бизнес-логику, включая операции регистрации и входа.

bcrypt.js полностью локален и не требует внешнего состояния, что делает его совместимым с горизонтальным масштабированием. Однако его вычислительная стоимость становится критическим фактором:

  • операция hash() при регистрации создаёт нагрузку на CPU
  • операция compare() при логине выполняет дорогостоящее сравнение хэшей
  • увеличение трафика напрямую увеличивает CPU usage на всех инстансах

В системах с высокой нагрузкой bcrypt становится не узким местом хранения, а узким местом вычислений.

Stateless-аутентификация и bcrypt.js

Stateless-аутентификация означает отсутствие серверного хранения сессий. Вместо этого используется токен (чаще всего JWT), который содержит информацию о пользователе и подписывается сервером.

bcrypt.js в такой архитектуре используется только на этапе:

  • регистрации (создание хэша пароля)
  • аутентификации (проверка пароля через сравнение)

После успешного входа сервер не хранит состояние пользователя, а доверяет токену.

Разделение ответственности

  • bcrypt.js: защита пароля
  • JWT: перенос состояния между запросами
  • база данных: хранение хэшей паролей

Это разделение критично для масштабируемости: ни один из инстансов не зависит от локальной памяти или общей сессии.

Особенности bcrypt в распределённой среде

1. Отсутствие общего состояния

bcrypt не требует синхронизации между серверами. Один и тот же пароль всегда даёт один и тот же результат при одинаковых параметрах salt и cost factor.

H = (P, S, c)

где:

  • P — пароль
  • S — соль
  • c — cost factor
  • H — хэш

Это свойство позволяет свободно масштабировать backend без дополнительных механизмов координации.

2. CPU-bound характер операций

bcrypt специально разработан как медленный алгоритм. Это означает, что при увеличении количества инстансов линейного ускорения может не происходить, если нагрузка упирается в вычисления.

Типичная проблема в масштабируемых системах:

  • увеличение числа пользователей → рост запросов login
  • каждый login вызывает bcrypt.compare
  • CPU загружается независимо на каждом узле

3. Влияние cost factor на масштабирование

T ^{c}

где:

  • T — время вычисления
  • c — cost factor

Даже небольшое увеличение cost factor резко увеличивает задержки, что в распределённой системе проявляется как рост p95/p99 latency.

bcrypt.js и балансировка нагрузки

В системах с горизонтальным масштабированием балансировщик распределяет запросы между инстансами. bcrypt.js не влияет на маршрутизацию, но влияет на:

  • время ответа инстанса
  • вероятность перегрузки отдельных узлов
  • необходимость autoscaling

При росте нагрузки узлы начинают деградировать не из-за базы данных или сети, а из-за CPU-bound операций сравнения хэшей.

Stateless JWT и отсутствие сессий

Использование JWT устраняет необходимость хранить сессии, что упрощает масштабирование:

  • любой инстанс может обработать запрос
  • нет зависимости от sticky sessions
  • нет общего session store (Redis и аналогов)

bcrypt.js в этой модели выполняет только роль первичной проверки, не участвуя в дальнейшей идентификации пользователя.

Комбинация bcrypt.js и JWT в масштабируемой архитектуре

Типичный поток аутентификации:

  1. пользователь отправляет логин и пароль
  2. сервер выполняет bcrypt.compare
  3. при успехе создаётся JWT
  4. клиент хранит JWT и отправляет его в каждом запросе
  5. сервер проверяет подпись JWT без обращения к bcrypt

Ключевая особенность: bcrypt участвует только в начале сессии, а не в каждом запросе.

Узкие места и характер нагрузки

В масштабируемых системах bcrypt создаёт специфический профиль нагрузки:

  • пики CPU при логинах
  • задержки при массовых регистрациях
  • непредсказуемая латентность при DDoS на endpoint авторизации

Проблема усиливается при использовании высоких cost factor, особенно в системах с ограниченными ресурсами контейнеров.

Практическая модель поведения в кластере

При увеличении количества инстансов:

  • throughput системы растёт линейно до момента CPU saturation
  • latency логина остаётся стабильной до достижения лимита CPU
  • после насыщения появляются очереди на выполнение bcrypt операций

Таким образом, масштабируется не bcrypt, а количество параллельных CPU-ресурсов, необходимых для его выполнения.

Роль соли и уникальность хэшей

bcrypt автоматически генерирует соль для каждого пароля, что делает невозможным использование радужных таблиц.

H_1 H_2 ; }

Это свойство обеспечивает безопасность даже в распределённых системах, где база данных может быть реплицирована между регионами или дата-центрами.

Итоговое поведение в stateless-архитектуре

bcrypt.js органично вписывается в stateless-модель:

  • не хранит состояние
  • не требует синхронизации
  • работает одинаково на любом узле

Основная стоимость переносится в CPU-вычисления, что делает масштабирование задачей управления ресурсами, а не архитектурной согласованности.