Browse Source

Document timestamp metrics and negotiated stream overload cuts

master
evgeny 2 days ago
parent
commit
f10078e482
  1. 63
      doc/stream.txt
  2. 10
      doc/tasks.md

63
doc/stream.txt

@ -370,8 +370,10 @@ Rate выдачи — её средний вклад в поступающую
Число выдач выбирается по их rates: закрываем достаточно выдач для требуемого сокращения;
при сильном росте это сразу несколько, не фиксированная одна и не случайное постоянное число.
OVERLOAD содержит request_id, расчётное число выдач и требуемое сокращение rate.
Получатель выбирает handles с учётом FEC и альтернативных поставщиков.
OVERLOAD содержит request_id, расчётное число выдач, требуемое сокращение rate и список handles с фиксированными rates.
Получатель выбирает handles с учётом FEC и альтернативных поставщиков и отправляет OVERLOAD_SELECT.
Отправитель исполняет выбор, только пока актуален исходный request_id, и сообщает CLOSED.
Получатель не отсоединяет выбранные handles до CLOSED: поздний SELECT после принудительного закрытия не режет дополнительные выдачи.
При разных rates одного количества закрытий недостаточно: суммарный снятый rate должен покрыть требование.
Rate закрываемых выдач фиксируется по оценке на момент запроса, чтобы условие исполнения не менялось на каждом тике.
Срок реакции — 2 секунды с первого запроса; повторы не сбрасывают срок и не начинают новое требование.
@ -544,9 +546,35 @@ Stop/destroy выполняются по правилам ядра, вне callb
Общий ./check.sh: 144 passed, 0 failed, 0 skipped; proxy/full (9/9), burst и load — PASS.
Лог: /tmp/stream-network-check.log (88 с).
[ ] Планировщик отправки и разгрузка:
одна очередь на пира, backpressure, ограничение памяти/возраста, A/D/X/Q,
подтверждение 500 мс, сокращение по g/rates и двухсекундный срок исполнения OVERLOAD.
[+] Метрики и разгрузка — 11.10.2026:
stream_load.c/h — баланс A/D/X/Q по packets/bytes для выдачи, пира и модуля;
интервалы >=200мс фактической длительности, история 10с, рост A-D за 1с до искусственных X.
Изменение состава выдач исключает смешанный интервал из роста и сбрасывает его подтверждение.
Кольцо сообщает только фактические вставки/вытеснения; повторный блок не создаёт A.
Списки субпотоков по времени вставки дают точный возраст ещё ожидающих блоков, в том числе вне порядка batch_seq.
Логическая DATA-очередь представлена курсорами и счетчиками: содержимое и история остаются в одном 32-МБ кольце.
Частные/общие метрики lag/rates/late/stops подключены к подписанным DATA; после END ожидание прекращается.
INFO содержит nonce пробы и 64-битный снимок метрик; RTT — uint32 мс с признаком неизвестного.
Условие перегрузки: ожидающая нагрузка старше 200мс и рост либо нулевой D;
непрерывное подтверждение — 500мс по монотонным часам, независимо от количества тиков.
Требуемое сокращение — g + 1% + 1 байт/с, с ограничением суммой доступных rates; при нулевом D — также оценка backlog/2с.
Rates фиксируются при создании OVERLOAD. Расчётное число — подсказка, исполнение проверяется по суммарному rate.
Получатель предпочитает закрытия, сохраняющие k с учётом других поставщиков, затем parity при равных условиях.
OVERLOAD_SELECT предлагает handles; source закрывает только актуальное требование, поздний/повторный выбор безопасен.
Срок 2с начинается с первого запроса и не меняется при повторе. Невыполненный остаток source закрывает сам.
Новые SUBSCRIBE не компенсируют разгрузку: запрет действует до исполнения и 500мс снятого давления;
stream_peer_get_load.accepting сообщает этот статус отдельно от request_active.
Глобальный бюджет включается только для backlog нескольких пиров вместе с CPU/опозданием callbacks;
CPU отдельно не отключает выдачи, уже запрошенное сокращение повторно не учитывается.
Control FIFO ограничена 128 кодограммами по 1094 байта, возрастом 4с и отменой неподтверждённых запросов.
Просроченные ожидающие DATA при активном OVERLOAD учитываются X и пропускаются явным GAP, кольцо не стирается.
Диагностика сообщает A/D/X/Q, age, input/output/g, длительность интервала, cpu/late callbacks,
frozen/released rates, request/deadline и нижние очереди/inflight; D остаётся принятием ETCP, а не доставкой.
test_stream_core: баланс, X отдельно от D, граница 500мс, глитч, смена состава, 10-секундное окно и широкие wire-метрики.
test_stream_service: реальная заблокированная очередь ETCP, короткий глитч без закрытий, частичная parity-разгрузка,
продолжающийся FEC decode, несколько закрытий, подавленный SELECT/fallback/поздний выбор и общий бюджет двух пиров.
Высокий CPU без backlog не создаёт нового OVERLOAD. Оба теста прошли под ASAN/LeakSanitizer без ошибок и утечек.
Логи: /tmp/stream-pressure-asan-core.log и /tmp/stream-pressure-asan-service.log.
[ ] Оптимизация сети и интеграционные проверки:
пути/защита от циклов, стартовые 32 пробы, дальнейший темп 1/с и полный цикл не чаще 30 с,
@ -557,31 +585,42 @@ stream_receive_get_info сообщает handle/прогресс/причину,
Локальная подписка по-прежнему владеет кольцом; receive handle её не заменяет и закрывается отдельно.
Прямой dispatcher в старой части теста сохранён для изолированной проверки FEC и закрытия из callback;
новая часть проверяет реальные сетевые bindings и передачу через relay.
Следующий этап — метрики поставщиков/общей нагрузки, OVERLOAD с подтверждением 500 мс и оптимизатор проб/переноса.
Следующий этап — автоматические пробы 32/1с/30с, выбор поставщиков, перенос с перекрытием и failover.
17. Зафиксированный сетевой формат и пределы первого сетевого этапа
Все stream-числа на wire — big-endian, без packed-структур и зависимости от host byte order.
Версия stream wire — 2; обратная совместимость не поддерживается.
Заголовок raw (52 байта): cmd:1, version:1, command:1, subblock:1,
group_id:8, source_node_id:8, source_epoch:8, sender_epoch:8, receiver_epoch:8, handle:8.
INFO_REQ/RESP согласуют sender/receiver epochs; неизвестная receiver_epoch=0 допустима только при начальном INFO_REQ/reverse.
Подписанный routed payload содержит тот же заголовок; его group_id сверяется с реальной группой router,
sender берётся из end-to-end router metadata. DATA через routed service отвергается.
INFO_RESP/ACCEPT: actual_seq:8, first_available:8, last_available:8, n:1, r:1, block_size:2,
path_count:1, node_ids:8*path_count. В INFO actual_seq — последний доступный, в ACCEPT — фактический старт.
SUBSCRIBE: requested_seq:8; REJECT: reason:1 и для отказа SUBSCRIBE first_available:8,last_available:8.
INFO_REQ: probe_nonce:8, не резервирует номер SUBSCRIBE.
INFO_RESP/ACCEPT: probe_nonce:8 (0 в ACCEPT), actual_seq:8, first_available:8, last_available:8, n:1, r:1, block_size:2,
metric_flags:1, lag_ms:8, source_rate:8, receive_rate:8, blocks:8, late_blocks:8, stops:8,
path_count:1, node_ids:8*path_count — фиксированная часть 86 байт. В INFO actual_seq — последний доступный, в ACCEPT — старт.
metric_flags: bit0 — измерение известно, bit1 — source_rate известен, bit2 — receive_rate известен, bit3 — stopped.
SUBSCRIBE: requested_seq:8; REJECT: reason:1, для SUBSCRIBE дополнительно first_available:8,last_available:8,
для INFO дополнительно probe_nonce:8. Старый nonce не подтверждает новую пробу.
RENEW: один header handle без payload (каждая кодограмма продлевает один элемент списка).
UNSUBSCRIBE/CLOSED: reason:1. DATA: path_count:1,node_ids:8*path_count,неизменяемый подписанный блок.
GAP: old_cursor:8,next_cursor:8, уведомление включает диапазон [old_cursor,next_cursor).
END: "stream_end":10,group_id:8,source_node_id:8,source_epoch:8,last_seq:8,Ed25519:64 — всего 106 байт.
UINT64_MAX в END означает пустой источник; запрос с конца пустого кольца явно отвергается (нет первого блока).
OVERLOAD: request_id:8, required_rate:8 (байт/с), estimated_count:1, candidate_count:1,
{handle:8,frozen_rate:8}*candidate_count; не более 64 элементов.
OVERLOAD_SELECT: request_id:8, selected_count:1, handles:8*selected_count; не более 64 элементов.
Оба сообщения идут по raw ETCP с проверенными эпохами пира и действуют только на существующие выдачи.
Список проверяется полностью до действия; повторный/поздний id не создаёт новое требование и не продлевает срок.
Предел пути — 32 узла. Сохраняются только реальные узлы пути; исходный {source} не требует отдельной аллокации.
Память пути отделена от 32-МБ бюджета данных и ограничена числом блоков кольца:
до (8 + 8*32) байт на блок плюс поля индекса и overhead allocator; источнику эта память путей не нужна.
64 stream-пира, 256 активных выдач всего и 64 на пира. Control FIFO — до 128 кодограмм,
каждая не больше 338 байт wire; DATA в ней не хранится. На пира один waiter общего send_input_q,
каждая не больше 1094 байт wire плюс 8 байт локального времени постановки; DATA в ней не хранится. На пира один waiter send_input_q,
отправка по освобождению до пустого порога; курсоры downstream обслуживаются round-robin.
Эти пределы задают ограниченную память базовой выдачи. A/D/X/Q, возраст нагрузки и 500-мс OVERLOAD
подключаются следующим этапом; автоматический выбор/перекрытие поставщиков пока не запускаются.
Для временного индекса каждый фактический блок дополнительно имеет seq/received_ms и два uint32 указателя списка субпотока.
Логический Q не выделяет память под копии/задания на весь backlog и ограничен доступными блоками колец и числом выдач.
Эти пределы задают ограниченную память выдачи и разгрузки; автоматический выбор/перекрытие поставщиков пока не запускаются.

