Browse Source

Document timestamp metrics and negotiated stream overload cuts

master
evgeny 3 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: закрываем достаточно выдач для требуемого сокращения; Число выдач выбирается по их rates: закрываем достаточно выдач для требуемого сокращения;
при сильном росте это сразу несколько, не фиксированная одна и не случайное постоянное число. при сильном росте это сразу несколько, не фиксированная одна и не случайное постоянное число.
OVERLOAD содержит request_id, расчётное число выдач и требуемое сокращение rate. OVERLOAD содержит request_id, расчётное число выдач, требуемое сокращение rate и список handles с фиксированными rates.
Получатель выбирает handles с учётом FEC и альтернативных поставщиков. Получатель выбирает handles с учётом FEC и альтернативных поставщиков и отправляет OVERLOAD_SELECT.
Отправитель исполняет выбор, только пока актуален исходный request_id, и сообщает CLOSED.
Получатель не отсоединяет выбранные handles до CLOSED: поздний SELECT после принудительного закрытия не режет дополнительные выдачи.
При разных rates одного количества закрытий недостаточно: суммарный снятый rate должен покрыть требование. При разных rates одного количества закрытий недостаточно: суммарный снятый rate должен покрыть требование.
Rate закрываемых выдач фиксируется по оценке на момент запроса, чтобы условие исполнения не менялось на каждом тике. Rate закрываемых выдач фиксируется по оценке на момент запроса, чтобы условие исполнения не менялось на каждом тике.
Срок реакции — 2 секунды с первого запроса; повторы не сбрасывают срок и не начинают новое требование. Срок реакции — 2 секунды с первого запроса; повторы не сбрасывают срок и не начинают новое требование.
@ -544,9 +546,35 @@ Stop/destroy выполняются по правилам ядра, вне callb
Общий ./check.sh: 144 passed, 0 failed, 0 skipped; proxy/full (9/9), burst и load — PASS. Общий ./check.sh: 144 passed, 0 failed, 0 skipped; proxy/full (9/9), burst и load — PASS.
Лог: /tmp/stream-network-check.log (88 с). Лог: /tmp/stream-network-check.log (88 с).
[ ] Планировщик отправки и разгрузка: [+] Метрики и разгрузка — 11.10.2026:
одна очередь на пира, backpressure, ограничение памяти/возраста, A/D/X/Q, stream_load.c/h — баланс A/D/X/Q по packets/bytes для выдачи, пира и модуля;
подтверждение 500 мс, сокращение по g/rates и двухсекундный срок исполнения OVERLOAD. интервалы >=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 с, пути/защита от циклов, стартовые 32 пробы, дальнейший темп 1/с и полный цикл не чаще 30 с,
@ -557,31 +585,42 @@ stream_receive_get_info сообщает handle/прогресс/причину,
Локальная подписка по-прежнему владеет кольцом; receive handle её не заменяет и закрывается отдельно. Локальная подписка по-прежнему владеет кольцом; receive handle её не заменяет и закрывается отдельно.
Прямой dispatcher в старой части теста сохранён для изолированной проверки FEC и закрытия из callback; Прямой dispatcher в старой части теста сохранён для изолированной проверки FEC и закрытия из callback;
новая часть проверяет реальные сетевые bindings и передачу через relay. новая часть проверяет реальные сетевые bindings и передачу через relay.
Следующий этап — метрики поставщиков/общей нагрузки, OVERLOAD с подтверждением 500 мс и оптимизатор проб/переноса. Следующий этап — автоматические пробы 32/1с/30с, выбор поставщиков, перенос с перекрытием и failover.
17. Зафиксированный сетевой формат и пределы первого сетевого этапа 17. Зафиксированный сетевой формат и пределы первого сетевого этапа
Все stream-числа на wire — big-endian, без packed-структур и зависимости от host byte order. Все stream-числа на wire — big-endian, без packed-структур и зависимости от host byte order.
Версия stream wire — 2; обратная совместимость не поддерживается.
Заголовок raw (52 байта): cmd:1, version:1, command:1, subblock:1, Заголовок 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. 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. INFO_REQ/RESP согласуют sender/receiver epochs; неизвестная receiver_epoch=0 допустима только при начальном INFO_REQ/reverse.
Подписанный routed payload содержит тот же заголовок; его group_id сверяется с реальной группой router, Подписанный routed payload содержит тот же заголовок; его group_id сверяется с реальной группой router,
sender берётся из end-to-end router metadata. DATA через routed service отвергается. 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, INFO_REQ: probe_nonce:8, не резервирует номер SUBSCRIBE.
path_count:1, node_ids:8*path_count. В INFO actual_seq — последний доступный, в ACCEPT — фактический старт. INFO_RESP/ACCEPT: probe_nonce:8 (0 в ACCEPT), actual_seq:8, first_available:8, last_available:8, n:1, r:1, block_size:2,
SUBSCRIBE: requested_seq:8; REJECT: reason:1 и для отказа SUBSCRIBE first_available:8,last_available:8. 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 (каждая кодограмма продлевает один элемент списка). RENEW: один header handle без payload (каждая кодограмма продлевает один элемент списка).
UNSUBSCRIBE/CLOSED: reason:1. DATA: path_count:1,node_ids:8*path_count,неизменяемый подписанный блок. UNSUBSCRIBE/CLOSED: reason:1. DATA: path_count:1,node_ids:8*path_count,неизменяемый подписанный блок.
GAP: old_cursor:8,next_cursor:8, уведомление включает диапазон [old_cursor,next_cursor). 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 байт. END: "stream_end":10,group_id:8,source_node_id:8,source_epoch:8,last_seq:8,Ed25519:64 — всего 106 байт.
UINT64_MAX в END означает пустой источник; запрос с конца пустого кольца явно отвергается (нет первого блока). 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 узла. Сохраняются только реальные узлы пути; исходный {source} не требует отдельной аллокации.
Память пути отделена от 32-МБ бюджета данных и ограничена числом блоков кольца: Память пути отделена от 32-МБ бюджета данных и ограничена числом блоков кольца:
до (8 + 8*32) байт на блок плюс поля индекса и overhead allocator; источнику эта память путей не нужна. до (8 + 8*32) байт на блок плюс поля индекса и overhead allocator; источнику эта память путей не нужна.
64 stream-пира, 256 активных выдач всего и 64 на пира. Control FIFO — до 128 кодограмм, 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. отправка по освобождению до пустого порога; курсоры 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; После восстановления обычной сборки ./check.sh: 144 passed, 0 failed, 0 skipped;
proxy/full (9/9), burst и load — PASS. Лог: /tmp/stream-network-check.log (88 с). proxy/full (9/9), burst и load — PASS. Лог: /tmp/stream-network-check.log (88 с).
Wire и численные пределы зафиксированы в doc/stream.txt, раздел 17. 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: [+] **test_reality_tls: коллизии порта слушателя** — 10.10.2026:
В общем прогоне 140 passed, 1 failed: stcp_server_create не смог занять порт 34922, bind errno=98 (EADDRINUSE). В общем прогоне 140 passed, 1 failed: stcp_server_create не смог занять порт 34922, bind errno=98 (EADDRINUSE).

Loading…
Cancel
Save