Производительность27 июля 2026 г. · 6 мин чтения

Нагрузочное тестирование gRPC стало нативным — стриминг, message RTT, ноль кодогенерации

perfscale v0.7.0 приносит семь встроенных gRPC-actions: динамические схемы из server reflection или descriptor set, payload'ы в JSON, unary и все три формы стриминга, честная метрика message-RTT. Бесплатно для всех, в open-source-движке.

Автор: Команда Perfscale

Нагрузочное тестирование gRPC стало нативным — стриминг, message RTT, ноль кодогенерации

Ваши сервисы наверняка говорят между собой на gRPC — а ваш инструмент нагрузочного тестирования, скорее всего, нет.

HTTP/2-фрейминг, бинарный protobuf-формат на проводе, схемы, запертые в .proto-файлах, и четыре формы RPC (unary плюс три вида стриминга) делают gRPC протоколом, на который большинство нагрузочных инструментов лишь разводит руками. Встроенный клиент k6 останавливается на unary-вызовах — для стримов нужны расширения; JMeter нужны плагины; и оба пути заканчиваются одинаково: protobuf-кодогенерацией в вашем тестовом пайплайне, сгенерированными стабами, вечно отстающими от сервера на версию, и отсутствием честного способа измерить стрим.

Начиная с v0.7.0, perfscale гоняет gRPC нативно. Семь actions std/grpc* живут в open-source-движке, рядом со std/http, std/tcp, std/udp и std/ws*. И как WebSocket, gRPC бесплатен для всех — actions, динамический загрузчик схем и метрики лежат в OSS-репозитории под двойной лицензией MIT/Apache-2.0.

Никакой кодогенерации, никаких стабов, никакого рассинхрона

Обычно больше всего болит схема. Классические инструменты хотят, чтобы вы запустили protoc, сгенерировали клиентские стабы и вечно держали их в синхроне с сервером. perfscale пропускает всё это: вызовы динамические. Схема приходит в рантайме — либо из reflection-сервиса сервера, либо из base64 FileDescriptorSet, который вы собрали один раз, — а payload'ы — обычный JSON, маппящийся по стандартным правилам protobuf-JSON.

На опечатку в "package.Service/Method" движок отвечает подсказкой «возможно, вы имели в виду…». Битый descriptor set падает сразу, до любого сетевого I/O. Ничего не надо генерировать, коммитить или поддерживать.

Стриминг — первоклассный

std/grpc-connect@v1 открывает живой HTTP/2-канал, который доживает до конца итерации. Unary-вызовы (std/grpc-call@v1) и стримы едут по тому же соединению, так что коннект и загрузка схемы оплачиваются раз на итерацию, а не на вызов.

Дальше std/grpc-stream-open@v1 открывает client-streaming, bidi или server-streaming вызов; std/grpc-stream-send@v1 шлёт сообщения — repeat + interval_ms превращают один шаблон в поток, токены ${seq}, ${uuid}, ${rand}, ${choice} раскрываются на каждую отправку; std/grpc-stream-recv@v1 читает до стоп-правила; std/grpc-stream-close@v1 делает half-close и дочитывает до финального статуса.

Метрики, которые что-то значат

Стриминг ломает модель «запрос/ответ», на которую рассчитано большинство метрик задержки. Поэтому perfscale сообщает четыре gRPC-серии:

  • grpc_req_duration — гистограмма латенси unary-вызовов.
  • grpc_msg_rtt — application-level RTT сообщения. На unary-вызове равен длительности запроса; на стриме это время от отправки до совпавшего ответа — записывается, только когда сработало ваше until-правило, поэтому p95 что-то значит.
  • grpc_msgs_sent / grpc_msgs_received — обычный throughput сообщений.
  • grpc_req_failed — RPC, не удовлетворившие expect_status.

gRPC-шаги никогда не протекают в http_req_duration. Серии grpc_* — это вся история, и они стоят в той же сводке рядом с перцентилями HTTP/TCP/UDP/WebSocket.

Тот же YAML, масштаб платформы

Всё вышеописанное работает из CLI уже сегодня. В репозитории лежит готовый examples/grpc.test.yaml плюс локальный echo-сервер с reflection, так что первый прогон занимает минуты.

Тот же YAML без изменений работает на платформе: распределённые машины подают нагрузку, прогон автоматически распознаётся как gRPC, и дашборд переключается на gRPC-плитки — скорости отправки/приёма, счётчики сообщений, перцентили message-RTT, перцентили длительности вызова. Тест как есть встаёт в CI через GitHub Action или шаблоны GitLab CI.

С чего начать

Если ваш service mesh плавится на пике — лучше узнать об этом из YAML-файла, чем от дежурного.

Комментарии

Ответить в Bluesky