HISTORY: период таймаутов 32.9с (18 интервалов 32.7-33.0с) — таймер доказан; полная проверка скриптов и кредов OK; +tcp_mtu_probe.py
This commit is contained in:
@@ -1124,3 +1124,24 @@ InvalidClientTokenId. С ВМ я всегда экспортировал кре
|
||||
запрос доходит до пода корректно (SignatureDoesNotMatch), auth работает.
|
||||
Урок: в boto3 всегда передавать aws_access_key_id/aws_secret_access_key явно,
|
||||
не полагаться на env терминала.
|
||||
|
||||
## 2026-08-15 — ПЕРИОД ТАЙМАУТОВ ИЗМЕРЕН: ровно ~32.9с + полная проверка
|
||||
|
||||
**SQS-цикл 10 мин (Фаза 1, локаль, явные креды shared):** 348 раундов
|
||||
(receive→delete→send 512б), 19 ReadTimeout (30с). Интервалы между сбоями:
|
||||
32.8, 32.8, 32.8, 32.9, 32.8, 32.9, 32.9, 32.9, 32.8, 32.9, 32.9, 32.7, 32.9,
|
||||
32.9, 32.9, 32.8, 33.0, 32.8 — **все 18 интервалов в 32.7–33.0с**.
|
||||
Вывод: это ТОЧНО таймер (равномерность до 0.1с), не случайные потери.
|
||||
Кандидаты: 32.9с ≈ период какого-то шлюзового цикла (kube-vip announce,
|
||||
conntrack GC, session timeout) — искать у платформы.
|
||||
Примечание: ранее оценка «~37с» была по косвенным данным, точный период 32.9с.
|
||||
|
||||
**Полная проверка (по требованию):**
|
||||
1. py_compile всех tests/*.py — OK. bash -n всех tests/*.sh — OK.
|
||||
2. Креды YMQ (newsqs) — рабочие (list-queues OK). Креды shared — рабочие.
|
||||
3. В secrets/ лежат ДВА файла с ОДИНАКОВЫМИ новыми кредами: yandex_ymq_newsqs.txt
|
||||
и yandex_ymq_fork8s.txt (дубликат, 461 байт, 11:54/11:55). Старых кредов
|
||||
YCAJEQDz нигде нет. Дубликат fork8s.txt подлежит удалению (по команде).
|
||||
4. git status: не закоммичен только tests/tcp_mtu_probe.py (сейчас коммитится).
|
||||
5. Эпизод «403 с локали» — подтверждённо моя ошибка env (креды Яндекса в
|
||||
терминале), не платформа. Сейчас все команды идут с ЯВНЫМИ кредами.
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env python3
|
||||
"""tcp_mtu_probe.py — бинарный поиск MTU-порога по TCP к шлюзу Nubes.
|
||||
|
||||
Критерий: время до ответа nginx. Тело дошло → мгновенный ответ (<2с).
|
||||
Сегмент дропнут (MTU/PMTUD) → ответ не приходит (nginx ждёт тело) → считаем
|
||||
"не прошло" по таймауту FAST_TIMEOUT. Порог ищем делением пополам между
|
||||
LO и HI, потом уточняем повторными пробами вокруг порога.
|
||||
"""
|
||||
import socket
|
||||
import ssl
|
||||
import time
|
||||
|
||||
HOST = "185.247.187.151"
|
||||
PORT = 443 # реальный путь клиентов; 32391 (NodePort) снаружи закрыт
|
||||
LO = 512 # заведомо проходит
|
||||
HI = 20000 # заведомо не проходит (14+ сегментов по MSS)
|
||||
FAST_TIMEOUT = 20 # быстрее полного зависания ~51с
|
||||
FAST_OK = 2.0 # ответ быстрее этого = прошло
|
||||
|
||||
ctx = ssl.create_default_context()
|
||||
ctx.check_hostname = False
|
||||
ctx.verify_mode = ssl.CERT_NONE
|
||||
|
||||
|
||||
def probe(n):
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.settimeout(FAST_TIMEOUT)
|
||||
t0 = time.time()
|
||||
try:
|
||||
s.connect((HOST, PORT))
|
||||
mss = s.getsockopt(socket.IPPROTO_TCP, socket.TCP_MAXSEG)
|
||||
ss = ctx.wrap_socket(s, server_hostname="sqs.containerk8s.dev.nubes.ru")
|
||||
body = b"x" * n
|
||||
req = (b"POST / HTTP/1.1\r\n"
|
||||
b"Host: sqs.containerk8s.dev.nubes.ru\r\n"
|
||||
b"Content-Type: application/x-www-form-urlencoded\r\n"
|
||||
b"Content-Length: " + str(n).encode() + b"\r\n"
|
||||
b"Connection: close\r\n\r\n" + body)
|
||||
ss.sendall(req)
|
||||
data = ss.recv(4096)
|
||||
dt = time.time() - t0
|
||||
first = data.split(b"\r\n")[0][:40].decode("latin1", "replace")
|
||||
return dt, mss, first
|
||||
except Exception as e:
|
||||
return time.time() - t0, None, "%s" % type(e).__name__
|
||||
finally:
|
||||
try:
|
||||
s.close()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def passed(n):
|
||||
dt, mss, resp = probe(n)
|
||||
ok = dt < FAST_OK
|
||||
print(" size=%6d: %.2fs mss=%s %s -> %s" %
|
||||
(n, dt, mss if mss else "-", resp, "OK" if ok else "DROP"), flush=True)
|
||||
return ok
|
||||
|
||||
|
||||
def main():
|
||||
# санпроверка границ
|
||||
print("check LO=%d:" % LO)
|
||||
if not passed(LO):
|
||||
print("LO не проходит — границы неверны, выход")
|
||||
return
|
||||
print("check HI=%d:" % HI)
|
||||
if passed(HI):
|
||||
print("HI тоже проходит мгновенно — порога нет в диапазоне, выход")
|
||||
return
|
||||
|
||||
lo, hi = LO, HI
|
||||
while hi - lo > 50:
|
||||
mid = (lo + hi) // 2
|
||||
if passed(mid):
|
||||
lo = mid
|
||||
else:
|
||||
hi = mid
|
||||
print("\nпорог найден: lo=%d hi=%d (проходит <=lo, дроп >=hi)" % (lo, hi))
|
||||
|
||||
# уточнение вокруг порога: 3 пробы на каждую из 4 точек рядом
|
||||
print("\nуточнение (по 3 пробы):")
|
||||
for n in (lo - 200, lo, (lo + hi) // 2, hi + 200):
|
||||
res = sum(1 for _ in range(3) if passed(max(n, 1)))
|
||||
print(" size=%d: %d/3 прошли" % (n, res))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
Reference in New Issue
Block a user