2013-05-31 2 views
7

LMAX Disruptor을 사용하여 응용 프로그램을 빌드하고 있습니다. Event Sourcing을 사용할 때 도메인 모델의주기적인 스냅 샷을 유지하려는 경우가 있습니다 (일부 사람들은 이것을 Memory Image 패턴이라고합니다).이벤트 소싱을 위해 도메인 모델 스냅 샷을 serialize하는 방법

스냅 샷을 만들 때 도메인 모델을 직렬화하기 위해 현재 사용중인 솔루션보다 더 나은 솔루션이 필요합니다. 디버깅을 위해이 스냅 샷을 읽기 쉬운 형식으로 "예쁘게 인쇄"할 수 있기를 원하며 스냅 샷 스키마 마이그레이션을 단순화하고 싶습니다.

현재 우리는 도메인 모델을 파일로 직렬화하기 위해 Googles' Protocol Buffers을 사용하고 있습니다. 프로토콜 버퍼는 XML/JSON보다 더 작기 때문에 압축 된 바이너리 형식을 사용하면 큰 Java 도메인 모델을 직렬화하는 것이 좋은 것처럼 보였으므로이 솔루션을 선택했습니다.

문제는 프로토콜 버퍼가 상대적으로 작은 메시지 용으로 설계되었으며 도메인 모델이 상당히 크기 때문입니다. 그래서 도메인 모델은 하나의 큰 계층 protobuf 메시지에 맞지 않는, 우리는이 같은 파일에 다양한 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 
    } 
    ... 
} 

.

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 메시지가 있다면 그것은 훨씬 쉽게 될 것이다 protobuf의 TextFormat을 사용하여 미리 인쇄하십시오. 현재의 접근 방법을 사용하면 다양한 protobuf 메시지를 하나씩 읽고 예쁜 인쇄를하는 것이 더 어렵습니다. 스트림의 protobuf 메시지 순서가 현재 스냅 샷 스키마에 따라 다르므로 예쁜 인쇄 도구 그 사실을 알고 있어야합니다.

도메인 모델이 발전하면 스냅 샷을 새 스냅 샷 스키마로 마이그레이션하는 도구가 필요합니다. 나는 여전히이 도구로 작업하고 있지만 어려운 것은 하나의 큰 메시지를 다루는 대신 다양한 protobuf 메시지 스트림을 처리해야하기 때문입니다. 단지 하나의 커다란 메시지라면, 다음과 같이 할 수 있습니다. - 스냅 샷 파일을 가져옵니다. - 이전 스냅 샷 버전의 .proto 스키마를 사용하여 파일을 큰 Java protobuf 메시지로 구문 분석하십시오. -이 큰 protobuf 메시지를 큰 protobuf로 변환하십시오. Dozer 및 일부 매핑 코드를 사용하여 새 버전에 대한 메시지 -이 새 protobuf 메시지를 새 버전의 .proto 스키마를 사용하여 새 파일에 작성하십시오.

그러나 여러 가지 protobuf 메시지 스트림을 다루고 있으므로 유형을 사용하려면 내 도구가 올바른 순서로이 스트림을 처리해야합니다.

  • 당신은 아마도 OutOfMemorryErrors을 피하기 위해 스트리밍을 사용하여, protobuf의 제한없이, 파일에 큰 도메인 모델을 직렬화 수있는 직렬화 도구를 아십니까 :

    그래서, 그래 ... 난 내 질문이 생각 ?

  • 이벤트 소싱 또는 메모리 이미지를 사용하는 경우 도메인 모델을 serialize하기 위해 무엇을 사용합니까? JSON? XML? Protobuf? 다른 것?

  • 잘못 했습니까? 의견 있으십니까?그냥 내 머리의 상단에서 (실제로 스냅 샷 파일을 얻을 것 얼마나 큰 모르고)

답변

2

는 :

