Системный аналитик

Курсы по REST API: учимся проектировать микросервисы, валидировать запросы и тестировать нагрузку. Паттерны, антипаттерны и боль SOAP в legacy-банках

Stateless и Statefull на пальцах

stateful и stateless на пальцах

Скучная теория:

В RestAPI интеграциях есть основные принципы, один из них — это stateless принцип. В скучной теории, определение этого принципа гласит, что stateless в клиент- серверной архитектуре — это когда сервер не хранит информацию о состоянии клиента. Но что это значит в техническом плане? Как препарировать это простое определение?

В своих объяснениях, я пытаюсь объяснить stateless в сравнении с statefull. Однако statefull не является принципом RestApi.

Объяснение 1 — видео

Я записал небольшое видео, делая акцент на объяснении принципа из офлайна. На примере заказа пиццы: VK и Youtube?

Объяснение 2 — код

Stateful

В нашем примере Stateful состояния, мы (клиенты) будем передавать на ручку /stateful (сервера) запрос.
По определению — stateful — хранит состояние клиента, то есть сервер должен хранить наше состояние. В качестве нашего состояния, мы будем хранить кол-во наших вызовов на эту ручку.
Посмотрите на код ниже:

// Stateful endpoint
@Get('stateful')
getStateful(@Req() req: Request): string {
    // Получаем IP-адрес клиента (упрощённо для демонстрации)
    const clientIP = req.ip;

    // Инициализируем счётчик клиента, если он не существует
    if (!this.clientCounts[clientIP]) {
        this.clientCounts[clientIP] = 0;
    }

    // Увеличиваем счётчик для этого клиента
    this.clientCounts[clientIP] += 1;

    // Возвращаем текущий счётчик клиента
    return `Stateful: Вы выполнили ${this.clientCounts[clientIP]} запросов.`;
}
Code language: JavaScript (javascript)
  • Строка 5 — сохраняет ваш IP в переменной памяти ( мы ведь stateful )
  • Строка 13 — прибавляет к каждому вызову +1
  • Строка 16 — выводит результат

То есть, в этом коде демонстрируется stateful состояние: поскольку кол-во запросов с вашего IP хранится в памяти сервера (сервер хранит состояние).
Если я перезагружу сервер, то память обнулится и кол-во запросов снова будет начинать с 0.

Посмотрите как это работает:

Stateless

В отличии от stateful, здесь сервер не сохраняет состояние (каждый запрос изолирован). То есть для сервера ваш клиентский запрос в ручку /stateless будет всегда, как новый. Поскольку он не использует память, как ячейку для хранения состояния. Это и есть один из основных принципов RestApi.
Посмотрим на код ниже:

 // Stateless endpoint  
 @Get('stateless')
  getStateless(@Query('count') count: string): string {
    // Парсим значение count из параметра запроса (по умолчанию 0, если не указано)
    const currentCount = parseInt(count) || 0;
    const newCount = currentCount + 1;

    // Возвращаем обновлённое значение счётчика
    return `Stateless: Вы выполнили ${newCount} запросов. Отправьте ?count=${newCount} в следующем запросе.`;
  }
Code language: JavaScript (javascript)
  • Строка 3 — получает переменную из query параметра : count (/stateless?count=1)
  • Строка 6 прибавляет +1 к счётчику (по аналогии строки 13 в stateful)
  • Строка 9 — выводит результат

Возможно, вы не понимаете, а какая разница по коду?
И там и там есть переменные, которые хранятся в памяти. Почему тогда это тоже stateless, если мы так же храним состояние в памяти?

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

Посмотрите ниже как это работает: