Słyszałem o utrzymywaniu aktywności HTTP, ale na razie chcę otworzyć połączenie przez gniazdo ze zdalnym serwerem.
Czy to połączenie przez gniazdo pozostanie otwarte na zawsze, czy też jest z nim powiązany limit czasu podobny do utrzymywania aktywności HTTP?
84
Odpowiedzi:
Gniazda TCP pozostają otwarte, dopóki nie zostaną zamknięte.
To powiedziawszy, bardzo trudno jest wykryć zerwane połączenie (zerwane, jak w przypadku routera, itp., W przeciwieństwie do zamkniętego) bez faktycznego wysyłania danych, więc większość aplikacji co jakiś czas wykonuje jakąś reakcję ping / pong, aby się upewnić połączenie jest nadal żywe.
źródło
Krótka odpowiedź brzmi: nie , nie pozostanie otwarte wiecznie, prawdopodobnie wyłączy się po kilku godzinach. Dlatego tak tam jest limit czasu i jest egzekwowane poprzez TCP keep-alive .
Jeśli chcesz skonfigurować limit czasu utrzymywania aktywności na swoim komputerze, zobacz sekcję „Zmiana limitów czasu TCP” poniżej. W przeciwnym razie przeczytaj resztę odpowiedzi, aby dowiedzieć się, jak działa TCP Keep-Alive.
Wprowadzenie
Połączenia TCP składają się z dwóch gniazd, po jednym na każdym końcu połączenia. Kiedy jedna strona chce zakończyć połączenie, wysyła
RST
pakiet, który druga strona potwierdza i obie zamykają swoje gniazda.Dopóki to jednak nie nastąpi, obie strony pozostaną otwarte na czas nieokreślony. To pozostawia otwartą możliwość, że jedna strona może zamknąć swoje gniazdo, celowo lub z powodu jakiegoś błędu, bez informowania drugiej strony za pośrednictwem
RST
. Aby wykryć ten scenariusz i zamknąć przestarzałe połączenia, używany jest proces TCP Keep Alive.Utrzymanie przy życiu procesu
Istnieją trzy konfigurowalne właściwości, które określają sposób działania Keep-Alives. W systemie Linux są to 1 :
tcp_keepalive_time
tcp_keepalive_probes
tcp_keepalive_intvl
Proces przebiega następująco:
tcp_keepalive_time
kilka sekund, wyślij pojedynczy pustyACK
pakiet. 1ACK
własnym odpowiednikiem?tcp_keepalive_intvl
sekundy, a następnie wyślij kolejnąACK
ACK
wysłanych sond będzie równatcp_keepalive_probes
.RST
i zakończ połączenie.Ten proces jest domyślnie włączony w większości systemów operacyjnych, dlatego martwe połączenia TCP są regularnie usuwane, gdy drugi koniec nie odpowiada przez 2 godziny i 11 minut (7200 sekund + 75 * 9 sekund).
Gotchas
Domyślnie 2 godziny
Ponieważ proces nie rozpoczyna się, dopóki połączenie nie jest domyślnie nieaktywne przez dwie godziny, nieaktualne połączenia TCP mogą utrzymywać się przez bardzo długi czas, zanim zostaną wyczyszczone. Może to być szczególnie szkodliwe w przypadku drogich połączeń, takich jak połączenia z bazą danych.
Utrzymywanie przy życiu jest opcjonalne
Zgodnie z RFC 1122 4.2.3.6 odpowiadanie na i / lub przekazywanie pakietów TCP Keep-Alive jest opcjonalne :
Powodem jest to, że pakiety Keep-Alive nie zawierają żadnych danych i nie są bezwzględnie konieczne, a ich nadużywanie grozi zapychaniem tub w sieciach.
Jednak w praktyce z mojego doświadczenia wynika, że problem ten z czasem zmniejszył się, ponieważ przepustowość stała się tańsza; i dlatego pakiety Keep-Alive zwykle nie są odrzucane. Na przykład dokumentacja Amazon EC2 zawiera pośrednie poparcie dla Keep-Alive, więc jeśli hostujesz w AWS, prawdopodobnie możesz bezpiecznie polegać na Keep-Alive, ale Twój przebieg może się różnić.
Zmiana limitów czasu TCP
Na gniazdo
Niestety, ponieważ połączenia TCP są zarządzane na poziomie systemu operacyjnego, Java nie obsługuje konfigurowania limitów czasu na poziomie na gniazdo, na przykład w
java.net.Socket
. Znalazłem kilka prób 3 wykorzystania natywnego interfejsu Java (JNI) do tworzenia gniazd Java, które wywołują kod natywny w celu skonfigurowania tych opcji, ale żadna z nich nie wydaje się mieć powszechnej akceptacji lub wsparcia społeczności.Zamiast tego możesz zostać zmuszony do zastosowania swojej konfiguracji do systemu operacyjnego jako całości. Należy pamiętać, że ta konfiguracja wpłynie na wszystkie połączenia TCP uruchomione w całym systemie.
Linux
Aktualnie skonfigurowane ustawienia TCP Keep-Alive można znaleźć w
/proc/sys/net/ipv4/tcp_keepalive_time
/proc/sys/net/ipv4/tcp_keepalive_probes
/proc/sys/net/ipv4/tcp_keepalive_intvl
Możesz zaktualizować dowolne z nich w następujący sposób:
# 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
Takie zmiany nie będą się utrzymywać po ponownym uruchomieniu. Aby wprowadzić trwałe zmiany, użyj
sysctl
:sysctl -w net.ipv4.tcp_keepalive_time=180 net.ipv4.tcp_keepalive_probes=3 net.ipv4.tcp_keepalive_intvl=10
Mac OS X
Aktualnie skonfigurowane ustawienia można wyświetlić za pomocą
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
Warto zauważyć, że Mac OS X definiuje
keepidle
ikeepintvl
w milisekundach, w przeciwieństwie do Linuksa, który używa sekund.Można ustawić właściwości,
sysctl
które będą zachowywać te ustawienia po ponownym uruchomieniu:sysctl -w net.inet.tcp.keepidle=180000 net.inet.tcp.keepcnt=3 net.inet.tcp.keepintvl=10000
Alternatywnie możesz je dodać do
/etc/sysctl.conf
(tworzenie pliku, jeśli nie istnieje).$ cat /etc/sysctl.conf net.inet.tcp.keepidle=180000 net.inet.tcp.keepintvl=10000 net.inet.tcp.keepcnt=3
Windows
Nie mam komputera z systemem Windows do potwierdzenia, ale odpowiednie ustawienia TCP Keep-Alive powinny znaleźć się w rejestrze pod adresem
\HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\TCPIP\Parameters
Przypisy
1. Zobacz,
man tcp
aby uzyskać więcej informacji.2. Ten pakiet jest często nazywany pakietem „Keep-Alive”, ale w specyfikacji TCP jest to zwykły
ACK
pakiet. Aplikacje takie jak Wireshark są w stanie oznaczyć go jako pakiet „Keep-Alive” poprzez metaanalizę sekwencji i numerów potwierdzeń, które zawiera w odniesieniu do poprzedniej komunikacji w gnieździe.3. Niektóre przykłady, które znalazłem z podstawowego wyszukiwania Google, to lucwilliams / JavaLinuxNet i flonatel / libdontdie .
źródło
$ no -a | grep tcp_keep
komendy.Szukasz opcji gniazda SO_KEEPALIVE.
W Java Socket API eksponuje „keep-alive” do aplikacji za pośrednictwem
setKeepAlive
igetKeepAlive
metod.EDYCJA: SO_KEEPALIVE jest zaimplementowana w stosach protokołów sieciowych systemu operacyjnego bez wysyłania żadnych „prawdziwych” danych. Interwał utrzymywania aktywności jest zależny od systemu operacyjnego i może być dostosowywany za pomocą parametru jądra.
Ponieważ żadne dane nie są wysyłane, SO_KEEPALIVE może tylko przetestować żywotność połączenia sieciowego, a nie usługi, z którą jest połączone gniazdo. Aby przetestować to drugie, musisz zaimplementować coś, co obejmuje wysyłanie wiadomości do serwera i uzyskiwanie odpowiedzi.
źródło
TCP keepalive i HTTP keepalive to bardzo różne koncepcje. W TCP utrzymanie aktywności to pakiet administracyjny wysyłany w celu wykrycia nieaktualnego połączenia. W HTTP utrzymanie aktywności oznacza trwały stan połączenia.
To pochodzi ze specyfikacji TCP,
Pakiety utrzymujące aktywność MUSZĄ być wysyłane tylko wtedy, gdy nie zostały odebrane żadne pakiety danych lub potwierdzenia dla połączenia w określonym przedziale czasu. Ten interwał MUSI być konfigurowalny i MUSI domyślnie wynosić nie mniej niż dwie godziny.
Jak widać, domyślny interwał utrzymywania aktywności TCP jest zbyt długi dla większości aplikacji. Może być konieczne dodanie funkcji keepalive w protokole aplikacji.
źródło
HTTP/1.0
każdym żądaniu / odpowiedzi konieczne było ponowne połączenie z serwerem. PonieważHTTP/1.1
wprowadziliKeep-Alive
nagłówek, który może być użyty do tego, aby serwer nie przerywał połączenia po zakończeniu przetwarzania odpowiedzi w celu ułatwienia żądania większej liczby plików i umożliwienia „pipeliningu”; wysyłanie wielu żądań, a następnie czekanie na powrót wszystkich danych.Jeśli jesteś za maskaradowym NATem (jak obecnie większość użytkowników domowych), istnieje ograniczona pula portów zewnętrznych, które muszą być współużytkowane przez połączenia TCP. Dlatego też NAT podszywający się pod maskę zakłada zwykle, że połączenie zostało zakończone, jeśli żadne dane nie zostały wysłane przez określony czas.
Ten i inne tego typu problemy (gdziekolwiek pomiędzy dwoma punktami końcowymi) mogą oznaczać, że połączenie nie będzie już „działać”, jeśli spróbujesz wysłać dane po rozsądnym okresie bezczynności. Jednak możesz nie odkryć tego, dopóki nie spróbujesz wysłać danych.
Korzystanie z funkcji utrzymywania aktywności zmniejsza ryzyko przerwania połączenia w jakimś miejscu na linii, a także pozwala szybciej dowiedzieć się o zerwanym połączeniu.
źródło
Oto dodatkowa literatura na temat utrzymywania aktywności, która wyjaśnia to bardziej szczegółowo.
http://www.tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO
Ponieważ Java nie pozwala kontrolować rzeczywistych czasów utrzymywania aktywności, możesz użyć przykładów, aby je zmienić, jeśli używasz jądra Linuksa (lub systemu operacyjnego opartego na proc).
źródło
W JAVA Socket - połączenia TCP są zarządzane na poziomie systemu operacyjnego, java.net.Socket nie udostępnia żadnej wbudowanej funkcji ustawiania limitów czasu dla pakietów utrzymywania aktywności na poziomie poszczególnych gniazd. Ale możemy włączyć opcję keepalive dla gniazda java, ale domyślnie zajmuje to 2 godziny 11 minut (7200 sekund) po nieaktualnych połączeniach tcp. To powoduje, że połączenie będzie dostępne przez bardzo długi czas przed czyszczeniem. Znaleźliśmy więc rozwiązanie umożliwiające użycie natywnego interfejsu Java (JNI), który wywołuje kod natywny (c ++) w celu skonfigurowania tych opcji.
**** System operacyjny Windows ****
W systemie operacyjnym Windows keepalive_time i keepalive_intvl mogą być konfigurowalne, ale tcp_keepalive_probes nie mogą być zmienione.Domyślnie, gdy gniazdo TCP jest zainicjowane, ustawia limit czasu utrzymywania aktywności na 2 godziny i interwał utrzymywania aktywności na 1 sekundę. Domyślną wartością limitu czasu utrzymania aktywności dla całego systemu można sterować za pomocą ustawienia rejestru KeepAliveTime, które przyjmuje wartość w milisekundach.
W systemie Windows Vista i nowszych liczba sond podtrzymujących aktywność (retransmisje danych) jest ustawiona na 10 i nie można jej zmienić.
W systemach Windows Server 2003, Windows XP i Windows 2000 domyślne ustawienie liczby sond utrzymujących aktywność to 5. Liczba sond utrzymujących aktywność jest kontrolowana. W systemie Windows biblioteka Winsock IOCTLs służy do konfigurowania parametrów tcp-keepalive.
int WSAIoctl (SocketFD, // deskryptor identyfikujący gniazdo SIO_KEEPALIVE_VALS, // dwIoControlCode (LPVOID) lpvInBuffer, // wskaźnik do tcp_keepalive struct (DWORD) cbInBuffer, // długość bufora wejściowego NULL, // bufor wyjściowy 0, // rozmiar bufor wyjściowy (LPDWORD) lpcbBytesReturned, // liczba zwróconych bajtów NULL, // struktura OVERLAPPED NULL // procedura uzupełniania);
System operacyjny Linux
Linux ma wbudowaną obsługę utrzymywania aktywności, która musi mieć włączoną obsługę sieci TCP / IP, aby z niej korzystać. Programy muszą żądać utrzymywania aktywności dla swoich gniazd za pomocą interfejsu setsockopt.
int setsockopt (int socket, int level, int optname, const void * optval, socklen_t optlen)
Każde gniazdo klienta zostanie utworzone za pomocą java.net.Socket. Identyfikator deskryptora pliku dla każdego gniazda zostanie pobrany przy użyciu odbicia java.
źródło
Dla Windows zgodnie z Microsoft Docs
źródło