Jak uniknąć „ponownych burz” w usługach rozproszonych?

10

„Ponowna burza” jest powodowana, gdy klienci są skonfigurowani do ponawiania określonej liczby razy przed poddaniem się, zasada ponawiania jest konieczna, ponieważ utrata pakietów nastąpi podczas normalnego działania usługi.

Weź ten przykład:

Przykładowa architektura

Jeśli na przykład usługi jako całość zostały skalowane w celu obsługi 80 000 żądań na sekundę i działały przy około 80% wydajności, skok ruchu, który spowodował, że usługa otrzymywała 101 000 żądań na sekundę, spowodowałaby niepowodzenie 1000 takich żądań.

Kiedy zaczynają się zasady ponawiania, otrzymujesz ponad 1000 żądań, w zależności od tego, gdzie wykryto awarię, co spowodowałoby przesunięcie usługi jako całości do 102 000 żądań na sekundę - stamtąd twoja usługa przechodzi w spiralę śmierci, podwajając liczbę nieudanych żądań co sekundę.

Inne niż masowe nadmierne świadczenie usług poza prognozowaną transakcją szczytową, co byłoby nieefektywne. Jakie strategie możesz zastosować, aby uniknąć „ponownych prób burz”?

Richard Slater
źródło
Jeśli 100kQPS to 80% pojemności, to 101kQPS nie powinno skutkować awariami 1k, powinno skutkować zerowymi awariami - czy nie jest to powodem nadmiernej kontroli?
Adrian
@Adrian, masz rację, był to wymyślony przykład, aby wyjaśnić tę kwestię - starałem się być na tyle redukcyjny, aby wyjaśnić swój punkt bez nadmiernej abstrakcji. Poprawiłem „skalowane do obsługi 100 000” na „skalowane do obsługi 80 000”.
Richard Slater

Odpowiedzi:

7

To zależy od tego, czego próbujesz uniknąć.

Jeśli próbujesz uniknąć przerwy w działaniu czegoś, co jest usługą naprawdę krytyczną (myślę w kategoriach „ludzie umrą, jeśli moje wywołanie API nie zostanie odpowiednio obsłużone”), musisz po prostu budżet na ogromną nieefektywność, która pochodzą z nadmiernej rezerwy dedykowanych zasobów. I tak, muszą być dedykowane, przy czym żadne z tych elementów nie pozwala na gwałtowne wzrosty ruchu, przyspieszenie wielu usług spowodowałoby awarię.

W znacznie bardziej prawdopodobnym scenariuszu, w którym obniżenie poziomu usług byłoby niewygodne, można rozwiązać problem zarówno po stronie klienta, jak i serwera. Chociaż warto zauważyć, że logicznie niemożliwe jest rozwiązanie problemu dużego ruchu, ponieważ bez przetworzenia ruchu (który zużywa zasoby) nie możesz wiedzieć, czy jest to ponawianie, czy jest to ponawianie dla żądania, które się powiodło, ale zostało nieprawidłowo obsłużone przez klienta, czy to DDoS itp Ale może złagodzić skutki.

W kodzie klienta napisz rozsądną logikę ponownych prób, która ma górną granicę i mechanizm łagodnego niepowodzenia. W ten sposób nie wpychasz użytkowników w nieskończoną pętlę nieudanych próśb i po prostu dajesz im błąd, mówiąc im, aby spróbowali tego, co właśnie zrobili w krótkim czasie.

W przypadku infrastruktury po stronie serwera najprostszym rozwiązaniem jest ograniczenie. Twarde limity żądań, zwłaszcza jeśli możesz spróbować rozłożyć je logicznie na podstawie konkretnego przypadku użycia (np. Jeśli masz scentralizowaną usługę, podejmuj trudne decyzje, czy chcesz zacząć blokować odległe geograficznie żądania, które mogą powodować zawieszanie się wątków po stronie serwera? A może chcesz równomiernie rozdzielić nieuniknione, ale niewielkie przestoje? itp.) Zasadniczo sprowadza się to do tego, że celowe zwrócenie 503 z bramy jest o wiele tańsze niż pozwolenie na przesłanie żądania i wysłanie 504 tak czy siak. Zasadniczo zmuś klientów do zachowania w oparciu o to, co możesz obecnie podać i udziel poprawnych odpowiedzi, aby klienci mogli odpowiednio zareagować.

hvindin
źródło
5

Jednym ze sposobów zapobiegania burzom ponownym jest użycie mechanizmów wycofywania.

W sekcji „ Wycofanie implementacji przy ponownej próbie ” przewodnika Google App Engine Designing for Scale :

Kod może ponowić próbę w przypadku niepowodzenia, niezależnie od tego, czy wywołuje usługę, taką jak Cloud Datastore, czy usługę zewnętrzną za pomocą funkcji pobierania adresu URL lub interfejsu API Socket. W takich przypadkach należy zawsze wdrożyć losową politykę wykładniczego wycofywania, aby uniknąć problemu stada grzmotów . Należy również ograniczyć całkowitą liczbę ponownych prób i obsłużyć błędy po osiągnięciu maksymalnego limitu ponownych prób.

Większość interfejsów API GAE ma już domyślnie włączone takie mechanizmy / zasady wycofywania.

Dan Cornilescu
źródło
Dzięki, implementacja mechanizmów wycofywania jest świetną radą, zwykle wybieram konfigurowalne wykładnicze wycofywanie za pomocą bloku aplikacji do obsługi błędów przejściowych . Jednak przez ponad 5 lat doświadczenia operacyjnego w obsłudze aplikacji w dużej skali na platformie Azure, nawet z wykładniczymi wycofywaniami w miejscu, „ponawiaj burze” wciąż zdarzają się dość często - nigdy nie byłem w stanie znaleźć skutecznej strategii unikania ich.
Richard Slater,