Поисковые и фильтрующие эндпоинты десятилетиями жили в неудобном углу HTTP. GET семантически правильный — безопасный, идемпотентный, кэшируемый — но упаковка сложного фильтра в query-string упирается в лимиты длины, боль с кодированием и логи, полные чувствительных параметров. Поэтому все берут POST — и взамен отдают безопасность и кэширование.
Ответ IETF — метод QUERY: безопасный, как GET, но с телом запроса, как у POST. Поисковые API в стиле Elasticsearch, фильтрующие эндпоинты рядом с GraphQL, отчётные запросы — это метод, которого они ждали.
По мере того как фреймворки и шлюзы выкатывают поддержку, эти эндпоинты понадобится нагружать, как и любые другие. Поэтому QUERY теперь работает во всём стеке perfscale — рядом с GET, POST, PUT и остальными.
В perfscale CLI (нативный движок)
Нативный YAML-движок пропускает любой валидный токен метода как есть, вместе с телом:
steps:
- name: поиск по товарам
use: std/http@v1
with:
method: QUERY
url: https://api.example.com/products/search
body:
category: "electronics"
price_max: 500
check:
status: 200
Запуск обычный:
perfscale run -f search.test.yaml -c load.yaml
Перцентили латентности, RPS и доля ошибок попадают в тот же summary http_req_*, что и у любого другого метода — дашбордам и пайплайну --report всё равно, что метод нестандартный.
В k6-скриптах
У модуля http в k6 нет шортката http.query(), но http.request() принимает метод первым аргументом:
import http from 'k6/http';
export default function () {
http.request('QUERY', 'https://api.example.com/products/search',
JSON.stringify({ category: 'electronics', price_max: 500 }),
{ headers: { 'Content-Type': 'application/json' } });
}
Это работает и с чистым k6, и через perfscale run --k6. Редактор тестов в controlplane теперь тоже разбирает вызовы http.request(), так что QUERY-шаг появляется в превью нативных шагов наравне с шорткатами.
В агенте perfscaled
Эндпоинт нативных шагов агента принимает те же определения по HTTP, так что оркестрируемые флоты получают QUERY бесплатно:
POST /api/v1/run/steps
{
"steps": [
{ "name": "search",
"use": "std/http@v1",
"with": { "method": "QUERY",
"url": "https://api.example.com/products/search",
"body": { "category": "electronics" } },
"check": { "status": 200 } }
],
"config": { "vus": 50, "duration": "5m" },
"mode": "stream"
}
Почему это важно для нагрузочного тестирования
QUERY меняет профиль производительности поисковых эндпоинтов — и лучше измерить это до того, как это сделает продакшн:
- В игру вступает кэширование. Ответы QUERY кэшируемы; нагрузочный тест, игнорирующий поведение кэша, переоценит нагрузку на origin.
- Тело у безопасного метода проходит через прокси, шлюзы и WAF, которые так никогда не работали. Некоторые под нагрузкой поведут себя странно — лучше узнать об этом во вторник днём на стейджинге.
- Серверные фреймворки маршрутизируют QUERY через generic-обработчики, пока не появится первоклассная поддержка, — а это зачастую другие цепочки middleware и другая латентность, чем у
GET.
Направьте QUERY-сценарий на свой staging-шлюз, прогоните свип по VUs и сравните перцентили с эквивалентным POST. Если цифры разойдутся — вы знаете, куда смотреть.
Всё описанное уже в текущем main perfscale — без флагов и конфигурации. Просто напишите method: QUERY.
