Avro do Kafki - czy rzeczywiście przynosi korzyści?

0

Rozumiem, że skoro Confluent sobie wymyślił Schema Registry dla Avro to stara się rozpropagować używanie Avro jako jedyną właściwą drogę tylko nie dostrzegam w tym jakiś specjalnych korzyści. Jaką przewagę będzie miało avro ze Schema Registry nad takim rozwiązaniem:

producer:
Niech klasa Message posiada Body i Headers. Niech każdy możliwy Message jakie serwis może wysłać do brokera niech serwis udostępnia jako osobny, publiczny moduł. Niech każdy Headers posiada header eventId i version obowiązkowo. Niech body będzie serializowane z String json.

konsumer
deserializuje body do String json. Nie mapuje ich na obiekt. Handlery sobie sprawdzają kombinację eventId i version i jeśli akceptują to obsługują sobie Message. Dopiero te handlery mapują String jsona na odpowiedni obiekt.

@KafkaListener
void listen(@Payload String body, @Headers Map<String, String> headers) {
    handlers.stream()
        .filter(handler -> handler.test(headers))
        .forEach(handler -> handler.accept(body, headers));
}

Przewagi takiego rozwiązania nad avro Schema Registry jest taka, że definicję możliwych body trzymasz zapisane w javie a nie w tym dziwnym schemacie avro. Nie potrzebujesz dodatkowych serwisów Schema Registry. Nie walidujesz ich, bo nie musisz, sprawdzasz sobie jedynie headery. Nie musisz trzymać Backward Compatibility ani Forward. Masz wzorzec Chain of Responsibility za darmo dzięki czemu możesz mieć wiele handlerów do tego samego Message'a.

Co do wydajności to minisem jest to, że wiele handlerów może konsumować obiekt i każdy z nich będzie osobno mapował jsona na obiekt, do tego iterowanie po handlerach no i deserializowanie body odbywa się zawsze. (no ale zazwyczaj schemat Messagy jest przecież poprawny). Z drugiej strony Confluentowe sprawdzanie poprawności body ze schematem kosztuje (mimo że to byte[]) i robi to chyba przy każdej wiadomości, a jak już wspomniane zazwyczaj schemat Messagy jest przecież poprawny. Handlerów raczej jest mało. Body może być wielkie.

0

@LitwinWileński:

Nie wiem rozmawialiśmy czy nie, ale Avro wydaje mi się serializerem odsuwajacym się w niszę, popularniejszy jest Apache Thrift (serializer jako część stosu RPC) czy przypuszczalny zwycięzca tej rywalizacji Google Protocol Buffers (serializer) / gRPC (stos na podstawie)

One na jakimś ogólnym poziomie są mocno podobne.

A co się dzieje powyżej serializera, to dość oddzielna opowieść... co myślał poeta (z Confluent) Ci nie powiem

1

Zacznijmy od podstaw: ConfluentRegistrySchema nie jest tożsame z AVRO. Tj. może być tak, że trafią tam schemy z AVRO, ale może być również tak, że będziesz miał pole String, int, czy cokolwiek i tyle.

Jeśli chodzi o twoją "przewagę" to:

  • posiadając schemę biblioteka AVRO wygeneruje ci klasę (przy kompilacji), która nie będzie działała na refleksji, tylko na żywym obiekcie. To daje bardzo duży skok do wydajności.
  • sprawdzanie kompatybilności jest by-design. Dzięki temu unikasz sytuacji, w której producent wrzuci na kolejkę niezrozumiałą wiadomość dla reszty świata.
  • nie ma żadnych powodów, żeby nie stworzyć sobie deserializera, który najpierw sprawdzi headery, a dopiero potem zdeserializuje wiadomość
  • tak samo można wyłączyć sprawdzanie poprawności wiadomości przy odbiorze

Ogólnie wydaje mi się, że strasznie zafiksowałeś się na jeden konkretny przypadek użycia. AVRO (i zresztą wszystkie formaty, które mają schemy) trochę lepiej nadają się do pracy przy dużych systemach, w których na jedną kolejkę wiadomości wysyła kilkanaście systemów.

0

z tego co podałeś to tylko 1 argument daje przewagę, choć nie za barzdo rozumiem na czym polega skok tej wydajności, w sensie dlaczego ten skok ma się zadziać.

2 arg
w moim rozwiązaniu nie możesz wrzucić niezrozumiałej wiadomości, bo wiadomości budujesz z publicznych modułów serwisów.

3 arg
w moim rozwiązaniu też możesz, ale masz prościej

4 arg
no w moim też nie sprawdzasz poprawności

1
LitwinWileński napisał(a):

z tego co podałeś to tylko 1 argument daje przewagę, choć nie za barzdo rozumiem na czym polega skok tej wydajności, w sensie dlaczego ten skok ma się zadziać.

2 arg
w moim rozwiązaniu nie możesz wrzucić niezrozumiałej wiadomości, bo wiadomości budujesz z publicznych modułów serwisów.

