NFsec Logo

Rozmowy przy Kafce #1

19/11/2018 w Administracja Brak komentarzy.  (artykuł nr 668, ilość słów: 740)

J

eśli chcemy odbyć krótką rozmowę o wydajności producenta kafki (w kontekście: logstash → kafka ← logstash → elasticsearch) musimy porozmawiać o dwóch rzeczach. Po pierwsze: opóźnieniu – ile czasu upłynęło od czasu wywołania metody send(), dopóki komunikat nie pojawi się na brokerze. Po drugie: przepustowości – ile wiadomości może wysłać producent do brokera na sekundę. Dlaczego musimy obawiać się o te dwie wartości? Jeśli procesowanie wiadomości zajmuje nam 10 milisekund (opóźnienie) to wyraźnie przepustowość jest ograniczona do 100 wiadomości na sekundę. Patrząc na to w ten sposób można dojść do wniosku, że im wyższe opóźnienie tym większa przepustowość. Jednak związek między opóźnieniem, a przepustowością nie jest tak trywialny.

Producent kafki pozwala na wysyłanie wiadomości w pakietach. Załóżmy, że ze względu na czasy połączeń w sieci przesyłanie pojedynczej wiadomości do brokera trwa 2 ms. Wysyłając jedną wiadomość na raz jej opóźnienie to wspomniane 2 ms i przepustowość producenta 500 wiadomości na sekundę. Przypuśćmy jednak, że nie śpieszy się nam zbytnio i możemy poczekać kilka milisekund i wysłać na raz większą partię wiadomości. Jeśli poczekamy 8 ms i uda nam się zgromadzić 1000 wiadomości to nasze opóźnienie sumarycznie będzie wynosić teraz 10 ms, ale nasza przepustowość wzrośnie do 100.000 wiadomości na sekundę! To główny powód, dla którego używa się zbiorczych pakietów wiadomości. Dając niewielkie opóźnienie nasza przepustowość jest 200 razy większa. Ten rodzaj kompromisu nie jest unikalny tylko dla Kafki. Stosuje go również Elasticsearch i inne rozwiązania aplikacyjne, a także sieci i podsystemy pamięci masowej (o czym jeszcze później).

Czasem opóźnienia i przepustowość współdziałają ze sobą nawet w zabawniejszy sposób. Możemy osiągać od kilkunastu do kilkudziesięciu ms opóźnienia przy przesyłaniu setek tysięcy wiadomości na sekundę lub kilku sekundowe przy przesyłaniu zaledwie kilku setek wiadomości. Dlaczego? Ponieważ ważne jest, aby zarówno producent i konsument tych wiadomości stale i nieprzerwanie zapewniały ciągłość przepływu (pierwszy podawał, drugi odbierał). Jeśli producent wrzuci, co jakiś czas małą paczkę wiadomości, którą konsument pochłonie od razu i nie będzie już dla niego więcej pracy – może odpytać się o kolejną porcję dopiero po określonym czasie włączając mechanizm backoff, czyli czas oczekiwania przed ponowną próbą. Dlatego ważne jest, aby zawsze zapewnić ciągłość przepływu danych – jeśli zależy nam na opóźnieniu. Istnieje kilka ustawień, które możemy modyfikować, aby poprawić opóźnienie lub przepustowość na poziomie producenta:

batch.size – jest to górny limit liczby wiadomości, które producent Kafki będzie próbował zebrać do pakietu przed wysłaniem – wyrażone w bajtach (domyślnie 16384 – 16 KB – czyli 16 wiadomości, jeśli każda będzie miała rozmiar 1 KB). Kafka może wysłać pakiet wiadomości zanim ten limit zostanie osiągnięty (więc opóźnienie nie zmieni się przez modyfikację tego parametru), ale zawsze będzie wysłany po osiągnięciu przyjętego limitu. Dlatego ustawienie zbyt niskiego limitu spowoduje zmniejszenie przepustowości bez poprawy opóźnień. Należy pamiętać, aby nie przesadzić z tą wartością, ponieważ możemy doprowadzić do wysycenia pamięci. Kafka zawsze przydzieli tyle pamięci, aby obsłużyć cały, zdefiniowany pakiet wiadomości – nawet jeśli wymagania dotyczące opóźnienia spowodują, że pakiety te będą do połowy puste pod względem ilości wiadomości.

linger.ms – określamy jak długo producent będzie czekał przed wysłaniem, aby umożliwić nagromadzenie większej ilości wiadomości w tym samym pakiecie. Zwykle producent w ogóle nie będzie czekać i po prostu wyśle wszystkie wiadomości zebrane podczas poprzedniego procesu wysyłania (2 ms w wcześniejszym przykładzie). Ja już wspomniałem – czasami jesteśmy skłonni troszkę dłużej poczekać, aby poprawić ogólną przepustowość kosztem nieco większego opóźnienia. W tym przypadku dostrojenie linger.ms do wyższej wartości będzie miało sens. Musimy mieć jednak na uwadze, że jeśli batch.size będzie za niski i zostanie wypełniony przed upływem czasu z ustawienia linger.ms – pakiet wiadomości zostanie wysłany wcześniej – dlatego rozsądnie jest dopasować do siebie te dwa ustawienia (obrazek #1 – zwiększenie linger oraz obrazek #2 – zwiększenie batch i zmniejszenie linger).

Poza dostrojeniem w/w parametrów możemy pokusić się o chęć uniknięcia czekania na wynik metody send() (czyli odpowiedzi od brokerów Kafki) i zamiast tego przesyłać dane w sposób ciągły. Możemy ignorować wynik (tylko jeśli powodzenie wysyłania, jak i same wiadomości nie są dla nas krytyczne!) poprzez ustawienie acks na wartość “0”, co spowoduje, że producent nie będzie czekać na żadne potwierdzenie z brokera. Oczywiście to również ma swoje odzwierciedlenie w opóźnieniu wiadomości (obrazek #3 – ustawienie ack = 0).

Więcej informacji: Tips for Improving Performance of Kafka Producer

Kategorie K a t e g o r i e : Administracja

Tagi T a g i : , , , , ,

Komentowanie tego wpisu jest zablokowane.