Czy zwrotne proxy HTTP zwykle włączają HTTP Keep-Alive po stronie klienta połączenia proxy, a nie po stronie serwera?

30

HAProxy ma możliwość włączania utrzymywania aktywności HTTP po stronie klienta (klient <-> HAProxy), ale wyłączania go po stronie serwera (serwer HAProxy <->).

Niektórzy z naszych klientów łączą się z naszą usługą internetową za pośrednictwem satelity, więc opóźnienie wynosi ~ 600 ms i myślę, że włączenie utrzymania aktywności przyspieszy nieco. Czy mam rację?

Czy to jest obsługiwane przez Nginx? Czy jest to szeroko stosowana funkcja w innych programach do równoważenia obciążenia oprogramowania i sprzętu? Co jeszcze oprócz HAProxy?

LostInComputer
źródło

Odpowiedzi:

43

edytuj: Moja odpowiedź obejmuje tylko oryginalne, niezredagowane pytanie, które dotyczyło tego, czy tego rodzaju rzeczy są typowe w przypadku równoważenia obciążenia / odwrotnych serwerów proxy. Nie jestem pewien, czy nginx / produkt X obsługuje to, 99,9% moich doświadczeń z odwrotnym proxy jest z HAproxy.

Poprawny. HTTP Keep-Alive po stronie klienta, ale nie po stronie serwera.

Czemu?

Jeśli podzielisz kilka szczegółów, szybko zobaczysz, dlaczego jest to korzyść. W tym przykładzie udajmy, że ładujemy stronę www.example.com, a ta strona zawiera 3 obrazy, img [1-3] .jpg.

Przeglądarka ładuje stronę bez Keep-Alive

  1. Klient nawiązuje połączenie TCP ze stroną www.example.com na porcie 80
  2. Klient wykonuje żądanie HTTP GET dla „/”
  3. Serwer wysyła zawartość HTML identyfikatora URI „/” (który zawiera tagi HTML odnoszące się do 3 obrazów)
  4. Serwer zamyka połączenie TCP
  5. Klient nawiązuje połączenie TCP ze stroną www.example.com na porcie 80
  6. Klient wykonuje żądanie HTTP GET dla „/img1.jpg”
  7. Serwer wysyła obraz
  8. Serwer zamyka połączenie TCP
  9. Klient nawiązuje połączenie TCP ze stroną www.example.com na porcie 80
  10. Klient wykonuje żądanie HTTP GET dla „/img2.jpg”
  11. Serwer wysyła obraz
  12. Serwer zamyka połączenie TCP
  13. Klient nawiązuje połączenie TCP ze stroną www.example.com na porcie 80
  14. Klient wykonuje żądanie HTTP GET dla „/img3.jpg”
  15. Serwer wysyła obraz
  16. Serwer zamyka połączenie TCP

Zauważ, że ustanowiono 4 osobne sesje TCP, a następnie zamknięto.

Przeglądarka ładuje stronę za pomocą Keep-Alive

HTTP Keep-Alive pozwala pojedynczemu połączeniu TCP obsługiwać wiele żądań HTTP, jeden po drugim.

  1. Klient nawiązuje połączenie TCP ze stroną www.example.com na porcie 80
  2. Klient wysyła żądanie HTTP GET dla „/”, a także prosi serwer, aby uczynił to sesją HTTP Keep-Alive.
  3. Serwer wysyła zawartość HTML identyfikatora URI „/” (który zawiera tagi HTML odnoszące się do 3 obrazów)
  4. Serwer nie zamyka połączenia TCP
  5. Klient tak i żądanie HTTP GET dla „/img1.jpg”
  6. Serwer wysyła obraz
  7. Klient tak i żądanie HTTP GET dla „/img2.jpg”
  8. Serwer wysyła obraz
  9. Klient robi i żądanie HTTP GET dla „/img3.jpg”
  10. Serwer wysyła obraz
  11. Serwer zamyka połączenie TCP, jeśli nie upłynie więcej żądań HTTP w jego limicie czasu podtrzymania HTTP

Zauważ, że dzięki Keep-Alive tylko 1 połączenie TCP jest ustanawiane i ostatecznie zamykane.

Dlaczego Keep-Alive jest lepszy?

Aby odpowiedzieć na to pytanie, musisz zrozumieć, co jest potrzebne do nawiązania połączenia TCP między klientem a serwerem. Nazywa się to potrójnym uzgadnianiem TCP.

  1. Klient wysyła pakiet SYN (chronise)
  2. Serwer odsyła SYN (chronise) ACK (nowledgement), SYN-ACK
  3. Klient wysyła pakiet ACK (nowledgement)
  4. Połączenie TCP jest teraz uważane za aktywne zarówno przez klienta, jak i serwer

Sieci mają opóźnienia, więc każdy krok w 3-kierunkowym uzgadnianiu zajmuje określoną ilość czasu. Powiedzmy, że między klientem a serwerem jest 30 ms, wysyłanie pakietów IP w przód iw tył wymagane do nawiązania połączenia TCP oznacza, że ​​ustanowienie połączenia TCP zajmuje 3 x 30 ms = 90 ms.

