TGStat
TGStat
Введите текст для поиска
Расширенный поиск каналов
  • flag Russian
    Язык сайта
    flag Russian flag English flag Uzbek
  • Вход на сайт
  • Каталог
    Каталог каналов и чатов Региональные подборки Тематические подборки Платные каналы Поиск каналов
    Добавить канал/чат
  • Рейтинги
    Рейтинг каналов Рейтинг чатов Рейтинг публикаций
    Рейтинги брендов и персон
  • Аналитика
  • Поиск по публикациям
  • Мониторинг Telegram
  • Продвижение
    Реклама через Яндекс Бизнес Реклама в каналах через TGStat Agency Реклама на сайте TGStat.ru
.NET sh blog

4 Feb 2025, 20:42

Открыть в Telegram Поделиться Пожаловаться

Немного про CancellationToken.

Основная её цель - иметь источник уведомлений о том, что результат работы которую выполняет ваш API или метод больше никто не ждет. Грустно, но такое бывает.

Начну чуть издалека :)

Существует миф что сеть стабильна. Но это не так. К тому же сейчас очень многие применяют микросервисную архитектуру, которая намного более интенсивно использует сеть. А значит больше точек отказа.
Еще обычно всё хостится в k8s, что еще больше усложняет топологию и перед вашим микросервисом может быть 5-6 балансировщиков и прокси, а то и больше :)

Типичный маршрут запроса в микросервис который расположен допустим в Yandex Cloud Managed k8s:

Yandex Network LoadBalancer -> k8s gateway / ingress -> k8s service -> ApiGateway -> k8s service -> ваш микросервис

Перед всем этим можно еще подключить защиту от DDoS (в виде еще одного прокси).
Часто еще делают AuthN/AuthZ прокси перед ApiGateway.. или еще Service Mesh.
Помимо этого в компании могут быть еще общие внешние балансировщики и вполне вероятно что даже и не один.

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

Как HTTP отменяет запросы?
HTTP/1.x - клиент просто закрывает TCP соединение
HTTP/2 - отправляет фрейм RST_STREAM, чтобы отменить запрос (стрим), но не закрывать соединение.
HTTP/3 - аналогично HTTP/2

Если погрузиться в исходники Kestrel, можно найти обработку этих ситуаций и вызов CancellationTokenSource.Cancel(),
CancellationToken которого пробрасывается в HttpContext.RequestAborted или в параметр экшена контроллера.

Нам надо только пробросить его дальше в наши методы и обязательно туда где есть IO операции или тяжелые CPU bound задачи.
Например HTTP, запросы в бд, чтение файлов. Чтобы если такая ситуация произойдет, мы могли отменить тяжелые операции и быстро освободить ресурсы на что-нибудь полезное.

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

Бывало ли у Вас такое, что вы отправляете во внешнюю систему POST запрос на создание ресурса, ловите таймаут, делаете ретрай с помощью Polly, а потом внезапно обнаруживаете, что создалось 2 (или более) ресурсов, вместо одного.

Такое часто возникает когда в API не предусмотрели отмену запроса. Или если запрос был прерван по другой причине и Вы не успели прочитать успешный ответ от сервера и сделали повторный запрос.

Эта проблема решается реализацией идемпотентности, о котором я расскажу в следующий раз.

Так вот я провел бенчмарк, на простых HTTP эндпойнтах, которые просто ждут 1 секунду и отдают 200 OK. В одном используется CancellationToken, а в другом нет.

Сетап бенчмарка простой - 250VUs, 1 сек sleep между итерациями.
Каждую итерацию отправляется запрос и отменяется спустя случайное кол-во мс (от 1 до 600).
Так как тестируемый эндпойнт выполняется минимум 1000 мс, то все запросы гарантированно завершаются ошибочным ответом (499).

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

'https://t.me/sh_dotnet/103?comment=334' rel='nofollow'>Первый - эндпойнт который корректно отменяет запрос
'https://t.me/sh_dotnet/103?comment=335' rel='nofollow'>Второй - эндпойнт который не отменяет запрос

Но больше всего интересно не с точки зрения клиента, а с точки зрения сервера.
В проекте BookLibrary у меня настроена сборка метрик с помощью OpenTelemetry, поэтому можно посмотреть как долго в итоге эти запросы отрабатывались, а значит тратили процессорное время.

Смотрим на 'https://t.me/sh_dotnet/103?comment=336' rel='nofollow'>http_server_request_duration_seconds_sum, это суммарное кол-во секунд которое затратил сервер в разбивке по эндпойнтам.

Первый - 596s / 2006 = 298 ms на один запрос
Второй - 2094s / 2000 =1047ms на один запрос т.е. здесь тратятся ресурсы значительно больше

Бенчмарки и 'https://t.me/sh_dotnet/103?comment=333' rel='nofollow'>доп. материал в комментариях.

529 0 9 11 20
Каталог
Каталог каналов и чатов Подборки каналов Поиск каналов Добавить канал/чат
Рейтинги
Рейтинг каналов Telegram Рейтинг чатов Telegram Рейтинг публикаций Рейтинги брендов и персон
API
API статистики API поиска публикаций API Callback
Наши каналы
@TGStat @TGStat_Chat @telepulse @TGStatAPI
Почитать
Академия TGStat Исследование Telegram 2019 Исследование Telegram 2021 Исследование Telegram 2023
Контакты
Справочный центр Поддержка Почта Вакансии
Всякая всячина
Пользовательское соглашение Политика конфиденциальности Публичная оферта
Наши боты
@TGStat_Bot @SearcheeBot @TGAlertsBot @tg_analytics_bot @TGStatChatBot