2013-05-31 11 views
7

Budujemy aplikację przy użyciu LMAX Disruptor. Podczas korzystania z Event Sourcing często chcesz przechowywać okresowe migawki swojego modelu domeny (niektórzy nazywają to wzorcem Memory Image).W jaki sposób należy serializować migawki modelu domeny w celu pozyskania zdarzeń?

Potrzebuję lepszego rozwiązania niż to, co obecnie używamy do serializacji naszego modelu domeny podczas robienia migawki. Chcę móc "ładnie wydrukować" tę migawkę w czytelnym formacie do debugowania i chcę uprościć migrację schematu migawek.

Obecnie używamy Googles' Protocol Buffers do przekształcania naszego modelu domeny do pliku. Wybraliśmy to rozwiązanie, ponieważ bufory protokołów są bardziej kompaktowe niż XML/JSON, a użycie kompaktowego formatu binarnego wydawało się dobrym pomysłem na serializację dużego modelu domeny Java.

Problem polega na tym, że bufory protokołów zostały zaprojektowane dla stosunkowo małych wiadomości, a nasz model domeny jest dość duży. Więc model domeny nie mieści się w jednym dużym hierarchicznej wiadomości Protobuf, a skończymy szeregowania różne komunikaty Protobuf do pliku, na przykład:

for each account { 
    write simple account fields (id, name, description) as one protobuf message 
    write number of user groups 
    for each user group { 
     convert user group to protobuf message, and serialize it 
    } 
    for each user { 
     convert user to protobuf message, and serialize it 
    } 
    for each sensor { 
     convert sensor to protobuf message, and serialize it 
    } 
    ... 
} 

Jest to irytujące, ponieważ manipulowanie strumień heterogenicznych wiadomości Protobuf jest skomplikowana . Byłoby o wiele łatwiej, gdybyśmy mieli jeden wielki wiadomość Protobuf który zawierał wszystkie nasze modelu domeny, na przykład:

public class AggregateRoot { 
    List<Account> accounts; 
} 

--> convert to big hierarchical protobuf message using some mapping code: 

message AggregateRootMessage { 
    repeated AccountMessage accounts = 1; 
} 

--> persist this big message to a file 

Jeśli to zrobimy, to łatwo prettyprint migawkę: wystarczy przeczytać duży wiadomość Protobuf, następnie wystarczy wydrukować go za pomocą protobuf's TextFormat. Przy naszym obecnym podejściu musimy czytać różne komunikaty protobuf jeden po drugim i ładować je, co jest trudniejsze, ponieważ kolejność komunikatów protobuf w strumieniu zależy od aktualnego schematu migawki, więc nasze ładne narzędzie do drukowania musi być tego świadomy.

Potrzebuję też narzędzia do migracji migawek do nowego schematu migawki, gdy nasz model domeny ewoluuje. Nadal pracuję nad tym narzędziem, ale jest to trudne, ponieważ muszę radzić sobie ze strumieniem różnych komunikatów protokołu protobuf, zamiast zajmować się tylko jedną dużą wiadomością. Gdyby to była tylko jedna wielka wiadomość, mógłbym: - pobrać plik migawki - przeanalizować plik jako dużą wiadomość protokołu Java, korzystając ze schematu .proto dla poprzedniej wersji migawki - przekształcić tę dużą wiadomość protobuf w dużą protobuf wiadomość dla nowej wersji, używając Dozera i kodu odwzorowującego - zapisz tę nową wiadomość protobuf w nowym pliku, używając schematu .proto dla nowej wersji

Ale ponieważ mam do czynienia ze strumieniem wiadomości protobuf różnych typy, moje narzędzie musi obsłużyć ten strumień we właściwej kolejności.

Tak, tak ... Myślę, że moje pytania są następujące:

  • Czy znasz jakieś narzędzie, które może serializacji serializowania duży model domeny do pliku, bez ograniczeń Protobuf, w razie potrzeby za pomocą przesyłania strumieniowego, aby uniknąć OutOfMemorryErrors ?

  • Jeśli używasz źródła zdarzeń lub obrazów pamięci, do czego służy serializacja modelu Twojej domeny? JSON? XML? Protobuf? Coś innego?

  • Czy robimy to źle? Masz jakieś sugestie?

Odpowiedz

2

Tylko z wierzchu głowy (bez faktycznie wiedząc, jak duże pliki migawkowe dostanie):