Może to nie brzmieć dużo, ale jeśli weźmiemy pod uwagę, że w naszym oryginalnym przykładzie musimy ustanowić 4 oddzielne połączenia TCP, to staje się 360ms. Co jeśli opóźnienie między klientem a serwerem wynosi 100 ms zamiast 30 ms? Nasze 4 połączenia trwają 1200ms.

Co gorsza, typowa strona internetowa może wymagać znacznie więcej niż tylko 3 obrazów do załadowania, może istnieć wiele plików CSS, JavaScript, obrazów lub innych plików, które klient musi zażądać. Jeśli strona ładuje 30 innych plików, a opóźnienie klient-serwer wynosi 100 ms, ile czasu spędzamy na nawiązywaniu połączeń TCP?

  1. Ustanowienie 1 połączenia TCP wymaga 3 x opóźnienia, tj. 3 x 100 ms = 300 ms.
  2. Musimy to zrobić 31 razy, raz dla strony i kolejne 30 razy dla każdego innego pliku, do którego odwołuje się strona. 31 x 300 ms = 9,3 sekundy.

9,3 sekundy spędziłem na ustanawianiu połączeń TCP w celu załadowania strony internetowej, która odwołuje się do 30 innych plików. I to nawet nie liczy czasu spędzonego na wysyłaniu żądań HTTP i otrzymywaniu odpowiedzi.

Dzięki HTTP Keep-Alive potrzebujemy tylko 1 połączenia TCP, co zajmuje 300ms.

Jeśli HTTP Keep-Alive jest tak świetny, dlaczego nie użyć go również po stronie serwera?

Odwrotne proxy HTTP (takie jak HAproxy) są zazwyczaj wdrażane bardzo blisko serwerów zaplecza, dla których są one proxy. W większości przypadków opóźnienie między zwrotnym serwerem proxy a jego serwerem zaplecza będzie wynosić poniżej 1ms, więc nawiązanie połączenia TCP jest znacznie szybsze niż między klientem.

To tylko połowa tego powodu. Serwer HTTP przydziela określoną ilość pamięci dla każdego połączenia klienta. Dzięki Keep-Alive utrzyma połączenie przy życiu, a przez rozszerzenie utrzyma pewną ilość pamięci używanej na serwerze, dopóki nie zostanie przekroczony limit czasu Keep-Alive, który może wynosić do 15 sekund, w zależności od konfiguracji serwera .

Jeśli więc weźmiemy pod uwagę skutki używania Keep-Alive po stronie serwera zwrotnego proxy HTTP, zwiększamy zapotrzebowanie na pamięć, ale ponieważ opóźnienie między serwerem proxy a serwerem jest tak niskie, nie uzyskujemy żadnej realnej korzyści z skrócenie czasu potrzebnego na potrójny uścisk dłoni TCP, więc zwykle lepiej jest po prostu wyłączyć Keep-Alive między serwerem proxy a serwerem WWW w tym scenariuszu.

Oświadczenie: tak, to wyjaśnienie nie bierze pod uwagę faktu, że przeglądarki zwykle ustanawiają wiele połączeń HTTP z serwerem równolegle. Istnieje jednak ograniczenie liczby połączeń równoległych, które przeglądarka nawiąże z tym samym hostem, i zwykle jest to wciąż wystarczająco małe, aby utrzymać aktywność przy życiu.

ThatGraemeGuy
źródło
5
Uznanie za doskonałe wyjaśnienie Graeme, nigdy nie poświęciłem wystarczająco dużo czasu na odpowiedź temu, kto mnie o to zapytał, i na pewno zachowam link do tego postu, aby był teraz bardzo jasną odpowiedzią :-)
Willy Tarreau
2
Czy korzyść dla keepAlive po stronie serwera byłaby, gdyby połączenie między proxy a backendem było https?
avmohan
„Serwer HTTP przydziela określoną ilość pamięci dla każdego połączenia klienta” tak, ale będzie ich niewiele (?) Tylko jedno na moduł równoważenia obciążenia? Ani jednego klienta w Internecie (?)
Raedwald
@ Raedwald, jeśli twój moduł równoważenia obciążenia ogranicza się do utworzenia pojedynczego połączenia HTTP z każdym serwerem objętym wsparciem, będziesz miał bardzo zły czas. :-)
ThatGraemeGuy
7

Nginx wspiera utrzymanie po obu stronach.

VBart
źródło
Czy powiedziałbyś, że utrzymanie przy życiu jest przydatne dla backendów, gdyby istniało opóźnienie między proxy a backendami? Jaka byłaby optymalna liczba utrzymywanych połączeń?
CMCDragonkai
@CMCDragonkai Jeśli zaplecze znajduje się na dedykowanych serwerach, przydatne może być uniknięcie opóźnień połączeń zależnych od sieci. Nie ma złotego środka, optymalna liczba zależy głównie od konfiguracji, środowiska, aplikacji i wzorca żądania.
VBart
Mam nadzieję znaleźć równanie, aby rozwiązać ten problem!
CMCDragonkai
2
Pytanie, które czytam, nie dotyczy pytania, czy nginx obsługuje utrzymanie aktywności w górę, ale czy nginx obsługuje wyłączenie utrzymania aktywności w górę.
user45793