Я чув про HTTP Keep-Live, але наразі я хочу відкрити сокетне з'єднання з віддаленим сервером.
Тепер чи залишатиметься це сокетне з’єднання назавжди відкритим, чи з ним пов’язане обмеження часу, подібне до HTTP Keep-Live?
Я чув про HTTP Keep-Live, але наразі я хочу відкрити сокетне з'єднання з віддаленим сервером.
Тепер чи залишатиметься це сокетне з’єднання назавжди відкритим, чи з ним пов’язане обмеження часу, подібне до HTTP Keep-Live?
Відповіді:
TCP-сокети залишаються відкритими до закриття.
Тим не менш, дуже важко виявити пошкоджене з’єднання (пошкоджене, як у маршрутизаторі, і т. Д., На відміну від закритого) без фактичної надсилання даних, тому більшість додатків проводять певні реакції пінг-понгу так часто, щоб просто переконатися зв'язок все ще живе.
Тепер чи залишатиметься це сокетне з’єднання назавжди відкритим, чи з ним пов’язане обмеження часу очікування, подібне до HTTP Keep-Live?
Коротка відповідь: ні, це не залишиться відкритим назавжди, можливо, через кілька годин очікується час. Тому так , є час очікування, і він застосовується через TCP Keep-Alive .
Якщо ви хочете налаштувати тайм-аут Keep-Alive на своєму комп'ютері, дивіться розділ "Зміна тайм-аутів TCP" нижче. В іншому випадку прочитайте решту відповіді, щоб дізнатись, як працює TCP Keep-Alive.
TCP-з'єднання складаються з двох сокетів, по одному на кожному кінці з'єднання. Коли одна сторона хоче розірвати з'єднання, вона надсилає RST
пакет, який підтверджує інша сторона, і обидва закривають свої сокети.
Однак поки цього не станеться, обидві сторони будуть тримати розетку відкритою на невизначений час. Це залишає відкритою можливість того, що одна сторона може закрити свою розетку навмисно або через якусь помилку, не повідомивши інший кінець через RST
. Для виявлення цього сценарію та закриття застарілих з'єднань використовується процес TCP Keep Alive.
Існує три властивості, які можна налаштувати, що визначають роботу Keep-Alives. У Linux це 1 :
tcp_keepalive_time
tcp_keepalive_probes
tcp_keepalive_intvl
Процес працює так:
tcp_keepalive_time
декількох секунд, надішліть один порожній ACK
пакет. 1ACK
своїм?
tcp_keepalive_intvl
секунди, а потім надішліть іншуACK
ACK
зондів не дорівнює tcp_keepalive_probes
.RST
та розірвіть з'єднання.Цей процес увімкнено за замовчуванням у більшості операційних систем, і, таким чином, мертві з'єднання TCP регулярно обрізаються, коли інший кінець не відповідає протягом 2 годин 11 хвилин (7200 секунд + 75 * 9 секунд).
Оскільки процес не починається, поки зв’язок за промовчанням не простояв дві години, застарілі з’єднання TCP можуть затриматись дуже довго, перш ніж бути обрізаними. Це може бути особливо шкідливим для дорогих підключень, таких як підключення до бази даних.
Відповідно до RFC 1122 4.2.3.6 , відповідати та / або передавати пакети TCP Keep-Alive необов’язково :
Реалізатори МОЖУТЬ включити "живих" до своїх реалізацій TCP, хоча ця практика не є загальновизнаною. Якщо включені програми збереження, програма ПОВИННА мати можливість їх увімкнути або вимкнути для кожного TCP-з'єднання, і вони ПОВИННІ вимкнути.
...
Надзвичайно важливо пам’ятати, що сегменти ACK, які не містять даних, не передаються надійно через TCP.
Міркування полягають у тому, що пакети Keep-Alive не містять даних і не є суворо необхідними, і при надмірному використанні ризикують засмітити трубки міжмереж.
На практиці, однак , я маю досвід, що з часом ця проблема зменшується, оскільки пропускна здатність стає дешевшою; і, таким чином, пакети Keep-Alive зазвичай не видаляються. Наприклад, документація Amazon EC2 дає непряме схвалення програми Keep-Alive, тому, якщо ви хостингуєте з AWS, ви, мабуть, безпечно покладаєтесь на Keep-Alive, але ваш пробіг може відрізнятися.
На жаль, оскільки TCP-з'єднання управляються на рівні ОС, Java не підтримує налаштування тайм-аутів на рівні кожного сокета, наприклад у java.net.Socket
. Я знайшов кілька спроб 3 використовувати рідний інтерфейс Java (JNI) для створення сокетів Java, які викликають власний код для налаштування цих параметрів, але, схоже, жодна з них не має широкого поширення або підтримки у спільноті.
Натомість вас можуть змусити застосувати свою конфігурацію до операційної системи в цілому. Майте на увазі, що ця конфігурація вплине на всі з'єднання TCP, що працюють у всій системі.
Налаштовані налаштування TCP Keep-Alive можна знайти в
/proc/sys/net/ipv4/tcp_keepalive_time
/proc/sys/net/ipv4/tcp_keepalive_probes
/proc/sys/net/ipv4/tcp_keepalive_intvl
Ви можете оновити будь-який із них приблизно так:
# Send first Keep-Alive packet when a TCP socket has been idle for 3 minutes
$ echo 180 > /proc/sys/net/ipv4/tcp_keepalive_time
# Send three Keep-Alive probes...
$ echo 3 > /proc/sys/net/ipv4/tcp_keepalive_probes
# ... spaced 10 seconds apart.
$ echo 10 > /proc/sys/net/ipv4/tcp_keepalive_intvl
Такі зміни не будуть зберігатися при перезапуску. Щоб вносити постійні зміни, використовуйте sysctl
:
sysctl -w net.ipv4.tcp_keepalive_time=180 net.ipv4.tcp_keepalive_probes=3 net.ipv4.tcp_keepalive_intvl=10
Поточні налаштування можна переглянути за допомогою sysctl
:
$ sysctl net.inet.tcp | grep -E "keepidle|keepintvl|keepcnt"
net.inet.tcp.keepidle: 7200000
net.inet.tcp.keepintvl: 75000
net.inet.tcp.keepcnt: 8
Слід зазначити, що Mac OS X визначає keepidle
і keepintvl
в одиницях мілісекунд на відміну від Linux, який використовує секунди.
Можна встановити властивості, за допомогою sysctl
яких будуть зберігатися ці налаштування при перезавантаженні:
sysctl -w net.inet.tcp.keepidle=180000 net.inet.tcp.keepcnt=3 net.inet.tcp.keepintvl=10000
Крім того, ви можете додати їх до /etc/sysctl.conf
(створення файлу, якщо він не існує).
$ cat /etc/sysctl.conf
net.inet.tcp.keepidle=180000
net.inet.tcp.keepintvl=10000
net.inet.tcp.keepcnt=3
У мене немає машини для підтвердження Windows, але ви повинні знайти відповідні налаштування TCP Keep-Alive у реєстрі за адресою
\HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\TCPIP\Parameters
Виноски
1. Див. man tcp
Додаткову інформацію.
2. Цей пакет часто називають пакетом "Keep-Alive", але в специфікації TCP це просто звичайний ACK
пакет. Додатки, такі як Wireshark, можуть позначати його як пакет "Keep-Alive" шляхом мета-аналізу послідовності та номерів підтвердження, які він містить, посилаючись на попередні повідомлення на сокеті.
3. Деякі приклади, які я знайшов із основного пошуку Google, - це lucwilliams / JavaLinuxNet та flonatel / libdontdie .
$ no -a | grep tcp_keep
команди.
Ви шукаєте варіант розетки SO_KEEPALIVE.
В API Java Торцеві оголює «підтримки активності» для додатків через setKeepAlive
таgetKeepAlive
методів.
EDIT: SO_KEEPALIVE реалізовано в стеках мережевих протоколів ОС без надсилання будь-яких "реальних" даних. Інтервал збереження життя залежить від операційної системи і може бути налаштований за допомогою параметра ядра.
Оскільки дані не надсилаються, SO_KEEPALIVE може протестувати лише активність мережевого підключення, а не активність служби, до якої підключено сокет. Щоб протестувати останнє, потрібно реалізувати щось, що передбачає надсилання повідомлень на сервер та отримання відповіді.
TCP Keepalive та HTTP Keepalive - це дуже різні поняття. У TCP keepalive - це адміністративний пакет, що надсилається для виявлення застарілого з'єднання. У HTTP keepalive означає постійний стан з'єднання.
Це із специфікації TCP,
Пакети збереження живлення ПОВИННІ надсилати лише тоді, коли за з'єднання протягом певного інтервалу не було отримано пакетів даних або підтверджень. Цей інтервал ПОВИНЕН налаштовуватись і ПОВИНЕН за замовчуванням становити не менше двох годин.
Як бачите, інтервал збереження TCP за замовчуванням завеликий для більшості програм. Можливо, вам доведеться додати keepalive у ваш протокол програми.
HTTP/1.0
кожному запиті / відповіді необхідне повторне підключення до сервера. Оскільки HTTP/1.1
вони ввели Keep-Alive
заголовок, який можна використовувати для запуску сервера, щоб не перервати з'єднання після обробки відповіді, щоб полегшити запит на додаткові файли та дозволити "конвеєризацію"; надсилання декількох запитів, а потім очікування повернення всіх даних.
Якщо ви стоїте за маскувальним NAT (як і в наш час більшість домашніх користувачів), існує обмежений пул зовнішніх портів, і вони повинні бути спільними між TCP-з'єднаннями. Тому маскуючі NAT, як правило, вважають, що з'єднання було розірвано, якщо протягом певного періоду часу не було надіслано даних.
Ця та інші подібні проблеми (в будь-якому місці між двома кінцевими точками) можуть означати, що з’єднання більше не буде «працювати», якщо ви спробуєте надіслати дані після неробочого періоду простою. Однак ви можете не виявити цього, поки не спробуєте надіслати дані.
Використання програм Keepalives одночасно зменшує ймовірність переривання зв’язку десь по лінії, а також дозволяє швидше дізнатися про розірваний зв’язок.
Ось додаткова література про Keepalive, яка пояснює це набагато детальніше.
http://www.tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO
Оскільки Java не дозволяє контролювати фактичний час збереження, ви можете використовувати приклади, щоб змінити їх, якщо ви використовуєте ядро Linux (або ОС на основі proc).
У JAVA Socket - TCP-з'єднання управляються на рівні ОС, java.net.Socket не надає жодної вбудованої функції для встановлення тайм-аутів для керуючого пакету на рівні кожного сокета. Але ми можемо ввімкнути опцію keepalive для сокета java, але за замовчуванням для обробки після застарілих з'єднань tcp потрібно 2 години 11 хвилин (7200 сек). Ця причина буде доступна дуже довго перед очищенням. Тож ми знайшли якесь рішення для використання власного інтерфейсу Java (JNI), який викликає власний код (c ++) для налаштування цих параметрів.
**** ОС Windows ****
В операційній системі Windows keepalive_time і keepalive_intvl можуть бути налаштовані, але tcp_keepalive_probes не можуть бути змінені. За замовчуванням, коли ініціалізовано сокет TCP, встановлюється час очікування до 2 годин, а інтервал до 1 секунди. Загальносистемне значення тайм-ауту Keep-Live контролюється за допомогою параметра реєстру KeepAliveTime, який приймає значення в мілісекундах.
У Windows Vista та пізніших версіях кількість зондів для збереження життя (повторних передач даних) встановлено на 10 і не може бути змінено.
У Windows Server 2003, Windows XP та Windows 2000 за замовчуванням встановлено кількість зондів підтримання активності - 5. Кількість зондів збереження активності можна контролювати. У Windows бібліотека IOCTL Winsock використовується для налаштування параметрів tcp-keepalive.
int WSAIoctl (SocketFD, // дескриптор, що ідентифікує сокет SIO_KEEPALIVE_VALS, // dwIoControlCode (LPVOID) lpvInBuffer, // вказівник на структуру tcp_keepalive (DWORD) cbInBuffer, // довжина вхідного буфера NULL, // вихідний буфер NULL, // вихідний буфер вихідний буфер (LPDWORD) lpcbBytesReturned, // кількість байтів, що повертаються NULL, // OVERLAPPED структура NULL // процедура завершення);
ОС Linux
Linux має вбудовану підтримку keepalive, яка необхідна для увімкнення мереж TCP / IP, щоб використовувати її. Програми повинні вимагати керованого керування своїми сокетами за допомогою інтерфейсу setsockopt.
int setsockopt (сокет int, рівень int, int optname, const void * optval, socklen_t optlen)
Кожен клієнтський сокет буде створений за допомогою java.net.Socket. Ідентифікатор дескриптора файлу для кожного сокета буде отримано за допомогою відображення Java.
Для Windows згідно з документами Microsoft