Czy próbowałeś bibliotekę Gson JSON Google? Wygląda na to, że dla dokumentów opartych na JSON zapewnia zarówno wersję (https://sites.google.com/site/gson/gson-user-guide#TOC-Versioning-Support), jak i streaming (https://sites.google.com/site/gson/streaming).

A teraz, gdy rozmawiamy z JSON-em, a może z przechowywaniem migawek w np. CouchDB (http://en.wikipedia.org/wiki/CouchDB) dokumenty?

JSON może zająć nieco więcej miejsca, ale jest czytelny.

+1

To może być lub może być nieprzydatne: http://contourline.wordpress.com/2012/01/18/how-big-is-too-big-for-documents-in-couchdb-some-brush-and -totally-unscientific-test-results/ – Jukka

+0

JSON jest rzeczywiście podejściem, z którego moglibyśmy skorzystać i uwielbiam używać formatów plików czytelnych dla człowieka. Ale zdecydowali się użyć formatu binarnego do serializacji, aby zaoszczędzić miejsce (zanim dołączyłem do projektu), i nie jestem pewien, czy chcę argumentować za przejściem na JSON, jeśli będzie to stwarzać problemy w dalszej części drogi, gdy migawka stanie się zbyt duży ... Rozważam to, ale interesują mnie również inne podejścia. Jeśli ktoś odpowie, że używa JSON-a na swoim projekcie Event Source z ogromnym modelem domeny, to może mi pomóc argumentować za JSON :) Jeśli w końcu wybierzemy JSON, będę naciskał na GSON, ponieważ uwielbiam tę bibliotekę :) –

+1

Zobacz również BSON i MongoDB: http://docs.mongodb.org/manual/core/document/ – Jukka

1

Najlepsza lista opcji, które widzę, to: https://github.com/eishay/jvm-serializers/wiki. Będziesz musiał wykonać szybkie testy, aby zobaczyć, co jest dla ciebie szybkie. Jeśli chodzi o streaming, musiałbym przejrzeć każdą z bibliotek na tej liście.

Nie jestem pewien, czy rozumiem problem drukowania. Nie wydaje się konieczne rozwiązywanie wydajnej serializacji i ładnego drukowania przy użyciu tej samej technologii, ponieważ z pewnością ładne drukowanie nie musi odbywać się w super wydajny sposób. Jeśli masz już reprezentację javabean, prawdopodobnie przeładowałbym dane do fasoli, a następnie użyłbym Jackson do wydrukowania danych do JSON.

Jeśli chodzi o wersjonowanie/migracje, czy rozwiązałeś już problem z uruchamianiem nowej wersji kodu, który uruchamia nowy model domeny? Jeśli tak, to dlaczego nie po prostu utworzyć nową migawkę po uruchomieniu nowej wersji?

+0

Chcemy ładnego drukowania do celów debugowania, np. aby zobaczyć, czy coś zostało nieprawidłowo zserializowane w naszym migawce.Jest dobrze, jeśli sama zserializowana wersja nie jest drukowana w dość prosty sposób, o ile mamy narzędzie, które może wyświetlać zawartość migawki. Ponowne wczytanie danych do obiektów modelu domeny i drukowanie za pomocą Jacksona jest rzeczywiście rozwiązaniem (właściwie rozważałem XStream, ponieważ obsługuje on odwołania do obiektów kołowych). Podczas migracji wersji planujemy zatrzymać serwer, przeprowadzić migrację migawki, zrestartować serwer przy użyciu nowej migawki i odtworzyć zdarzenia odebrane w międzyczasie. –

+0

Rozumiem. Zaktualizuję moją odpowiedź na podstawie tych informacji i kilku nowych założeń. – jtoberon

5

Sposób zdefiniowania rozwiązania problemu polega na oddzieleniu "specyfikacji" od "składni transferu". Teraz, kiedy zdefiniowaliśmy nasze specyfikacje komunikatów, musimy pracować nad reprezentacją linii telefonicznej, która może wspierać różne potrzeby, różniące się między wydajnością maszyny a ludzką czytelnością;

  • tryb binarny - najmniej gadatliwy ale nie czytelnej
  • charakter - że reprezentuje polecenia i params jest bardziej czytelny, a także zapewnia solidna STORAGE
  • wyraźny tekst - powiedzmy dla celów debugowania

rozwiązanie musi zapewniać przełączalne zachowanie. Możemy oprzeć nasze rozwiązanie na ASN.1 i powiązanym zestawie narzędzi, który jest agnostykiem zarówno językowym, jak i platformowym, chociaż bogaty ekosystem jest dostępny z Javą (Bouncycastle i inni). Użyliśmy go z dość dużymi blokami wiadomości w sieci bez znanych problemów :)

Mam nadzieję, że daje pewne wskazówki.

+0

Moja idealna odpowiedź byłaby od kogoś, kto napotkał podobny problem (migawki w pozyskiwaniu zdarzeń) i mógł opisać swoje rozwiązanie. Ale nagroda wygasa za 15 minut, a twoja odpowiedź, choć teoretyczna, dała mi najwięcej do myślenia, więc dam ci nagrodę :) Będę czekać na inne odpowiedzi przed "zaakceptowaniem odpowiedzi". –

Powiązane problemy