Причина, по якій ви не можете конкретно змінити RTO, полягає в тому, що це не є статичним значенням. Натомість (за винятком початкового SYN, природно), він базується на RTT (час туди і назад) для кожного з'єднання. Власне, він заснований на згладженій версії RTT та дисперсії RTT з деякими константами, кинутими в суміш. Отже, це динамічне, обчислене значення для кожного з'єднання TCP, і я настійно рекомендую цю статтю, яка детальніше розглядає обчислення та RTO загалом.
Також актуальною є RFC 6298, де зазначено (серед багатьох інших):
Щоразу, коли RTO обчислюється, якщо вона менша за 1 секунду, RTO ОБОВ'ЯЗКОВО повинен бути округлий до 1 секунди.
Чи завжди ядро встановлює RTO на 1 секунду? Ну, за допомогою Linux ви можете показати поточні значення RTO для відкритих підключень, запустивши ss -i
команду:
State Recv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB 0 0 10.0.2.15:52861 216.58.219.46:http
cubic rto:204 rtt:4/2 cwnd:10 send 29.2Mbps rcv_space:14600
ESTAB 0 0 10.0.2.15:ssh 10.0.2.2:52586
cubic rto:201 rtt:1.5/0.75 ato:40 cwnd:10 send 77.9Mbps rcv_space:14600
ESTAB 0 0 10.0.2.15:52864 216.58.219.46:http
cubic rto:204 rtt:4.5/4.5 cwnd:10 send 26.0Mbps rcv_space:14600
Наведене вище - це вихід з VM, на якому я ввійшов у SSH і має пару з’єднань, відкритих для google.com. Як бачите, RTO насправді встановлений на 200-іш (мілісекунд). Ви зауважите, що воно не округлене до значення 1 секунди від RFC, і ви також можете подумати, що це трохи вище. Це тому, що є мінімальні (200 мілісекунд) та максимум (120 секунд) межі, коли мова йде про RTO для Linux (є чудове пояснення цього в статті, яку я пов’язував вище).
Таким чином, ви не можете змінити значення RTO безпосередньо, але для втрачених мереж (наприклад, бездротових) ви можете спробувати налаштувати F-RTO (це може бути вже включено залежно від вашого дистрибутива). Насправді є два варіанти, пов'язані з F-RTO, які ви можете налаштувати (хороший підсумок тут ):
net.ipv4.tcp_frto
net.ipv4.tcp_frto_response
Залежно від того, для чого ви намагаєтесь оптимізувати, вони можуть бути, а можуть і не бути корисними.
EDIT: перевірка на можливість налаштування rto_min / max значень для TCP з коментарів.
Ви не можете змінити глобальний мінімальний RTO для TCP (як сторону, ви можете зробити це для SCTP - вони виставлені в sysctl), але гарна новина полягає в тому, що ви можете налаштувати мінімальне значення RTO на маршрут основа. Ось моя таблиця маршрутизації на моєму CentOS VM:
ip route
10.0.2.0/24 dev eth0 proto kernel scope link src 10.0.2.15
169.254.0.0/16 dev eth0 scope link metric 1002
default via 10.0.2.2 dev eth0
Я можу змінити значення rto_min на маршруті за замовчуванням так:
ip route change default via 10.0.2.2 dev eth0 rto_min 5ms
А тепер моя таблиця маршрутизації виглядає приблизно так:
ip route
10.0.2.0/24 dev eth0 proto kernel scope link src 10.0.2.15
169.254.0.0/16 dev eth0 scope link metric 1002
default via 10.0.2.2 dev eth0 rto_min lock 5ms
Нарешті, давайте розпочнемо з’єднання та перевіримо, ss -i
чи дотримувались цього:
ss -i
State Recv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB 0 0 10.0.2.15:ssh 10.0.2.2:50714
cubic rto:201 rtt:1.5/0.75 ato:40 cwnd:10 send 77.9Mbps rcv_space:14600
ESTAB 0 0 10.0.2.15:39042 216.58.216.14:http
cubic rto:15 rtt:5/2.5 cwnd:10 send 23.4Mbps rcv_space:14600
Успіху! Rto на HTTP-з’єднанні (після зміни) становить 15 мс, тоді як з'єднання SSH (до зміни) становить 200+, як і раніше.
Мені насправді подобається такий підхід - він дозволяє встановлювати нижнє значення на відповідних маршрутах, а не глобально, де це може призвести до іншого трафіку. Аналогічно (див. Сторінку ip man ) можна налаштувати початкову оцінку rtt та початкову rttvar для маршруту (використовується під час обчислення динамічного RTO). Хоча це не повне рішення з точки зору налаштування, я думаю, що більшість важливих фрагментів є саме там. Ви не можете налаштувати налаштування максимуму, але я думаю, що це не буде настільки корисним, як правило, у будь-якому випадку.