W Apache Flink watermark sygnalizuje postęp czasu zdarzeń, a jawny bufor może porządkować rekordy według ich znaczników czasu dla każdej sesji. W opisywanym rozwiązaniu Cisco zastosowało właśnie taki bufor; to odrębny mechanizm od sygnalizowania postępu przez watermarki.

Dlaczego kolejność zdarzeń ma znaczenie

Potok Cisco pobiera zdarzenia z Apache Kafka i analizuje kolejne etapy połączenia, takie jak auth, assoc, dhcp i dns. Rekord może dotrzeć później niż inne zdarzenie, które w rzeczywistości nastąpiło po nim. Jeśli aplikacja uzna kolejność nadejścia za kolejność zdarzeń, może błędnie ocenić przebieg połączenia. Cisco podało, że w pierwotnym rozwiązaniu zdarzenia poza kolejnością prowadziły do fałszywych informacji o udanym połączeniu. Firma wskazała też dostęp do stanu w RocksDB i rejestrowanie timerów przy każdym zdarzeniu jako obciążenie ścieżki przetwarzania. Cisco opisuje ten przypadek.

Czas zdarzenia (event time) to czas, w którym zdarzenie wystąpiło. Czas przetwarzania (processing time) opiera się na zegarze systemowym maszyny wykonującej obliczenia. Watermark sygnalizuje postęp w czasie zdarzeń, dzięki czemu operator może przesunąć obliczenia zależne od czasu do określonego punktu. Tak Apache Flink opisuje czas i watermarki.

W rozwiązaniu Cisco kolejność ustala natomiast jawne sortowanie rekordów zgromadzonych dla sesji. Watermark i bufor są powiązane z obsługą czasu zdarzeń, ale pełnią różne role w opisanym projekcie: pierwszy sygnalizuje postęp, drugi porządkuje rekordy w obrębie sesji.

Jak Cisco sortowało zdarzenia i odtwarzało stan

Cisco opisało wariant wykorzystujący KeyedProcessFunction oraz HashMap przechowujący zdarzenia dla danej sesji. Przed analizą łańcucha połączenia rekordy były sortowane według czasu zdarzenia, a nie czasu nadejścia. Bufor znajdował się na stercie JVM, poza stanem zarządzanym przez Flink.

Podczas checkpointu Cisco kopiowało zawartość bufora do ListState, a po restarcie odtwarzało ją z tego stanu. Sam checkpoint stanu aplikacji nie wystarcza jednak do zapewnienia przetwarzania dokładnie raz od początku do końca: znaczenie ma również to, jak sink, czyli komponent zapisujący wynik, obsługuje ponownie odtworzone dane. Cisco wskazuje tę zależność w opisie implementacji.

Limity pamięci i wyniki podane przez Cisco

Ponieważ bufor działał na stercie JVM, Cisco zastosowało kilka zabezpieczeń: usuwało bezczynne sesje po trzech minutach, ograniczało rejestrację timerów, używało kompaktowych obiektów POJO i parsowało pola przy przyjęciu zdarzenia. Firma podała również, że uruchamiała nowy wariant równolegle z pierwotnym na danych produkcyjnych przez pięć miesięcy. W tym okresie pierwotna wersja pozostawała domyślna, a widoczność wyników kontrolowały flagi funkcji.

Cisco podało przepustowość 200 000 wiadomości na sekundę dla opisanego potoku połączeń. Po okresie równoległego działania firma zmieniła domyślne tematy i usunęła rozgałęzienia starej i nowej logiki z interfejsu, serwera panelu oraz warstwy zapytań ClickHouse. Cisco poinformowało, że wdrożenie Flink działało w Kubernetes na Amazon EKS.