CQRS + 이벤트 소싱 : (정확한가) 명령은 일반적으로 지점 간 통신되고 도메인 이벤트는 pub / sub를 통해 통신됩니까?


12

나는 기본적으로 CQRS 의 개념 과 관련 개념에 대해 머리를 감싸려고합니다 .

CQRS가 메시징과 이벤트 소싱을 반드시 통합 할 필요는 없지만, 이러한 개념을 결합한 많은 예제 / 블로그 게시물에서 볼 수 있듯이 좋은 조합으로 보입니다.

무언가에 대한 상태 변경에 대한 유스 케이스가 주어지면 (SO에 대한 질문을 업데이트하는 것과 같이) 다음 흐름이 올바른 것으로 간주합니까 (모범 사례에서와 같이)?

시스템은 질문 집계 루트를 대상으로하는 UpdateQuestion 및 사용자 집계 루트를 대상으로하는 UpdateUserAction (작은 포인트 등)과 같은 두 개의 작은 명령으로 분리 될 수있는 집계 UpdateQuestionCommand를 실행합니다. 이들은 지점 간 메시징을 사용하여 비동기식으로 전송됩니다.

집합 루트는 자신의 일을하고 모든 것이 잘 진행되면 이벤트 이벤트 UpdateUpdate 및 UserActionUpdated가 발생합니다. 이벤트 업데이트에 아웃소싱 된 상태가 포함되어 있습니다.

이 이벤트는 또한 방송을 위해 펍 / 서브 대기열에 놓입니다. 모든 구독자 (읽기 뷰를 생성하는 하나 이상의 프로젝터가있을 수 있음)는이 이벤트를 자유롭게 구독 할 수 있습니다.

일반적인 질문 : 실제로는 명령이 지점 간 (즉 : 수신자가 알려져 있음)으로 전달되는 반면 이벤트는 브로드 캐스팅되는 것이 가장 좋습니다 (즉 : 수신자는 알려지지 않음)?

위와 같이 가정하면, 명령이 지점 간이 아닌 pub / sub를 통해 브로드 캐스트되도록하는 장점과 단점은 무엇입니까?

예를 들어, Saga를 사용하는 동안 명령을 브로드 캐스팅 하는 것이 문제가 될 수 있습니다. saga가 시작하는 데 참여하는 집계 루트를 모르기 때문에 집계 루트 중 하나가 실패 할 경우 Saga가 수행해야하는 중개 역할이 방해 받기 때문에 .

반면에, 방송 명령이 허용 될 때 장점 (유연성)이 보입니다.


잘 쓰여진 질문 btw.
Dav

답변:


19

면책 조항 : CQRS 세계에서 첫 번째 단계를 밟고 있지만 현재 문제에 대한 현재의 이해를 제공 할 수 있으며 다른 사람들이 확인하는지 확인할 수 있습니다. 아래에 적는 모든 내용은 "본다"라는 주제를 가지고 있으며 권한이 없습니다.

80 % 사건

귀하의 질문에 대답하기 위해, 명령은 실제로 일대일 업무입니다. 명령이 컨트롤러 (MVC webapp)에 들어가면 해당 컨트롤러는 명령 디스패처에게 하나의 적절한 명령 핸들러를 찾도록 요청하고 작업을 해당 핸들러로 위임합니다.

왜 게시하지 않습니까?

그것은 책임 의 문제입니다 . 무언가가 명령을 보내면, 그것이 성취 될 것이라는 기대 를 수반 합니다. 당신이 단순히 무언가를 집어 들고 행동하기를 간절히 바라고 희망한다면, 이것이 사실 일 것이라는 보장 은 없습니다 . 외삽 법으로, 여러 핸들러가 명령에 대해 수행하기로 결정하지 않았는지 여부를 알지 못해 동일한 변경 사항이 두 번 이상 적용될 수 있습니다.

반면에, 이벤트는 본질적으로 유익한 정보이며, 0 개, 2 개 또는 그 이상의 구성 요소가 특정 이벤트에 관심이있을 것으로 기대하는 것이 합리적입니다. 요청 된 변경을 수행하는 범위에는 실제로 신경 쓰지 않습니다.

이것은 실생활과 비교 될 수 있습니다. 세 명의 자녀가있는 경우, 방으로 들어가서 단순히 "욕실 청소"를 외치십시오. 두 번 수행하지 않을 경우 누군가가 의지 할 것임을 보장 할 수 없으며 (순종적인 자녀가있는 경우 ;-) 당신이하고 싶은 일을하도록 특정 아이를 배정한다면 더 나은 요금을받을 수 있습니다.

그러나 그 아이가 일을 마치면 "욕실이 청소되었습니다"라고 외치면 편리합니다.이를 닦고 싶어하는 모든 사람이 이제는 할 수 있음을 알 수 있습니다.


많은 의미가 있습니다. 탁월한 비유 :)
Geert-Jan

날 잃었 어 ..- When a command enters a controller (MVC webapp)? RESTful을 사용하고 있습니까? 또는 일부 하이브리드 API 엔드 포인트? 예를 들어 주시겠습니까?
Piotr Kula

@ppumkin은 명령을 실행할 때마다 웹 응용 프로그램에서 호출하는 WebAPI 끝점을 사용했습니다. 예 : 사용자가 게시물 댓글을 추가하려는 경우 웹 앱은에 POST 요청을 보냈습니다 example.com/api/Post/AddPostComment.
Dav

1

초기 시스템은 일반적으로 여러 대상 시스템이 명령을 처리하지 않을 것이라는 데 동의합니다.

  • 명령은 일반적으로 '보내고기도'하지 않습니다. 명령의 시작 시스템은 일반적으로 명령의 진행 및 결과가 발생함에 따라 비동기 피드백을 원합니다 (예 :와 같은 상태 이벤트 acknowledgement, 성공 completion또는 failure대상 시스템에 의해 게시 될 수 있음). 체계).
  • 여러 대상 시스템이 관련된 경우 시작 시스템은 명령에 대해 여러 가지 (모순 될 수있는) 결과를받습니다 (예 : 대상 1은 성공했지만 대상 2는 실패했습니다). 원래 명령의 실제 상태를 결정하는 데 추가 복잡성이 필요합니다 (예 : 모든 대상이 성공한 경우에만 명령 트랜잭션이 성공한 것으로 간주됩니까? 대상 중 하나가 실패한 경우 명령을 롤백하거나 성공한 대상에서 보상해야합니까? 기타.). 이는 개시 시스템과 목표 시스템 사이에 바람직하지 않은 결합 및 복잡성을 야기 할 것이다.

그러나 시스템간에 발행 된 명령을 '도청'하는 추가 (트랜잭션 적이 지 않고 일반적으로 상당히 '무차별적인') 소비자를 구독 할 수 있다는 장점이 여전히 있습니다.

  • 감사 목적
  • 계측 및 운영 지표 (예 : 부하, 비즈니스 분석 등)
  • 복잡한 이벤트 처리 또는 스트림 이벤트 처리 '도청 자'-이 시스템은 명령의 오류 또는 불규칙성을 감지 할 수 있으며 (예 : 명령 빈도 또는 명령과 이벤트의 다른 조합 사이의 상관 관계) 경보 또는 수정 조치 (종종 다른 유형의 명령의 형식).
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.