Перейти к содержанию

Практикум: клиентские интерцепторы gRPC и потоковые RPC

Воркер выгрузок вызывает настоящий локальный сервис отчётов. Проверяем регистрацию интерцепторов, результат потокового вызова, контекст и завершение работы. Пример к статье «Почему интерцепторы gRPC ломаются на потоковых RPC».

Запуск

Установите uv и запустите команды из корня репозитория сайта. При необходимости uv загрузит Python и зависимости. RPC используют только локальный адрес и автоматически выбранный порт.

cd docs/blog/lab/2026-09-07-grpc-interceptors-and-streams
uv run --no-project --python 3.13 --with-requirements requirements.txt python interceptors_lab.py
uv run --no-project --python 3.13 --with-requirements requirements.txt python probe.py

Зафиксированы grpc-client-kit==0.4.0, grpcio==1.84.0; используется Python 3.13. Байтовые сообщения и обычные обработчики позволяют обойтись без генерации protobuf-кода. Здесь проверяется поведение клиентских интерцепторов; это не замер производительности и не конфигурация развёртывания.

Проверки

Сценарий Что должно выполняться
Один объект с четырьмя базовыми классами В этой версии grpcio запускается только unary-unary
Один логический интерцептор, четыре адаптера Каждый вид RPC создаёт одну запись об успешном результате
Таймер вокруг continuation Действительно запускается, заканчивает до первой строки и пропускает ошибку сервера, которая приходит позже
Таймер вокруг итерации Учитывает ошибку посреди потока; сохраняет статус, детали и завершающие метаданные
Библиотечный наблюдатель Пять строк при успехе; две строки и UNAVAILABLE при сбое
Досрочный выход Явная отмена останавливает серверный обработчик и даёт одну запись CANCELLED
break без отмены Удерживаемый вызов остаётся активным до явной отмены
Быстрый поток Наблюдатель может завершиться до продолжения итерации после последней строки
Потоковый запрос через write() После done_writing() приходит ответ; интерцептор не блокирует отправку
Область действия контекста Токен сбрасывается для всех четырёх видов RPC; контекст вызывающего кода не меняется
RuntimeError при завершении интерцептора Четыре успешных вызова и один UNAVAILABLE сохраняют результат; пять сбоев попадают в лог

Оба скрипта завершаются с ошибкой при нарушении утверждения или необработанной ошибке asyncio. Завершение ожидается через очереди и события с таймаутами, без подбора пауз. Задержки на сервере имитируют подготовку строк; длительности печатаются для сравнения и могут меняться между запусками.

Файлы

  • report_service.py: четыре обработчика RPC, сценарии сбоя и отмены, запуск и остановка сервера.
  • observers.py: обычные и логические интерцепторы из статьи.
  • consumer.py: полная загрузка и контекст потребителя с отменой при досрочном выходе.
  • interceptors_lab.py: потоковые сценарии и проверка интерфейса вызова.
  • probe.py: изоляция контекста и логирование ошибок завершающего кода.
  • requirements.txt: точные версии библиотек.

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