당신은 구글의 GSON JSON 라이브러리를 시도? JSON 기반 문서의 경우 버전 관리 (https://sites.google.com/site/gson/gson-user-guide#TOC-Versioning-Support)와 스트리밍 (https://sites.google.com/site/gson/streaming)을 제공하는 것으로 보입니다.

이제 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 전체적으로 - 비 과학적 테스트 결과/ – Jukka

+0

JSON은 실제로 우리가 사용할 수있는 접근 방식이며 사람이 읽을 수있는 파일 형식을 사용하는 것을 좋아합니다. 그러나 그들은 (프로젝트에 참여하기 전에) 공간을 절약하기 위해 직렬화에 바이너리 형식을 사용하기로 결정했습니다. 나중에 스냅 샷이 될 때 문제가 발생할 경우 JSON으로 전환한다고 주장하고 싶지 않습니다. 너무 커서 ... 나는 그것을 고려하고 있지만 다른 접근법에도 관심이있다. 누군가가 거대한 도메인 모델로 자신의 이벤트 소스 프로젝트에서 JSON을 사용하면 JSON에 대해 논쟁하는 데 도움이 될 것입니다. JSON을 선택하게되면이 라이브러리를 좋아하기 때문에 GSON을 푸시합니다. –

+1

BSON과 MongoDB도 살펴보십시오. http://docs.mongodb.org/manual/core/document/ – Jukka

1

가장 좋은 옵션 목록은 여기에 있습니다 : https://github.com/eishay/jvm-serializers/wiki. 빠른 결과를 보려면 빠른 테스트를해야합니다. 스트리밍에 관해서는이 목록에있는 각 라이브러리를 살펴 봐야합니다.

꽤 인쇄 문제를 잘 모르겠습니다. 확실히 똑같은 기술로 효율적인 직렬화와 예쁜 인쇄를 해결할 필요는없는 것 같습니다. 확실히 인쇄가 효율적으로 효율적으로 수행 될 필요가 없기 때문입니다. 이미 javabean 표현이 있다면 콩에 데이터를 다시로드 한 다음 Jackson을 사용하여 데이터를 JSON으로 인쇄하십시오.

버전 관리/마이그레이션과 관련하여 새 도메인 모델을 실행하는 코드의 새 버전을 시작하는 방법에 대한 문제를 이미 해결 했습니까? 그렇다면 새 버전이 시작된 후 새 스냅 샷을 만드는 것이 어떻습니까?

+0

디버깅 목적으로 예쁜 인쇄를 원합니다. 우리의 스냅 샷에서 어떤 것이 잘못 직렬화되었는지 확인하십시오.스냅 샷의 내용을 표시 할 수있는 도구가있는 경우 직렬화 된 양식 자체가 예쁘게 인쇄되지 않는 것이 좋습니다. 데이터를 도메인 모델 객체에 다시로드하고 Jackson을 사용하여 인쇄하는 것은 실제로 솔루션입니다 (순환 객체 참조를 지원하므로 실제로 XStream을 고려했습니다). 버전을 마이그레이션 할 때 서버를 중지하고 스냅 샷을 마이그레이션하고 새 스냅 샷을 사용하여 서버를 다시 시작한 다음 그 사이에받은 이벤트를 재생할 계획입니다. –

+0

알았어요. 이 정보와 몇 가지 새로운 가정을 바탕으로 내 대답을 업데이트하겠습니다. – jtoberon

5

문제에 대한 해결책을 정의하는 방법은 '사양'과 '전송 구문'을 분리하는 것입니다. 이제 우리는 기계 효율과 사람의 가독성 사이에서 다양한 요구를 지원할 수있는 유선 회선에 대해 작업해야하는 메시지 사양을 정의했습니다.

  • 바이너리 모드 - 이상 자세한하지만 사람이 읽을 수 없습니다
  • 문자 - 명령, params가 더 읽기이며, 또한 강력한 스토리지를
  • 일반 텍스트를 제공 나타냅니다 - 디버그 목적으로 말을

솔루션은 전환 가능한 동작을 제공해야합니다. Java와 함께 풍부한 생태계를 사용할 수 있지만 (ASN.1) 및 언어와 플랫폼에 상관없이 관련 도구 세트를 기반으로 솔루션을 기반으로 할 수 있습니다 (Bouncycastle 외). 우리는 알려진 문제없이 네트워크를 통해 상당히 큰 메시지 얼룩과 함께 사용했습니다.

희망 사항이 있습니다.

+0

나의 이상적인 대답은 비슷한 문제 (이벤트 소싱의 스냅 샷)가 발생하여 그의 솔루션을 설명 할 수있는 사람으로부터 왔을 것입니다. 하지만 현상금은 15 분 만에 만료되고, 당신의 대답은 이론이면서 생각에 가장 많은 음식을주었습니다. 그래서 나는 당신에게 현상금을 줄 것입니다. 나는 대답을 받기 전에 다른 대답을 기다릴 것입니다. –

관련 문제