이벤트 아키텍처
이벤트 아키텍처 (EDA)
1) 이벤트 인 이유와 EDA 이유
이벤트-도메인에서 이미 발생한 변하지 않는 사실 ("PlayerVerified", "PaymentCaptured"). EDA는 이러한 사실의 출판과 그에 대한 반응을 중심으로 통합을 구축합니다
서비스의 연결성이 약합니다
소비자를 독립적으로 확
프로젝션의 재생/재 배열,
투명한 감사.
EDA는 동기식 API를 취소하지 않습니다. 서비스 간 종속성을 비동기 계층으로 가져 와서 보완합니다.
2) 이벤트 유형
도메인: 중요한 비즈니스 사실 (OrderPlaced, BonusGranted).
통합: 외부 시스템의 "스냅 샷 "/변경 (사용자 업데이트, WalletBalanceChanged).
기술: 수명주기 및 원격 측정 (Heartbeat, PipelineFailed).
명령 (이벤트가 아니라 근처): "do X" (CapturePayment) 명령.
추천: 도메인 이벤트가 기본입니다. 통합은 특정 소비자에 대한 예측에 의해 형성됩니다.
3) 이벤트 계약 및 스키마
확인: Avro/Proto/JSON Schema + Schema Registry; 호환성 전략: 소비자 진화를위한 'BACKWARD', 중요한 주제에 대한 'FULL'.
CloudEvents (id, 소스, 유형, 시간, 주제, 데이터 콘텐트 타입) - 균일 한 헤더.
필요한 메타 데이터: '이벤트 _ id' (ULID/UUI), 'arched _ at', 'producer', 'skima _ version', 'correlation _ id '/' causation _ id', 'idempotency _ key'.
버전 지정: 추가 전용 필드, 이름 변경/시맨틱 브레이크 금지; 새로운 유형-새로운 테마/유형.
json
{
"type":"record","name":"PaymentCaptured","namespace":"events.v1",
"fields":[
{"name":"event_id","type":"string"},
{"name":"occurred_at","type":{"type":"long","logicalType":"timestamp-micros"}},
{"name":"payment_id","type":"string"},
{"name":"amount","type":{"type":"bytes","logicalType":"decimal","precision":18,"scale":2}},
{"name":"currency","type":"string"},
{"name":"player_id","type":"string"}
]
}
4) 배송, 주문 및 일관성
적어도 한 번은 기본 → 핸들러 demempotency가 필요합니다.
주문: 파티 (Kafka) 또는 큐 (RabbitMQ) 내에서 보장되지만 퇴각으로 인해 파손 될 수 있습니다. 이벤트 키는 순서의 도메인 과립 (예: 'player _ id') 을 반영해야합니다.
일관성: 돈/대출-잡지/사가/보상을 통해서만; LWW를 피하십시오.
읽기 모델: 프로젝션과 캐시는 최종적으로 "진행중인 업데이트"... 를 표시하고 엄격한 경로에 RNOT 전략을 사용합니다.
5) 전송/받은 편지함... CDC
편지함: 서비스는 데이터베이스와 아웃 박스 테이블에 하나의 트랜잭션 → 작업자가 버스에 게시합니다.
받은 편지함: 중복 제거를위한 처리 결과가있는 소비자 상점 '이벤트 _ id'.
CDC (데이터 캡처 변경): 데이터베이스에서 버스로의 변경 흐름이 응용 프로그램 변경없이 통합을 구축합니다.
이념성: 'dedempotency _ key '/' event _ id' 로 처리하면 고정 될 때까지 외부 세계를 변경하지 않습니다.
6) CQRS 온라인 이벤트 소싱
CQRS: 별도의 쓰기 모델과 읽기 프로젝션; 프로젝션은 이벤트로 구성되며 뒤쳐 질 수 있습니다.
이벤트 소싱: 집계 상태 = 이벤트 롤업. 장점: 전체 감사/재생; 단점: 마이그레이션/체계/스냅 샷의 복잡성.
연습: ES-모든 곳이 아니라 역사와 보상이 중요한 곳; CQRS-거의 항상 EDA에 있습니다.
7) 사가: 오케스트레이션 및 안무
오케스트레이션: 코디네이터는 명령을 보내고 응답 이벤트를 기다립니다. 복잡한 프로세스에 편리합니다 (KYC → 예금 → 보너스).
안무: 서비스는 서로의 사건에 반응합니다. 더 쉽지만 추적하기가 어렵습니다.
항상 보상 및 단계 마감일을 정의하십시오.
8) 토폴로지 디자인 (Kafka/RabbitMQ)
카프카
도메인 이벤트 당 주제: '결제. 캡처. v1 ',' 플레이어. 확인되었습니 v1 '.
파티션 키: 'player _ id '/' wallet _ id' -순서가 중요한 곳.
'복제. factor = 3 ',' min. 동기화되지 않았습니다. 복제본 = 2 ', 생산자' acks = all '.
보존: 시간별 (예: 7-90 일) 및/또는 압축 (키별로 마지막 상태).
백오프와 함께 재 시도 및 DLQ 주제.
RabbitMQ
교환: '주제 '/' 직접', 라우팅 키 '지불. 캡처. v1 '.
넓은 팬 아웃- '주제' + 여러 대기열의 경우; RPC/명령 용-별도의 대기열.
HA를위한 정원 대기열; 배상을위한 TTL + 데드 레터 교환.
9) 관찰 및 SLO EDA
SLI/SLO:- 엔드-투-엔드 대기 시간 (발생 _ at → 처리): p50/p95/p99.
- 지연/연령: 소비자 지연 (Kafka 소비자 지연, 토끼 백 로그 연령).
- 처리량 출판/처리.
- DLQ 속도 및 반복 비율.
- 비즈니스 거래의 성공 (예: "증착 확인
- 'trace _ id '/' correlation _ id' (OTel) 를 통한 이벤트의 상관 관계
- 정렬 → 메트릭의 인스턴스.
- 화상 경보가 포함 된 대시 보드 "생산자 → 중개자 → 소비자".
10) 재생, 보존 및 백필
프로젝션/수정 버그를 재구성하기 위해 재생: 새로운 프로젝션/공간으로 운전 한 다음 읽기를 전환하십시오
보존: 법률/사업 요건 (GDPR/PCI); 민감한 필드-암호화 및/또는 토큰 화.
백필: 일회성 테마/대기열, 제품을 방해하지 않도록 명확한 RPS 제한.
11) 안전 및 준수
내부 클라이언트를위한 TLS 대중 교통, mTLS.
승인: 주제 당/교환 당 ACL; 네임 스페이스/호스트를 통한 멀티 테넌시.
PII: 이벤트에서 필드를 최소화합니다. 봉투 메타 데이터는 별도로, 필요한 경우 페이로드가 암호
이벤트에 대한 감사 액세스는 "모든 강력한" 키를 금지합니다.
보존 및 삭제 권리 (GDPR) 정책: 데이터 참조 또는 묘비 이벤트를 저장하고 예측에서 삭제합니다.
12) EDA 테스트
계약 테스트: 소비자는 체계 (소비자 중심) 에 대한 기대치를 검증합니다.
재생 테스트: 새로운 핸들러/스키마 버전을 통해 히스토리 샘플링을 실행하십시오.
혼돈 시나리오: 중개인 지연/손실, 노드 감소, 소비자 지연 → SLO가 남아 있습니다.
CI에서의 연기: 시간 테마에 대한 짧은 엔드 투 엔드 파이프 라인.
13) "CRUD 통합 → EDA" 마이그레이션
1. 도메인 사실을 식별하십시오
2. 소스 서비스에 아웃 박스가 포함되어 있습니
3. 최소 도메인 이벤트를 게시하고 1-2 프로젝션을 연결하십시오.
4. 점차 포인트 동기식 통합을 비활성화하여 구독으로 대체합니다.
5. 스키마 등록 및 호환성 정책을 입력하십시오
6. 필드가있는 추가 전용 이벤트 연장; 새로운 유형을 통해서만 중단됩니다.
14) 반 패턴
이벤트 = "DTO API" (너무 뚱뚱하고 내부 모델에 따라 다름) -소비자를 해체하십시오.
스키마 등록 부족 및 호환성 부족 - "깨지기 쉬운" 통합.
코드에서 게시하고 데이터베이스로 작성하는 것은 원자가 아닙니다 (아웃 박스 없음). 이벤트를 잃습니다.
"모든 곳에서 정확히 한 번" -이익없이 높은 가격; 적어도 한 번은 + demempotency가 더 좋습니다.
하나의 "범용" 파티션 키 → 핫 파티션.
프로덕션 프로젝션으로 바로 재생하십시오-온라인 SLO를 중단하십시오.
15) 구현 점검표 (0-45 일)
0-10 일
Schema Registry를 배포하고 호환성 전략을 승인하십시
도메인 이벤트와 해당 키 (순서의 과립) 를 식별합니다.
1-2 서비스에 아웃 박스/받은 편지함 추가; 최소한의 CloudEvents 봉투.
11-25 일
다시 시도/DLQ, 백오프, 처리기의 demempotency를 입력하십시오.
대시 보드: 지연/연령/종료; 화상 경보.
이벤트 문서 (카탈로그), 소유자 및 스키마 검토 프로세스.
26-45 일
첫 번째 투영의 재생/재 배열; 런북 재생 및 백필.
보안 정책 (SL, ACL, PII), 보존, GDPR 절차.
중개인과 소비자를위한 정기적 인 혼란과 게임 일.
16) 성숙도 지표
도메인 이벤트의 100% 는 체계와 등록으로 설명됩니다.
인터페이스/받은 편지함은 모든 Tier-0/1 생산자/소비자를 대상으로
SLO: 목표 내 p95 엔드-투-엔드 대기 시간 및 소비자 지연은 99% 이상입니다.
재생/백필은 다운 타임없이 가능합니다. 확인 된 런북이 있습니다.
Versioning: 새로운 분야-깨지지 않고; 오래된 소비자는 떨어지지 않습니
보안: SL + mSL, 주제 당 ACL, 액세스 로그, PII/보존 정책.
17) 미니 스 니펫
카프카 프로듀서 (신뢰할 수있는 출판, 아이디어):properties acks=all enable.idempotence=true max.in.flight.requests.per.connection=1 compression.type=zstd linger.ms=5
소비자 핸들러 (demempotency, pseudocode):
python if inbox.contains(event_id): return # дедуп process(event) # побочные эффекты детерминированы inbox.commit(event_id) # atomically with side-effect commit_offset()
DLX를 통한 RabbitMQ 재시도 (아이디어):
- '큐: 작업' → nack → DLX 작업. 다시 시도합니다. 1m '(TTL = 60 년대) →' 작업 '으로 돌아갑니다. 추가 '5m/15m'.
18) 결론
EDA는 통합을 명확한 계약 및 관리 일관성을 갖춘 비즈니스 사실의 흐름으로 전환합니다. 스키마 + 레지스트리, 아웃 박스/받은 편지함, 주문 키, dememotent 처리기, SLO 및 관찰 가능성, 안전한 보존 및 재생 등 기초를 구축하십시오. 그런 다음 이벤트는 연약한 연결 및 야간 마이그레이션없이 스케일링, 분석 및 새로운 기능을위한 "진실의 원천" 이됩니다.