Задача «давайте нагрузим endpoint» выглядит короткой, пока через неделю не приходится объяснять, что именно проверяли. Один человек помнит счётчик запросов, другой — иной набор данных, третий — другую конфигурацию. Цена такой экономии не в плохом графике. Команда получает число без причины: по нему нельзя решить, менять код, окружение или сам сценарий.
Перед инструментом я бы зафиксировал workload на одной карточке. В этой заметке это учебная in-memory модель для GET /fixture/neutral-resource. Она не отправляет HTTP, не запускает generator, сервер, базу или сеть. planned request slots, accepted units и rejected units здесь — только заданные единицы плана. Они не означают RPS, миллисекунды, пользователей, latency, throughput или реальную ёмкость.
Карточка workload отвечает на пять вопросов
Первый вопрос — какой контракт проверяем. Не «каталог вообще», а нейтральное намерение чтения, метод, путь и ожидаемая граница результата. Второй — кто владеет данными: откуда берётся fixture record, изменяется ли он и как узнать его версию. Третий — где выполняется проверка. Слово «стенд» бесполезно, пока не записаны конфигурация, версия, внешние зависимости и ограничение, которое сценарий обязуется не пересекать молча.
Четвёртый вопрос — как профиль меняется по сегментам. Warm-up, steady, step и recovery нужны не как красивые английские подписи. У каждого есть роль: до основного шага проверить карточку, удержать повторяемый план, показать заранее смоделированную границу и вернуть модель к малому плану. Пятый вопрос — когда остановиться. Если критерий не объявлен заранее, остановка выбирается после того, как кому-то понравилось или не понравилось число.
| Поле карточки | Пример в учебной fixture | Проверка | Не является |
|---|---|---|---|
| Endpoint intent | GET /fixture/neutral-resource | путь и метод совпадают во всех сегментах | HTTP-вызовом или существующим сервисом |
| Среда | isolated-training-envelope-v1 | есть identity, режим и явное ограничение | описанием production или capacity |
| Данные | training-data-v1 | fixture record фиксирован, mutation отсутствует | копией пользовательских данных |
| Профиль | warm-up → steady → step → recovery | последовательность и slots сохранены в packet | одним общим количеством запросов |
| Критерий остановки | recovery evidence after synthetic bottleneck | модель останавливается только после recovery | таймаутом или сигналом настоящей системы |
Профиль — это переходы, а не один большой счётчик
Внутри fixture каждый сегмент хранит массив planned request slots. Это полезнее одного total: можно увидеть, какой слот принадлежит warm-up, какой — step, и где появились rejected synthetic units. При declared limit в три accepted units step содержит пять slots; два из них модель помечает rejected. Такое расхождение не доказывает перегрузку. Оно заранее создано, чтобы увидеть, что evidence packet умеет хранить и план, и результат его учебной границы.
Steady не обязан быть «нормой», а step не обязан быть «пиком» настоящей нагрузки. Это названия ролей в документе. Если в реальном тесте их смысл другой, карточку переименовывают и рядом объясняют почему. Хуже оставить привычные слова, но не записать вход, data setup и переход. Тогда reader видит форму графика, а автор не может ответить, изменилось ли приложение, данные или только generator.
Среда и data setup — часть результата
Среда в карточке — не колонка «dev» или «stage». Нужны identity и ограничение: например, «in-memory evaluation, внешней системы нет, за один segment принимается не больше трёх synthetic units». Такое условие не похоже на реальный лимит, и это хорошо: его нельзя случайно перенести в конфигурацию. Оно заставляет автора назвать, что именно сравнивается, и запрещает потом объяснять результат неизвестным сервером.
Data setup тоже не прячется за словом «тестовые данные». Для операции чтения достаточно назвать fixture record, его версию и правило неизменности. Для операции изменения понадобились бы начальное состояние, очистка, idempotency и проверка результата, но их нельзя домыслить к нейтральному чтению. Если данные меняются между сегментами, это отдельная гипотеза и отдельный evidence packet, а не параметр, затерянный в shell history.
Критерий остановки защищает расследование
В учебной модели stop criterion требует четыре факта: сегменты прошли по порядку, только step получил synthetic bottleneck flag, accepted плюс rejected units равны количеству slots, а recovery записан в packet. До этого состояния модель не называет себя завершённой. В реальном инструменте критерий может быть другим, но ему всё равно нужна наблюдаемая формулировка: какая граница остановит сценарий, какие данные будут сохранены и кто решит, что запуск повторять нельзя.
Критерий не заменяет проверку качества. Он отделяет два вопроса. Сначала: «достаточно ли evidence, чтобы прочитать именно этот сценарий?» Потом: «соответствует ли наблюдение договорённости?» Если первый вопрос не закрыт, нельзя честно переходить ко второму. Поэтому bare counter «много запросов» в fixture отклонён: у него нет endpoint intent, среды, данных, последовательности, criterion и packet.
Минимальный пример: прочитать модель, не запускать benchmark
Ниже пример не обращается к адресу из endpoint intent. Он импортирует функцию из revision-модуля, выводит already-materialized objects и проверяет объявленный criterion. Такой пример нужен для редакционной проверки: любой change в profile, который спутал порядок сегментов или назвал units latency, должен разрушить assertion до интеграции статьи.
import { runLoadTestingFixture } from "./upgrade-2021-11.mjs";
const fixture = runLoadTestingFixture();
console.table(fixture.evidencePacket.profile.map((segment) => ({
segment: segment.name,
plannedSlots: segment.plannedRequestSlots.length,
acceptedUnits: segment.acceptedUnits,
rejectedUnits: segment.rejectedUnits,
syntheticBottleneck: segment.syntheticBottleneckFlag,
})));
if (!fixture.assertions.stoppedByDeclaredCriterion) {
throw new Error("fixture did not reach its declared stop criterion");
}
// Synthetic units are not latency, throughput, RPS, users or capacity.
Важная деталь — comment в конце. Она не декоративная: exact boundary повторяется в объекте каждого segment и в assertions. Если в будущем кто-то добавит поле latency, throughput или rps в эту модель, assertion станет false. Для реального измерения лучше создать другой артефакт с источником времени, версией инструмента и условиями запуска, чем тихо расширить учебную fixture.
Evidence packet должен пережить разговор через неделю
После описания профиля сохраняем не только результат. Packet несёт endpoint intent, environment, data setup, profile records, stop criterion, stop state и diagnostic labels. Этого достаточно, чтобы коллега проверил порядок размышления: почему step виден отдельно, почему recovery обязателен и почему rejected units нельзя выдать за error rate. Это ещё не raw result инструмента. Но это минимальный договор, без которого raw result тоже быстро теряет смысл.
Историческая рамка здесь намеренно скромная. В релизе k6 v0.35.0 от 17 ноября 2021 года есть работа с stage tags и сценариями; sample того же тега показывает пороги, связанные с именованными метриками. Из этого следует только практическое правило: инструмент и метрика должны быть названы вместе. Fixture не использует k6 и не делает вывод о его executor semantics. OpenTelemetry v1.0.0 полезен как напоминание, что измерению дают явный смысл; в том снимке Metrics API всё ещё experimental.
Маршрут: симптом → причина → проверка → действие
- Симптом. В обсуждении есть лишь «много запросов» или один total, а по нему уже предлагают менять endpoint.
- Причина. Workload не отделён от среды, data setup и условия завершения; разные запуски невозможно сравнить по одному договору.
- Проверка. Выпишите endpoint intent, среду с ограничением, версию данных, четыре сегмента и criterion. Проверьте, что planned slots раскладываются на accepted/rejected units.
- Действие. Сначала исправьте карточку и сохраните evidence packet. Инструмент выбирайте после того, как стало понятно, какую реальную величину и на какой версии среды он должен собирать.
- Повторная проверка. Если изменились среда или данные, дайте новому запуску новую identity. Не сравнивайте его с прежним только по форме графика.
- Ожидаемый результат. У команды остаётся сценарий, который можно прочитать и воспроизвести как договорённость, не выдавая учебные units за benchmark.
Ограничения и следующий проверяемый шаг
Эта fixture не моделирует HTTP status, DNS, TLS, соединения, очередь процесса, scheduler, clock, нагрузочный generator, database, cache, данные пользователя, concurrency, latency, throughput, error rate, capacity, пользователей или production incident. Rejected unit означает только, что planned slot не прошёл заданный synthetic limit. Он не говорит, почему реальная система могла бы вернуть ошибку и не обещает, что реальная среда выдержит иной сценарий.
Следующий проверяемый шаг в своём проекте — не копировать числа из модели, а оформить такую же карточку для одного настоящего endpoint: выбрать инструмент версии, существовавшей на дату работы, записать его конфигурацию, среду, data setup, вход, критерий остановки и место хранения raw output. Лишь после этого имеет смысл запускать отдельный реальный тест. Учебная модель помогает не потерять вопрос до такого запуска, но не заменяет его.
Проверяемые источники
- Grafana k6 v0.35.0: versioned release record — релиз опубликован 17 ноября 2021 года; он задаёт историческую верхнюю границу для упоминания инструмента и не является результатом прогона этой fixture
- Grafana k6 v0.35.0: fixed source snapshot samples/thresholds.js — точный commit, на который указывает тег v0.35.0; пример связывает порог с именованной метрикой, а пакет не импортирует k6 и не исполняет его
- OpenTelemetry Specification v1.0.0: fixed Metrics API snapshot — снимок от февраля 2021 года помечает Metrics API как experimental и отдельно описывает смысл измерения, instrument и aggregation; fixture не реализует OpenTelemetry
- OpenTelemetry Specification v1.0.0: fixed Trace API snapshot — исторический документ для терминов trace и span; evidence packet в этой статье является локальным object, а не экспортированной трассой
- RFC 2330: Framework for IP Performance Metrics — нормативная рамка для аккуратного определения измеряемого свойства; RFC относится к IP-метрикам и не превращает учебный endpoint в capacity benchmark