10
doc/tasks.md

@ -25,7 +25,15 @@
После восстановления обычной сборки ./check.sh: 144 passed, 0 failed, 0 skipped;
proxy/full (9/9), burst и load — PASS. Лог: /tmp/stream-network-check.log (88 с).
Wire и численные пределы зафиксированы в doc/stream.txt, раздел 17.
Следующий этап — метрики и перегрузка (500мс/rates/OVERLOAD), затем автоматические пробы/перенос/failover.
11.10.2026 подключены timestamp-метрики/rates/stops, nonce/метрики INFO и RTT uint32 мс,
A/D/X/Q выдач/пиров/модуля, интервалы 200мс и история 10с, подтверждение перегрузки 500мс.
OVERLOAD с frozen rates, FEC/альтернативами при выборе, SELECT/CLOSED, неизменным сроком 2с и fallback;
глобальный бюджет нескольких пиров требует backlog и локальной загрузки, CPU отдельно не режет.
4-секундный предел возраста control/ожидающих заданий, GAP/X при истечении и наблюдаемый статус accepting.
Частичная/сильная/глобальная разгрузка, короткий глитч и поздний SELECT прошли под ASAN/LeakSanitizer без ошибок/утечек.
Логи: /tmp/stream-pressure-asan-core.log и /tmp/stream-pressure-asan-service.log.
Wire версии 2 и пределы обновлены в doc/stream.txt, раздел 17.
Следующий этап — автоматические пробы 32/1с/30с, перенос с перекрытием и failover.
[+] **test_reality_tls: коллизии порта слушателя** — 10.10.2026:
В общем прогоне 140 passed, 1 failed: stcp_server_create не смог занять порт 34922, bind errno=98 (EADDRINUSE).

Loading…
Cancel
Save