2013-05-31 2 views
7

Мы создаем приложение, используя LMAX Disruptor. При использовании Event Sourcing вы часто хотите сохранять периодические снимки вашей модели домена (некоторые люди называют это шаблоном Memory Image).Как сделать сериализацию снимков модели домена для получения источников событий

Мне нужно лучшее решение, чем то, что мы в настоящее время используем для сериализации нашей модели домена при съемке. Я хочу иметь возможность «красиво распечатать» этот моментальный снимок в читаемом формате для отладки, и я хочу упростить миграцию схемы моментальных снимков.

В настоящее время мы используем Googles' Protocol Buffers, чтобы сериализовать нашу модель домена в файл. Мы выбрали это решение, поскольку буферы протокола более компактны, чем XML/JSON, и использование компактного двоичного формата показалось хорошей идеей сериализации большой модели домена Java.

Проблема заключается в том, что буферы протокола были разработаны для относительно небольших сообщений, а наша модель домена довольно велика. Таким образом, модель предметной области не помещается в один большом иерархическом сообщении Protobuf, и мы в конечном итоге сериализации различных Protobuf сообщения в файл, например:

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 
    } 
    ... 
} 

Это раздражает, потому что манипулируя поток гетерогенных сообщений Protobuf является сложным , Было бы намного проще, если бы у нас было одно большое сообщение Protobuf, содержащий все наши модели предметной области, например:

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 

Если мы это сделаем, это легко prettyprint снимок: просто прочитать большое сообщение Protobuf, затем отпечатайте его с помощью protobuf's TextFormat. В нашем текущем подходе нам нужно читать разные сообщения protobuf по одному и красиво печатать их, что сложнее, так как порядок сообщений protobuf в потоке зависит от текущей схемы моментальных снимков, поэтому наш инструмент довольно печатной должен знать об этом.

Мне также нужен инструмент для переноса моментальных снимков в новую схему моментального снимка, когда наша модель домена развивается. Я все еще работаю над этим инструментом, но это сложно, потому что мне приходится иметь дело с потоком различных сообщений protobuf, вместо того, чтобы иметь дело с одним большим сообщением. Если бы это было просто одно большое сообщение, я мог бы: - взять файл моментального снимка - разобрать файл как большое сообщение protobuf Java, используя схему .proto для предыдущей версии моментального снимка - конвертировать это большое сообщение protobuf в большой protobuf сообщение для новой версии, используя Dozer и некоторый код сопоставления - напишите это новое сообщение protobuf в новом файле, используя схему .proto для новой версии

Но поскольку я имею дело с потоком сообщений протобуфа различных типы, мой инструмент должен обрабатывать этот поток в правильном порядке.

Так что, да ... Я думаю, мои вопросы:

  • Вы знаете, любой инструмент, который может сериализацию сериализовать большую модель предметной области в файл, без ограничений Protobuf в, возможно с использованием потокового видео, чтобы избежать OutOfMemorryErrors ?

  • Если вы используете источники событий или изображения памяти, что вы используете для сериализации вашей модели домена? JSON? XML? Protobuf? Что-то другое?

  • Мы делаем это неправильно? Есть ли у вас какие-либо предложения?

ответ

2

Просто от верхней части головы (фактически не зная, как большие файлы моментальных бы получить):

Вы пробовали библиотеку Gson JSON Google? Кажется, он обеспечивает как управление версиями (https://sites.google.com/site/gson/gson-user-guide#TOC-Versioning-Support), так и потоковое (https://sites.google.com/site/gson/streaming) для документов на основе JSON.

И теперь, когда мы говорим о JSON, как насчет сохранения моментальных снимков, например. CouchDB (http://en.wikipedia.org/wiki/CouchDB) документы?

JSON может занимать немного больше места, но его можно прочитать.

+1

Это может быть полезно или не полезно: http://contourline.wordpress.com/2012/01/18/how-big-is-too-big-for-documents-in-couchdb-some-biased-and -totally-unscientific-test-results/ – Jukka

+0

JSON - действительно подход, который мы могли бы использовать, и мне нравится использовать удобные для чтения форматы файлов. Но они решили использовать двоичный формат для сериализации, чтобы сэкономить место (до того, как я присоединился к проекту), и я не уверен, что хочу спорить о переключении на JSON, если он будет создавать проблемы позже по дороге, когда моментальный снимок станет слишком большой ... Я обдумываю это, но меня тоже интересуют другие подходы. Если кто-то ответит, что он использует JSON в своем проекте Source Source с огромной моделью домена, это может помочь мне аргументировать JSON :) Если мы в конечном итоге выберем JSON, я буду настаивать на GSON, так как мне нравится эта библиотека :) –

+1

Посмотрите также на BSON и MongoDB: http://docs.mongodb.org/manual/core/document/ – Jukka

1

Лучший список вариантов, которые я вижу здесь: https://github.com/eishay/jvm-serializers/wiki. Вам нужно будет сделать несколько быстрых тестов, чтобы узнать, что быстро для вас. Что касается потоковой передачи, мне придется просматривать каждую из библиотек в этом списке.

Не уверен, что я понимаю, проблема с печатью. Нет необходимости решать эффективную сериализацию и красивую печать с использованием той же технологии, так как, безусловно, довольно печатная работа не должна выполняться суперэффективно. Если у вас уже есть javabean-представление, я бы, вероятно, перезагрузил данные в beans, а затем использовал Jackson для печати данных в JSON.

Что касается управления версиями/миграциями, вы уже решили проблему с запуском новой версии кода, на котором запущена новая модель домена? Если да, то почему бы просто не создать новый моментальный снимок после запуска новой версии?

+0

Мы хотим довольно печатать для целей отладки, например чтобы убедиться, что что-то было неправильно сериализовано в нашем снимке.Все в порядке, если сама сериализованная форма не является довольно печатной, если у нас есть инструмент, который может отображать содержимое моментального снимка. Перезагрузка данных в объектах модели домена и печать с использованием Джексона действительно являются решением (я фактически рассматривал XStream, так как он поддерживает ссылки на круглые объекты). При переносе версий мы планируем остановить сервер, перенести моментальный снимок, перезапустить сервер с использованием нового моментального снимка и воспроизвести полученные события между ними. –

+0

Получил это. Я буду обновлять свой ответ на основе этой информации и нескольких новых предположений. – jtoberon

5

Как я могу определить решение проблемы, разделив «спецификацию» с «синтаксисом передачи». Теперь, когда мы определили наши спецификации сообщений, нам нужно работать над представлением проводной линии, которое может поддерживать различные потребности, варьирующиеся между эффективностью машины и удобочитаемостью человека.

  • двоичный режим - не менее многословный, но не читаемый человек
  • характера - что представляет команды и PARAMS является более удобными для чтения, а также обеспечивают надежное средства хранения
  • ясного текст - скажем, для отладки цели

решение должно обеспечивать переключаемое поведение. Мы можем основывать наше решение на ASN.1 и соответствующем наборе инструментов, который является агностиком языка и платформы, хотя богатая экосистема доступна с Java (Bouncycastle et al). Мы использовали его с довольно большими сообщениями по сети без каких-либо известных проблем :)

Надеюсь, что это дает некоторые указатели.

+0

Мой идеальный ответ был бы у кого-то, кто столкнулся с подобной проблемой (моментальные снимки при поиске источников) и мог бы описать его решение. Но щедрость истекает через 15 минут, и ваш ответ, в то время как теоретик, дал мне больше пищи для размышлений, поэтому я дам вам щедрость :) Я буду ждать других ответов, прежде чем «принять ответ». –