Tak jak pisałem - fiksujesz się na jeden przypadek, który nazywasz "twoim rozwiązaniem". Nie mam pojęcia co rozumiesz przez "publiczne moduły serwisów" - tj. mamy jakiegoś JARa, który ogarnia wiadomości? A co, jeśli się zmieni schema format danych? To wtedy nagle wszystkie serwisy muszą zsynchronizować release? Czy jak?

3 arg
w moim rozwiązaniu też możesz, ale masz prościej

Nie wiem co to znaczy "masz prościej" bo nie znam twojego rozwiązania, które masz w głowie. W przypadku Kafka + AVRO po prostu tworzysz MyClassDeserializer<MyClass>, który zadziała jako dekorator dla AvroDeserializera z biblioteki AVRO i tyle. Boilerplate wyjdzie w sumie na 20-30 linijek, z czego spora część to po prostu wygenerowane nazwy metod i annotacje.

4 arg
no w moim też nie sprawdzasz poprawności

Tak. Natomiast twoim zarzutem było to, że sprawdzanie poprawności jest ciężkie - to można z tego co pamiętam jedną flagą wyłączyć.

0
wartek01 napisał(a):

Nie mam pojęcia co rozumiesz przez "publiczne moduły serwisów" - tj. mamy jakiegoś JARa, który ogarnia wiadomości? A co, jeśli się zmieni schema format danych? To wtedy nagle wszystkie serwisy muszą zsynchronizować release? Czy jak?

każdy mikroserwis wysyłający coś na kafkę składa się z 2 modułów:

  • public api
  • private service

w api masz klasy POJO, zdefiniowane wiadomości jakie produkuje serwis. Dzięki temu inne serwisy, które chcą skonsumować tę wiadomość importują sobie to publiczne api i nie muszą mieć swojego dtosa.
Jeśli coś się zmieni to tak jak pisałem podbijasz wersję wiadomości. Podbijasz też wersję api. Dopóki konsumerzy nie dostosują się do nowej wersji to będą ją odrzucać przy konsumowaniu.
Możes wysyłąć wszystkie wersje wiadomości naraz, a konsumer sobie wybierze które wersje chce zjeść.

1

Czyli twoje rozwiązanie całkowicie nie nadaje się do streamingu danych bo wygenerowałoby dodatkowy ruch sieciowy. Z drugiej strony małe zmiany, kompatybilne wstecz (jak dorzucenie opcjonalnego pola) doprowadziłyby do stopowania działania całych aplikacji. W przypadku opcji z rejestrem AVRO te problemy nie istnieją.

Dodatkowo całe Kafka Streams API przestaje mieć rację bytu.

0
wartek01 napisał(a):

Czyli twoje rozwiązanie całkowicie nie nadaje się do streamingu danych bo wygenerowałoby dodatkowy ruch sieciowy.

czemu ruch sieciowy?
ładujesz to api jako bibliotekę do dependencies a nie strzelasz do tych mikroserwisów po api

dodatkowy ruch sieciowy to właśnie przy avro ze SchemaRegistry masz.

1
LitwinWileński napisał(a):

czemu ruch sieciowy?

Zrozumiałem, że po prostu strzelasz do API.
W takim razie twoje rozwiązanie po prostu robi to, co masz przy AVRO, bez zalet AVRO. To samo uzyskasz tworząc klienta AVRO bez dorzucania ConfluentRegistry, jedynie pakując wszystkie klasy do oddzielnego JARa - co prowadzi właśnie do problemów z kompatybilnością.

dodatkowy ruch sieciowy to właśnie przy avro ze SchemaRegistry masz.

Ściągnięcie schemy do cache'a nie kwalifikuje się jako "nadmierny ruch sieciowy".

0

mi nie chodzi o samo avro tylko o avro + schema registry ech..

0

Ogólnie to nie tylko Java istnieje.

"Nie musisz trzymać Backward Compatibility"?

2

Są istotne różnice pomiędzy tymi trzema (avro, proto, thrift), już nie chce mi się książki przepisywać więc odsyłam do "Designing-data-intensive-applications" Chapter 4. Każdy z nich będzie lepszy lub gorszy w zależności od kontekstu

1
LitwinWileński napisał(a):

mi nie chodzi o samo avro tylko o avro + schema registry ech..

Mi też.
Jeśli zmiana jest kompatybilna wstecznie to przy odpowiednim oznaczeniu możesz podmienić konsumentów, a potem producentów. Jeśli zmiana jest kompatybilna w przód to przy dobrym ustawieniu możesz podmienić producentów, a potem konsumentów.
Przy twoim rozwiązaniu wszystko trzeba podmieniać na raz.

0

Jesli jest kompatybilna to nie musisz zmieniac wersji POJOsow

1

Jak kompatybilna? Wstecznie, do przodu, czy całkowicie?

0

Nie czytałem całego wątku, ale na pytanie postawione w temacie:

Uja a nie korzyści xd tylko przeszkadza

1 użytkowników online, w tym zalogowanych: 0, gości: 1