Kluczem do skalowania warstwy równoważenia obciążenia HTTP jest najpierw dodanie kolejnej warstwy równoważenia obciążenia niższego poziomu (IP lub TCP). Warstwę tę można zbudować w całości za pomocą oprogramowania typu open source, chociaż lepsze wyniki uzyskasz, jeśli posiadasz nowoczesne routery.
Przepływy (sesje TCP) powinny być zaszyfrowane przy użyciu nagłówków, takich jak źródłowy / docelowy port IP i porty TCP, aby zdecydować, do którego frontendu się udają. Potrzebujesz również mechanizmu, aby upewnić się, że gdy interfejs umiera, przestaje się przyzwyczajać.
Istnieją różne strategie, przedstawię kilka, które wykorzystałem w produkcji w witrynach obsługujących miliony użytkowników, abyś mógł uzyskać pomysł. To byłoby zbyt długie, aby wyjaśnić wszystko szczegółowo, ale mam nadzieję, że ta odpowiedź dostarczy ci wystarczających informacji / wskazówek, aby zacząć. Aby wdrożyć te rozwiązania, będziesz potrzebować kogoś, kto ma naprawdę dużą wiedzę na temat sieci.
Wprawdzie to, co tu opisuję, jest znacznie trudniejsze do wdrożenia niż to, co opisano w innych odpowiedziach, ale tak naprawdę jest to najnowocześniejsze, jeśli masz witrynę o dużym natężeniu ruchu z dużymi problemami ze skalowalnością i dostępnością powyżej 99,9% . Pod warunkiem, że masz już inżyniera sieciowego, to kosztuje mniej na instalacji i uruchomieniu (zarówno w nakładach inwestycyjnych, jak i operacjach operacyjnych) niż w urządzeniach do równoważenia obciążenia i można go skalować dalej prawie bez dodatkowych kosztów (w porównaniu z zakupem nowego, jeszcze więcej drogie urządzenie, gdy przerosniesz swój obecny model).
Pierwsza strategia: z zaporą ogniową
Przypuszczalnie masz kilka routerów, do których podłączone są łącza wysyłające twojego ISP. Twój dostawca usług internetowych zapewnia 2 linki (aktywne / pasywne, przy użyciu VRRP). Na routerach korzystasz także z VRRP i kierujesz ruch do sieci publicznej do zapory. Zapory ogniowe ( FW 1
i FW 2
poniżej) również są aktywne / pasywne i będą filtrować ruch i wysyłać każdy przepływ do zdrowego serwera frontendowego (do równoważników obciążenia HTTP FE 1
i FE 2
niższych).
+ -------------- + + -------------- +
| Router ISP A | | Router ISP B |
+ -------------- + + -------------- +
| |
== # ====================== # == (sieć publiczna)
| |
+ --------------- + + --------------- +
| Twój router A | | Twój router B |
+ --------------- + + --------------- +
| |
== # ===== # ========== # ===== # == (sieć prywatna RFC 1918)
| | | |
+ ------ + + ------ + + ------ + + ------ +
| FW 1 | | FE 1 | | FE 2 | | FW 2 |
+ ------ + + ------ + + ------ + + ------ +
Celem jest, aby przepływ wyglądał tak:
- ISP kieruje ruch do twoich adresów IP do twojego aktywnego routera.
- Twoje routery kierują ruch do VIP-a korzystającego z adresu RFC 1918 . Ten VIP jest własnością aktywnej zapory ogniowej, podobnie jak VRRP. Jeśli używasz OpenBSD do swoich potrzeb zapory ogniowej, możesz użyć CARP , nieopatentowanej alternatywy dla VRRP / HSRP.
- Twoja zapora ogniowa stosuje filtr (np. „Zezwól tylko 80 / tcp i 443 / tcp na ten konkretny adres IP”).
- Zapora działa również jako router i przekazuje pakiety do zdrowej nakładki.
- Twój interfejs kończy połączenie TCP.
Teraz magia dzieje się w krokach 4 i 5, więc zobaczmy bardziej szczegółowo, co robią.
Twoja zapora ogniowa zna listę frontendów ( FE 1
i FE 2
) i wybierze jeden z nich na podstawie określonego aspektu przepływu (np. Mieszając źródłowe IP i port, między innymi nagłówkami). Ale musi także upewnić się, że przekierowuje ruch do zdrowej nakładki, w przeciwnym razie zablokujesz ruch. Jeśli na przykład używasz OpenBSD, możesz użyć relayd
. Corelayd
robi jest proste: sprawdza poprawność wszystkich twoich nakładek (np. wysyłając im zapytanie HTTP z sondą), a ilekroć nakładka jest zdrowa, dodaje ją do tabeli używanej przez zaporę ogniową do wybierania następnego przeskoku pakietów danego przepływu . Jeśli interfejs nie przejdzie kontroli poprawności, zostanie usunięty ze stołu i żadne pakiety nie będą już do niego wysyłane. Podczas przesyłania pakietu do interfejsu użytkownika zapora zamienia docelowy adres MAC pakietu na adres wybranego interfejsu.
W kroku 5 pakiety od użytkownika są odbierane przez moduł równoważenia obciążenia (czy to Lakier, Nginx lub cokolwiek innego). W tym momencie pakiet jest nadal kierowany na twój publiczny adres IP, więc musisz aliasować swoich VIPów na interfejsie sprzężenia zwrotnego. Nazywa się to DSR (Direct Server Return), ponieważ twoje interfejsy kończą połączenie TCP, a zapora pomiędzy nimi widzi tylko ruch simpleks (tylko pakiety przychodzące). Router skieruje wychodzące pakiety bezpośrednio z powrotem do routerów usługodawcy internetowego. Jest to szczególnie dobre w przypadku ruchu HTTP, ponieważ żądania są zwykle mniejsze niż odpowiedzi, czasem znacznie większe. Żeby było jasne: nie jest to kwestia specyficzna dla OpenBSD i jest szeroko stosowana w witrynach o dużym natężeniu ruchu.
Gotchas:
- Użytkownicy końcowi będą łączyć się bezpośrednio z serwerami frontonu, ponieważ korzystasz z DSR. Być może już tak było, ale jeśli nie, musisz upewnić się, że są odpowiednio zabezpieczone.
- Jeśli korzystasz z OpenBSD, strzeż się, że jądro jest jednowątkowe, więc wydajność jednego rdzenia procesora ograniczy przepustowość zapory. Może to stanowić problem w zależności od typu karty sieciowej i wyświetlanej szybkości pakietów. Istnieją sposoby rozwiązania tego problemu (więcej na ten temat poniżej).
Druga strategia: bez zapory ogniowej
Ta strategia jest bardziej wydajna, ale trudniejsza do skonfigurowania, ponieważ zależy bardziej od specyfiki posiadanych routerów. Chodzi o to, aby omijać zaporę powyżej i pozwolić routerom wykonać całą pracę, którą wykonują zapory ogniowe.
Będziesz potrzebować routerów obsługujących listy ACL L3 / L4 na port, BGP i ECMP oraz routing oparty na zasadach (PBR). Tylko routery wysokiej klasy obsługują te funkcje i często mają dodatkowe opłaty licencyjne za korzystanie z BGP. Jest to zwykle nadal tańsze niż sprzętowe równoważenia obciążenia, a także znacznie łatwiejsze do skalowania. Dobrą rzeczą w tych routerach z wyższej półki jest to, że mają tendencję do liniowej szybkości (np. Zawsze mogą maksymalnie wykorzystać łącze, nawet na interfejsach 10GbE, ponieważ wszystkie decyzje, które podejmują, są podejmowane sprzętowo przez ASIC).
Na portach, na których masz łącza uplink ISP, zastosuj listę ACL, która była wcześniej w zaporze (np. „Zezwól tylko na 80 / tcp i 443 / tcp na ten konkretny adres IP”). Następnie poproś, aby każda z twoich nakładek utrzymywała sesję BGP z routerem. Możesz użyć doskonałego OpenBGPD (jeśli twoje nakładki są na OpenBSD) lub Quagga . Router będzie ECMP generował ruch do interfejsów, które są zdrowe (ponieważ utrzymują sesje BGP). Router będzie również odpowiednio kierował ruch przy użyciu PBR.
Udoskonalenia
- Dzięki rozwiązaniu pary zapory dobrze jest zsynchronizować stany TCP w zaporach, aby w przypadku awarii jednej zapory wszystko przeszło płynnie w drugą. Możesz to osiągnąć za pomocą
pfsync
.
- Pamiętaj, że
pfsync
zwykle podwaja szybkość pakietów w twoich zaporach ogniowych.
- HTTP jest protokołem bezstanowym, więc nie jest to koniec świata, jeśli zresetujesz wszystkie połączenia podczas przełączania awaryjnego zapory, ponieważ nie używasz
pfsync
.
- Jeśli przerosniesz pojedynczą zaporę, możesz użyć ECMP na routerze, aby skierować ruch do więcej niż jednej pary zapory.
- Jeśli używasz więcej niż jednej pary zapory, równie dobrze możesz ustawić je wszystkie jako aktywne / aktywne. Możesz to osiągnąć poprzez utrzymywanie przez zapory ogniowe sesji BGP z routerami, podobnie jak interfejsy muszą utrzymywać jeden w drugim projekcie bez zapór ogniowych.
Przykładowa relayd
konfiguracja
Zobacz także HOWTO na https://calomel.org/relayd.html
vip = "1.2.3.4" # Twój publiczny adres IP
# (możesz mieć więcej niż jeden, ale nie musisz)
fe1 = „10.1.2.101”
fe2 = „10.1.2.102”
fe3 = „10.1.2.103”
fe4 = "10.1.2.104" # Możesz mieć dowolną liczbę frontendów.
int_if = "em0"
tabela <fe> {$ fe1 retry 2, $ fe2 retry 2, $ fe3 retry 2, $ fe4 retry 2}
tabela <fallback> {127.0.0.1}
przekieruj webtraffic {
nasłuchuj na porcie 80 VIP
limit czasu sesji 60
trasa do <fe> sprawdź http „/healthcheck.html„ digest ”(sha1sum of healthcheck.html)„ interfejs $ int_if
}