728x90
반응형
728x90
반응형
반응형

event driven architecture

정의:

  • EDA는 시스템 내의 이벤트를 통해 컴포넌트나 서비스 간의 통신을 관리하는 아키텍처입니다. 어떤 상태 변화나 동작이 발생하면 이벤트가 생성되고, 이를 기반으로 다른 컴포넌트들이 반응합니다.
  • EDA 이벤트를 통해 시스템 간 통신과 상호작용을 관리하는 데 초점을 맞추며, 컴포넌트 간의 느슨한 결합과 비동기 처리를 가능하게 합니다.

특징:

  • 비동기 통신: 이벤트는 비동기적으로 발행되고, 이를 처리하는 소비자들이 독립적으로 이벤트를 처리합니다. 이는 시스템의 느슨한 결합을 가능하게 합니다.
  • 루스 커플링: 이벤트 발행자와 소비자는 서로 직접적으로 알 필요가 없습니다. 이는 시스템 간의 의존성을 줄이고 유연한 확장성을 제공합니다.
  • 확장성: 새로운 이벤트 소비자를 쉽게 추가할 수 있고, 시스템의 각 구성 요소가 독립적으로 확장 가능합니다.
  • 리액티브 시스템: EDA는 시스템의 비동기적 반응성을 높여 실시간으로 변화에 대응할 수 있게 합니다.
  • EDA: 시스템 간의 비동기적 상호작용을 통해 최종 일관성(Eventual Consistency)을 유지할 수 있습니다. 메시지 손실이나 중복 처리 등은 메시징 시스템의 특성에 따라 다르게 처리될 수 있습니다.
  •  monolithic
    • 단일 데이터베이스
    • 트랜잭션 처리를 완벽하게 -> ACID
      • atomicity
      • consistency
      • isloation
      • durable
  • msa
    • 각 서비스마다 독립적인 데이터베이스(polyglot)
    • API를 통해 접근
    • atomicy, consistency를 완벽하게 지키기 힘듦 -> commit transaction 사용
      • 작업 단위가 정상적으로 끝났음을 알려줌
      • A 서비스: 최초에 대기상태로 저장 후 요청(카프카) -> B서비스: 수량 등을 확인하고 재고처리 후 confirm 메세지 발행(카프카; 메세지 종류는 상태에 따라 다르게 발생) -> A서비스: confirm message를 받아서 상태값을 변경
      • 롤백이나 취소 상태로 변경 용이 

event sourcing

정의:

  • Event Sourcing은 시스템의 상태를 데이터베이스에 직접 저장하지 않고, 상태 변화를 나타내는 모든 이벤트를 저장하고, 이 이벤트들을 순차적으로 재생(Replay)하여 현재 상태를 복원하는 아키텍처 패턴입니다.
  • Event Sourcing은 시스템의 상태 변화를 이벤트로 기록하여 현재 상태를 유지하고, 데이터의 변경 이력을 완벽하게 보존하는 데 중점을 둡니다.

특징:

  • 이벤트 저장: 애플리케이션의 모든 상태 변화는 이벤트로 표현되어 이벤트 스토어에 기록됩니다. 예를 들어, "계좌 개설", "잔고 추가", "잔고 인출"과 같은 이벤트들이 저장됩니다.
  • 현재 상태 재생: 현재 상태는 저장된 모든 이벤트를 순차적으로 재생하여 계산할 수 있습니다. 이를 통해 애플리케이션의 상태를 특정 시점으로 되돌리거나 복원할 수 있습니다.
  • 이벤트 불변성: 이벤트는 불변이며, 한번 기록된 이벤트는 변경되지 않습니다. 이는 감사(audit) 기록이나 상태 추적에 유리합니다.
  • CQS와의 결합: Event Sourcing은 일반적으로 CQRS 패턴과 함께 사용되며, 명령(Command)이 발생하면 이벤트로 기록하고, 이 이벤트를 통해 읽기 모델(Query)를 업데이트합니다.
  • Event Sourcing: 이벤트 로그가 시스템의 단일 진실 원천(Single Source of Truth)입니다. 모든 상태는 이벤트 로그를 통해 재구성될 수 있기 때문에 데이터 일관성이 매우 중요합니다.
  • 데이터의 마지막 상태만을 저장하는 것이 아닌, 해당 데이터에 수행된 전체 이력을 기록
    • 이벤트 자체를 발행, 끌어가서 알아서 처리
    • insert만 존재; update/delete 없음
  • 데이터 구조 단순
  • 데이터의 일관성과 트랜잭션 처리 가능
  • 데이터 저장소의 개체를 직접 업데이트 하지 않기 때문에 동시성 충돌 문제 해결 
  • 도메인 주도 설계(domain driven design)
    • aggregate; 데이터의 상태 값을 바꾸기 위한 방법 
    • projection; 현재 데이터 상태 값을 표시하기 위한 방법
  • 메세지 중심의 비동기 작업 처리
  • 단점
    • 모든 이벤트에 대한 복원; 시간
      • snapshot(중간 세이브포인트; 어느 순간 이후부터 히스토리 쌓기)
    • 다양한 데이터가 여러 조회
      • cqrs(command and query responsibility segregation)도입으로 해결 가능
        • 명령과 조회의 책임 분리
        • 상태를 변경하는 command
        • 조회를 담당하는 query


saga pattern

SAGA 패턴은 주로 비동기적으로 분산 트랜잭션을 관리하기 위해 사용됩니다. 이 패턴은 분산 시스템에서 트랜잭션 일관성을 유지하는 데 유용하며, 특히 데이터 일관성이 필요한 여러 서비스 간의 장기 실행 트랜잭션(Long-Running Transactions)에 적합합니다.

Saga는 여러 서비스에 걸쳐 진행되는 일련의 로컬 트랜잭션으로 이루어져 있습니다. 각 서비스가 자신의 트랜잭션을 성공적으로 처리하면, 다음 서비스가 트랜잭션을 진행하고, 만약 어느 한 서비스에서 트랜잭션이 실패하면 이전에 성공한 트랜잭션을 보상 트랜잭션을 통해 취소합니다.

  • 구현방식: 어플리케이션에서 트랜젝션 처리하는 방식에 따라서 choreography, orchestration 방식으로 구분됨 
    • 어플리케이션이 분리된 경우에는 각각의 local transaction만 처리
  • 각 어플리케이션에 대한 연속적인 트랜젝션에서 실패할 경우
    • 롤백 시 모든 값을 원상복구해야하는데, 관련한 롤백 처리 구현 -> 보상 트랜젝션이 준비되어 있음.
  • 데이터의 원자성을 보장하지 않지만 일관성을 보장 

내 할일만 잘하면 됨

장점

  • 탈결합: 서비스가 이벤트를 통해 통신하므로 독립적으로 발전할 수 있습니다.
  • 확장성: 각 서비스가 자체 트랜잭션을 관리하므로 수평적으로 확장이 가능합니다.
  • 회복력: 부분적인 실패와 보상을 허용하여 시스템 회복력을 높일 수 있습니다.

단점

  • 복잡성: 여러 서비스 간에 발생하는 이벤트 흐름을 추적하기 어려워지며, 트랜잭션 경로가 복잡해질 수 있습니다.
  • 최종 일관성(Eventual Consistency): 사가는 즉각적인 일관성을 보장하지 않으며, 시간이 지남에 따라 데이터가 일관성을 갖도록 합니다.
  • 오류 처리: 강력한 오류 처리 및 보상 로직 구현이 어려울 수 있습니다.

 

choreography-based saga

  1. 비동기 메시징:
    • 코레오그라피 사가는 각 서비스가 이벤트를 발행하고, 다른 서비스들이 이 이벤트를 구독하여 작업을 수행(상태를 조정)하는 방식으로 진행됩니다. 이 과정은 비동기로 이루어지며, 각 서비스는 서로의 상태를 직접 알지 않고 이벤트를 통해 통신합니다. 확장성이 높음
  2. 자율성:
    • 각 서비스는 스스로/독립적으로 행동하며, 다른 서비스와의 상호작용을 이벤트로만 처리합니다. 이러한 자율성 덕분에 서비스 간의 결합도가 낮아지고, 시스템의 유연성이 증가합니다.
  3. 상태 관리:
    • 코레오그라피 사가는 각 서비스가 자신의 상태를 관리합니다. 서비스는 다른 서비스의 상태에 의존하지 않고, 이벤트에 따라 자신의 행동을 결정합니다.
  4. 장애 복구:
    • 장애 발생 시 각 서비스는 발행된 이벤트에 따라 적절한 복구 작업을 수행할 수 있습니다. 실패한 작업을 롤백하기 위한 이벤트를 수신하고 처리할 수 있기 때문에 전체 시스템의 복원력을 높일 수 있습니다.

SAGA Choreography의 장점

  • 서비스 간의 느슨한 결합: 각 서비스는 자신의 트랜잭션만 신경 쓰며, 다른 서비스와는 이벤트를 통해 통신하므로 결합도가 낮습니다.
  • 확장성: 서비스들이 독립적으로 동작하므로, 새로운 서비스를 쉽게 추가할 수 있습니다.
  • 비동기 처리: 이벤트 기반 아키텍처이기 때문에 각 서비스는 비동기로 트랜잭션을 처리할 수 있습니다.

SAGA Choreography의 단점

  • 복잡성 증가: 여러 서비스 간에 발생하는 이벤트 흐름을 추적하기 어려워지며, 트랜잭션 경로가 복잡해질 수 있습니다.
  • 순환 참조 문제: 서비스 간의 이벤트 의존도가 높아지면 이벤트가 서로 꼬이는 순환 참조 문제가 발생할 수 있습니다.
  • 보상 트랜잭션 관리: 오류가 발생했을 때 롤백을 위한 보상 트랜잭션을 관리하는 로직이 복잡해질 수 있습니다.

 

SAGA의 코레오그래피 패턴을 안정적으로 운영하려면 여러 가지 고려 사항이 필요합니다. 코레오그래피에서는 각 서비스가 자신의 비즈니스 로직을 처리하면서 필요한 메시지를 전송하고, 실패 처리도 자체적으로 관리하는 방식입니다. 이 방식의 주요 장점은 중앙 관리자가 없다는 것입니다. 하지만 이로 인해 시스템의 복잡성도 높아지고, 신뢰성과 일관성 확보가 어려운 경우도 있습니다. 안정적인 운영을 위한 몇 가지 중요한 점들을 아래에 정리해 보겠습니다. (다운타임 고려)

1. 메시지 브로커의 안정성 확보

코레오그래피에서는 서비스 간의 통신을 비동기적으로 메시지를 통해 이루어지기 때문에, 메시지 브로커(예: Kafka, RabbitMQ)가 핵심적인 역할을 합니다. 이 시스템이 다운되거나 메시지 유실이 발생하면 전체 사가가 실패할 수 있습니다.

  • 메시지 영속성: 메시지 브로커는 재시작되더라도 메시지가 손실되지 않도록 보장 / 메시지를 영속적으로 저장할 수 있도록 설정
    • Kafka는 기본적으로 로그 기반 아키텍처를 사용하여 메시지를 디스크에 영속적으로 저장하므로 높은 내구성을 제공합니다. 메시지가 파티션에 기록되고, 각 파티션은 순서가 보장되며, 복제 설정을 통해 장애 발생 시에도 데이터 손실을 방지할 수 있습니다. 소비자는 이전에 처리된 메시지로부터 다시 시작할 수 있는 유연성을 제공합니다.
      • 스토리지: Kafka는 로그 기반 시스템으로, 메시지가 디스크에 지속적으로 기록되며, 지정된 기간 동안 또는 설정된 크기까지 보존됩니다.
    • 반면 RabbitMQ는 기본적으로 메모리 기반 큐로, 영속성을 위해 추가적인 설정이 필요합니다. 영속성을 위해 메시지를 디스크에 저장하면 성능 저하가 발생할 수 있습니다. 따라서 대규모 데이터 처리 및 내구성이 중요한 시스템에서는 Kafka가 더 적합할 수 있습니다.
  • 메세지 보장:
    • 래빗 - 메시지 확인 및 재처리:
      • 소비자가 메시지를 처리할 때 ACK(Acknowledge) 또는 NACK(Negative Acknowledge)를 사용하여 메시지의 처리가 성공적으로 완료되었는지 여부를 브로커에 알립니다.
        • ACK: 소비자가 메시지를 성공적으로 처리한 후에 ACK를 보내면, RabbitMQ는 해당 메시지를 큐에서 제거합니다.
        • NACK: 메시지 처리가 실패했을 경우 소비자는 NACK를 보내어 메시지를 다시 큐에 추가하거나 다른 큐로 이동할 수 있습니다. 이는 메시지 손실을 방지하는 데 도움을 줍니다.
      • 만약 소비자가 다운될 경우, 처리되지 않은 메시지는 브로커에 남아 있게 되어, 후에 재시도할 수 있습니다. 이로써 서비스가 다시 시작되면 미처리된 메시지를 재처리할 수 있습니다.
    • 카프카 - 오프셋 관리:
      • Kafka와 같은 로그 기반의 메시징 시스템을 사용하면, 각 소비자는 자신의 오프셋(offset)을 관리할 수 있습니다. 이를 통해 서비스가 재시작되더라도 마지막으로 처리한 메시지 이후의 메시지만 읽을 수 있어, 데이터 손실 없이 안정적으로 운영할 수 있습니다.
      • 오프셋 관리: 소비자가 메시지를 처리한 후 해당 메시지의 오프셋을 커밋하여 카프카 브로커에 저장합니다. 오프셋은 각 파티션에서 메시지가 몇 번째인지에 대한 정보입니다. 이 커밋은 소비자가 해당 메시지를 성공적으로 처리했음을 카프카에 알려주는 역할을 합니다.
        • 메시지 처리 완료 확인: 소비자는 커밋된 오프셋을 기준으로 메시지가 이미 처리되었음을 확인하고, 다음에 읽을 메시지를 결정합니다.
        • 메시지 중복 방지: 카프카는 마지막 커밋된 오프셋부터 메시지를 소비하므로, 오프셋을 잘 관리하면 메시지의 중복 처리를 방지할 수 있습니다.
  • 재시도 메커니즘: 메시지 브로커에서 메시지 처리가 실패했을 때  일정 횟수까지 재시도를 할 수 있는 메커니즘을 도입합니다. 재시도 횟수를 제한하거나, 실패한 메시지는 DLQ(Dead Letter Queue)에 보관하고, 해당 메시지에 대해 수동 또는 자동으로 복구할 수 있는 절차를 마련합니다.
    • RabbitMQ는 Dead Letter Queue(DLQ)와 Retry Queue를 활용하여 메시지가 처리되지 않았을 경우 이를 다시 시도하도록 할 수 있습니다.

2. 모니터링과 트레이싱 / 알람

코레오그래피 패턴에서는 각 서비스가 독립적으로 행동하기 때문에, 문제 발생 시 전체 시스템에서 어떤 서비스가 문제를 일으켰는지 추적하는 것이 중요합니다. 메시지 처리 지연, 실패율 등을 관찰하고, 문제가 발생할 경우 경고를 받을 수 있습니다.

  • 분산 추적 시스템: 예를 들어, OpenTelemetry, Zipkin, Jaeger 등을 사용하여 분산 트레이싱을 설정합니다. 이를 통해 각 서비스에서 발생하는 요청과 응답을 추적하고, 실패나 지연이 발생한 지점을 쉽게 파악할 수 있습니다.
  • 로그 집합 시스템: 각 서비스에서 발생하는 로그를 통합하여 분석할 수 있는 시스템(예: ELK Stack, Prometheus, Grafana)을 구축합니다. 서비스 간 메시지 흐름을 추적하고, 오류를 신속하게 발견할 수 있도록 합니다.

3. 상태 관리와 보상 트랜잭션

코레오그래피 패턴에서는 각 서비스가 자신만의 상태를 관리하며, 실패 시 보상 트랜잭션을 처리해야 합니다. 보상 트랜잭션이란 이전 단계에서 발생한 변경을 되돌리는 작업을 의미합니다.

  • 보상 트랜잭션 설계: 각 서비스는 실패가 발생할 경우 보상 작업을 자동으로 실행해야 합니다. 예를 들어, 결제 처리 서비스에서 결제가 실패하면 이전에 발생한 예약을 취소하는 등의 처리를 해야 합니다.
  • 보상 트랜잭션의 신뢰성: 보상 트랜잭션이 실패하지 않도록, 처리되는 모든 작업은 idempotent(멱등성; 중복 실행 시 동일한 결과를 보장하는) 방식이어야 합니다. 이를 통해 여러 번 재시도가 이루어져도 시스템이 일관성 있게 동작할 수 있습니다.
  • 보상 트랜잭션의 회복: 보상 트랜잭션 역시 실패할 수 있기 때문에, 보상 작업이 실패하면 이를 다시 시도하거나 수동으로 복구할 수 있는 시스템을 마련해야 합니다.

4. 데이터 일관성 확보

코레오그래피 패턴에서는 이벤트 기반으로 서비스가 통신하므로, 데이터 일관성 문제를 해결하는 것이 중요합니다. 서비스 간의 데이터 변경이 일관되게 이루어지도록 해야 합니다.

  • 최종 일관성 보장: 코레오그래피 패턴은 강력한 일관성(ACID) 대신 최종 일관성(eventual consistency)을 제공합니다. 즉, 시간이 조금 걸릴 수 있지만 모든 서비스가 일관된 상태에 도달하도록 설계해야 합니다. 이를 위해 서비스들이 동일한 이벤트를 처리하는 순서를 보장하거나, 가능한 한 빠르게 일관된 상태로 수렴할 수 있도록 해야 합니다.

5. SLA(서비스 수준 계약, Service Level Agreement)와 트랜잭션의 타임아웃

서비스들이 비동기적으로 처리되기 때문에 각 단계의 응답 시간이 지연될 수 있습니다. 각 서비스가 적절한 시간 내에 작업을 완료하지 않으면 전체 SAGA가 실패할 수 있습니다.

  • SLA 설정: 각 서비스의 작업에 대해 적절한 SLA(Service Level Agreement)를 설정하고, 이 SLA를 기준으로 타임아웃을 설정하여 시스템이 적절한 시간 내에 작업을 완료할 수 있도록 합니다.
    • ex. 모든 API 요청에 대한 응답 시간은 200ms 이내로 처리
      • 응답 시간의 95%는 200ms를 초과하지 않아야 
      • 최대 응답 시간은 500ms를 초과할 수 없음
  • 타임아웃 처리: 각 서비스가 SLA를 지키지 않으면, 적절한 처리(예: 오류 로그 기록, 알림 발송, 재시도 등)를 통해 전체 트랜잭션을 관리합니다.

6. 이벤트 소싱

  • 모든 상태 변경을 이벤트로 기록하고 이를 통해 현재 상태를 재구성할 수 있는 이벤트 소싱(Event Sourcing) 패턴을 활용할 수 있습니다. 이렇게 하면 각 서비스가 발생한 이벤트를 기반으로 자신의 상태를 재구성할 수 있어, 데이터의 일관성을 유지하는 데 도움이 됩니다.
    •  

orchestration-based saga

  • 중앙 통제자: 중앙 조정자(orchestrator) 역할을 하는 서비스가 각 서비스의 트랜잭션을 관리합니다. 이 조정자는 트랜잭션 단계를 순차적으로 실행하고, 필요한 경우 보상 작업을 수행합니다.
  • 흐름 제어: 오케스트레이터는 각 서비스 호출의 순서를 정의하고, 에러 처리나 롤백도 중앙에서 관리합니다. 동기/비동기 모두 가능
  • 장점:
    • 단순한 흐름 제어: 중앙에서 모든 것을 관리하기 때문에 트랜잭션 흐름이 명확합니다.
    • 에러 처리 및 롤백이 통합되어 관리되므로 일관성을 유지하기 쉽습니다.; 오류 처리 쉬움
  • 단점:
    • Single Point of Failure: 중앙 통제자가 다운될 경우 전체 트랜잭션이 영향을 받습니다.
    • 확장성 문제: 모든 트랜잭션을 중앙에서 관리하기 때문에 트랜잭션 수가 많아질수록 부담이 커질 수 있습니다.

1. 동기식 오케스트레이션

  • 설명: 모든 서비스 호출이 순차적으로 진행되며, 각 서비스 호출이 완료될 때까지 대기합니다. 즉, 오케스트레이터가 각 서비스에 요청을 보내고 응답을 받을 때까지 기다립니다.
  • 장점:
    • 단순한 흐름: 트랜잭션의 흐름이 명확하고 예측 가능하여 디버깅과 모니터링이 용이합니다.
    • 즉각적인 오류 처리: 오류가 발생하면 즉시 대응할 수 있으며, 다음 단계로 진행하기 전에 에러 처리를 수행할 수 있습니다.
  • 단점:
    • 지연: 각 서비스 호출이 완료될 때까지 기다려야 하므로 전체 트랜잭션의 실행 시간이 늘어날 수 있습니다.
    • 스케일 문제: 동기식 호출이 많아지면 시스템의 성능이 저하될 수 있습니다.

2. 비동기식 오케스트레이션

  • 설명: 서비스 호출이 비동기적으로 이루어지며, 오케스트레이터는 각 서비스에 요청을 보내고 응답을 기다리지 않고 다음 작업을 진행합니다. 일반적으로 메시지 큐를 사용하여 서비스 간의 통신을 처리합니다.
  • 장점:
    • 성능 향상: 각 서비스가 독립적으로 작동하므로 동시에 여러 요청을 처리할 수 있어 성능이 향상됩니다.
    • 유연성: 서비스 간의 느슨한 결합을 유지할 수 있으며, 서비스가 독립적으로 확장될 수 있습니다.
  • 단점:
    • 복잡성: 비동기 통신은 흐름을 이해하고 디버깅하기 더 어렵게 만들 수 있습니다.
    • 오류 처리: 각 서비스가 비동기적으로 작동하므로 에러 발생 시 처리하기가 더 복잡해질 수 있습니다.

 

오케스트레이터는 복잡한 프로세스나 워크플로우를 관리하고 조정하는 시스템입니다. 마이크로서비스 아키텍처에서는 다양한 서비스 간의 상호작용을 관리하는 데 사용됩니다. 오케스트레이터는 일반적으로 다음과 같은 역할을 합니다:

  • 서비스 간의 호출 순서 및 의존성을 관리
  • 오류 처리 및 재시도 로직 구현
  • 상태를 모니터링하고 필요한 경우 알림 전송

오케스트레이터는 여러 형태로 구현될 수 있습니다:

  1. 전용 프로그램:
    • Apache Airflow, Camunda, Temporal과 같은 오케스트레이션 도구는 비즈니스 프로세스를 자동화하고 조정하는 데 사용됩니다. 이들 도구는 복잡한 워크플로우를 설계하고 실행하는 데 필요한 기능을 제공합니다.
  2. 메시지 브로커:
    • Kafka와 같은 시스템은 메시지를 전달하고 여러 서비스 간의 통신을 조정할 수 있지만, 기본적으로는 오케스트레이션 기능을 제공하지 않습니다. Kafka는 주로 데이터 스트리밍 및 이벤트 기반 아키텍처에 사용되며, 오케스트레이션과는 다릅니다. 하지만 오케스트레이터와 메시지 브로커를 함께 사용하여 전체 시스템을 구성하는 것이 일반적..
  3. 서비스 메쉬:
    • Istio와 같은 서비스 메쉬는 마이크로서비스 간의 통신을 관리하고 보안, 트래픽 관리, 모니터링 등의 기능을 제공합니다. 이러한 솔루션도 오케스트레이션의 일종으로 간주될 수 있습니다.

 


2 phase commit

2PC(2-Phase Commit, 2단계 커밋)는 분산 데이터베이스 시스템에서 트랜잭션을 안전하게 커밋하기 위해 사용하는 프로토콜입니다. 이 프로토콜은 여러 데이터베이스 또는 서비스가 관련된 트랜잭션을 일관성 있게 처리하기 위해 설계되었습니다.

2-Phase Commit 동작 단계

  1. Prepare 단계:
    • **트랜잭션 코디네이터(Coordinator)**가 모든 참여 노드(또는 서비스)에 "Prepare" 메시지를 전송합니다.
    • 각 참여자는 트랜잭션을 수행할 준비가 되면 로컬로 락을 설정하고 "Yes"(준비 완료) 응답을 보냅니다.
    • 만약 어떤 노드가 준비되지 않거나 실패하면 "No"(준비 실패) 응답을 보냅니다.
  2. Commit 단계:
    • 코디네이터가 모든 노드로부터 "Yes" 응답을 받으면, 각 노드에 **트랜잭션을 커밋(commit)**하도록 지시하고 트랜잭션이 완료됩니다.
    • 만약 어느 하나의 노드라도 "No" 응답을 보낸 경우, 트랜잭션을 전체적으로 롤백합니다.
    • 커밋이나 롤백 완료 후 각 노드는 락을 해제합니다.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;

@Service
public class InventoryService {

    @Autowired
    private DataSource warehouse1DataSource;

    @Autowired
    private DataSource warehouse2DataSource;

    @Transactional
    public void updateInventory(String productId, int quantity) throws Exception {
        try (Connection conn1 = warehouse1DataSource.getConnection();
             Connection conn2 = warehouse2DataSource.getConnection()) {

            String updateWarehouse1 = "UPDATE inventory SET quantity = quantity - ? WHERE product_id = ?"; 
            try (PreparedStatement ps1 = conn1.prepareStatement(updateWarehouse1)) {
                ps1.setInt(1, quantity / 2);
                ps1.setString(2, productId);
                ps1.executeUpdate();
            }

            String updateWarehouse2 = "UPDATE inventory SET quantity = quantity - ? WHERE product_id = ?";
            try (PreparedStatement ps2 = conn2.prepareStatement(updateWarehouse2)) {
                ps2.setInt(1, quantity / 2);
                ps2.setString(2, productId);
                ps2.executeUpdate();
            }
        } catch (Exception e) {
            throw new RuntimeException("Inventory update failed, rolling back transaction", e);
        }
    }
}

위 코드에서 2PC의 Prepare 단계Commit 단계는 트랜잭션 매니저(JtaTransactionManager)에 의해 관리됩니다. 코드 자체에는 Prepare와 Commit이라는 명시적인 단계가 보이지 않지만, JtaTransactionManager가 내부적으로 이 과정을 수행합니다.


MySQL에서 UPDATE 쿼리를 실행할 때, InnoDB는 기본적으로 **행 잠금(Row Lock)**을 사용하여 UPDATE 대상이 되는 행을 잠급니다. 다른 트랜잭션에서 읽을 수는 있지만, 실제로 쓰기를 시도하려면 트랜잭션이 완료될 때까지 기다려야 하므로 일시적인 충돌은 방지됩니다. 하지만 다수의 트랜잭션에서 동시에 동일한 데이터를 수정하려고 하면 **경쟁 조건(Race Condition)**이 발생할 수 있습니다.

INSERT 쿼리에서 InnoDB는 기본적으로 행 잠금을 사용하지 않습니다. 즉, INSERT가 실행될 때는 행에 락을 걸지 않으며, 다른 트랜잭션은 동시에 다른 행을 삽입할 수 있습니다.

 

  • auto_increment 필드를 사용하는 경우, InnoDB는 자동 증가 값을 생성할 때 해당 레코드에 잠금을 걸 수 있습니다. 이 값이 충돌하지 않도록 내부적으로 관리되기 때문입니다.
  • 예를 들어, 여러 트랜잭션이 동시에 INSERT를 시도할 때, 자동 증가 값에 대한 충돌을 피하기 위해 자동 증가 번호를 추적하기 위한 락이 필요합니다. 이 경우 다른 트랜잭션은 번호가 할당될 때까지 대기할 수 있습니다.

 

1. Prepare 단계

Prepare 단계는 트랜잭션 관리자가 각 데이터 소스에 트랜잭션을 시작하고 작업을 준비시키는 과정입니다. 여기서 중요한 역할을 하는 부분은 @Transactional 애너테이션입니다. 이 애너테이션을 통해 트랜잭션이 시작되면 다음과 같은 작업들이 순서대로 진행됩니다.

  • 트랜잭션 매니저는 각각의 데이터 소스에 대해 트랜잭션을 시작합니다.
  • updateWarehouse1와 updateWarehouse2 쿼리를 실행하여 각 데이터베이스에 변경 사항을 기록합니다.
  • Prepare 단계에서는 실제 커밋을 수행하지 않고, 각 데이터베이스에 잠금(Lock)을 통해 데이터의 일관성을 보장합니다.

만약 이 단계에서 에러가 발생하면 JtaTransactionManager가 rollback을 호출하여 전체 트랜잭션이 취소됩니다.

2. Commit 단계

Commit 단계는 모든 준비가 완료된 후, 각 데이터 소스에 대해 트랜잭션을 실제로 커밋하는 과정입니다. 이 단계에서는 다음 작업들이 수행됩니다.

  • 트랜잭션 매니저가 각 데이터 소스에 commit 명령을 내리고, 모든 변경 사항을 데이터베이스에 영구적으로 반영합니다.
  • 각 데이터베이스가 성공적으로 커밋되면, 트랜잭션이 완료됩니다.
  • 만약 이 과정에서 하나라도 실패하면 rollback이 호출되어 모든 데이터베이스의 작업이 원상복구됩니다.

정리하면:

  • @Transactional 애너테이션을 통해 시작되는 트랜잭션이 Prepare 단계에서 두 데이터베이스에 모두 준비된 상태로 변경 작업을 적용한 후 잠금을 유지합니다.
  • 트랜잭션 매니저가 커밋을 호출하면서, 실제 변경 사항이 모든 데이터베이스에 커밋되는 것이 Commit 단계입니다.

2-Phase Commit에서의 락(Lock)과 문제점

락의 사용:

  • 각 참여 노드는 "Prepare" 단계에서 트랜잭션에 관련된 자원을 락합니다. 이 락은 트랜잭션의 커밋 또는 롤백이 완료될 때까지 유지되어, 다른 트랜잭션이 해당 자원에 접근하지 못하게 합니다.
  • 이 락은 데이터 일관성을 유지하는 데 필수적이지만, 락을 길게 유지하면 성능 저하가 발생할 수 있습니다.

문제점:

  • 블로킹(Blocking): 한 노드가 준비 상태에서 응답을 보내지 못하거나 장애가 발생하면, 코디네이터는 트랜잭션의 커밋 또는 롤백을 기다려야 하므로 전체 트랜잭션이 중단될 수 있습니다.
  • 확장성 문제: 트랜잭션이 많아지고 락을 획득하는 시간이 길어질수록 시스템의 성능이 저하됩니다.
  • 고립된 락: 참여자가 죽거나 네트워크 분리가 발생하면 락이 해제되지 않는 문제가 발생할 수 있습니다.

이러한 문제로 인해, 2PC는 락 비용이 크고 고가용성을 요구하는 시스템에는 적합하지 않으며, 대신 SAGA 패턴이나 **3-Phase Commit(3PC)**과 같은 대안이 사용되기도 합니다.


실패 가능 시나리오

1. Prepare 단계에서 참가자 실패

  • 상황: 코디네이터가 각 참가자에게 Prepare 메시지를 보내고 승인을 기다리는 동안, 한 참가자가 응답하지 않거나 실패하는 경우입니다.
  • 처리 방식:
    • 대기 하다가
    • 타임아웃 설정(권장): 참가자가 Prepare 단계에서 정해진 시간 내에 응답하지 않으면, 코디네이터는 해당 참가자를 실패로 간주합니다.
    • 롤백 결정: 코디네이터는 전체 트랜잭션을 롤백하기로 결정하고 모든 응답한 참가자에게 Rollback 명령을 보냅니다.
    • 일관성 보장: 응답하지 않은 참가자 역시, 복구 시 자신의 트랜잭션을 롤백하는 규칙을 따릅니다.

2. Commit 단계에서 참가자 실패

  • 상황: 모든 참가자가 Prepare 요청에 승인했으나, Commit 명령을 기다리는 도중에 일부 참가자가 실패합니다.
  • 처리 방식:
    • Commit 의무: Prepare에서 Commit을 승인한 참가자는 이후 반드시 Commit을 완료해야 합니다.
    • 복구 프로세스: 실패한 참가자는 복구되었을 때 로그를 확인하여 Commit 또는 Rollback을 수행합니다. 참가자는 Prepare 단계에서 승인 후 실패하면, 복구 후 반드시 Commit을 실행해야 일관성이 유지됩니다.
      • 코디네이터가 '대기'하는 것이 아닌, 참가자가 로그를 확인하는 방식: 코디네이터는 더 이상 해당 트랜잭션을 대기하지 않고 종료

3.  Prepare 단계에서의 코디네이터 실패:

    • 대기 상태 유지: 참가자는 Commit 또는 Rollback 명령을 받을 때까지 대기합니다.
      • 코디네이터가 Prepare 메시지를 보낸 후 실패하면, 참가자들은 각자의 상태를 Prepared로 유지하며 Commit 또는 Rollback 명령을 기다립니다.
      • 이 시점에서는 코디네이터의 복구나 교체 없이는 참가자들이 개별적으로 Commit이나 Rollback을 결정하지 못하므로, 참가자들은 일시적으로 대기 상태에 들어갑니다.
    • 타임아웃 및 복구: 코디네이터가 복구되면 로그를 확인해 Prepare 상태를 마친 참가자에게 Commit 또는 Rollback을 지시합니다. 새로운 코디네이터가 지정되거나 기존 코디네이터가 복구되기를 기다리며 재시도를 합니다.
      • 재시도 메커니즘: 참가자가 코디네이터의 상태를 감지할 수 있도록 재시도 메커니즘을 적용할 수 있습니다. 코디네이터가 다시 살아날 경우 트랜잭션을 다시 시도할 수 있습니다.  
      • 참가자들은 일정 시간 동안 코디네이터의 응답을 기다리도록 타임아웃을 설정할 수 있습니다. 타임아웃이 발생하면 참가자는 문제가 생겼음을 인식하고 롤백 프로세스를 시작하게 됩니다.
    • 코디네이터가 복구되거나 새로운 코디네이터가 지정되면 모든 참가자들의 상태 로그를 검토하여 트랜잭션 상태(Commit 또는 Rollback)를 확인합니다.

4. Commit 단계에서의 코디네이터 실패:

  1. Commit 명령을 받은 후 코디네이터가 실패한 경우:
    • 코디네이터가 모든 참가자에게 Commit 명령을 전달한 후에 실패했다면, 대부분의 참가자는 이미 Commit을 완료했을 것입니다.
    • 참가자는 트랜잭션 로그에 Commit 완료 상태를 기록하여 코디네이터가 없는 상태에서도 트랜잭션 완료 상태를 기억할 수 있습니다.
    • 새로운 코디네이터가 복구되면 참가자들의 로그 상태를 조회 일관성을 검증하고, 트랜잭션이 Commit으로 완료되었는지 확인합니다.
  2. Commit 명령이 일부 참가자에게 전달되지 않은 경우:
    • 코디네이터가 일부 참가자에게 Commit 명령을 보내기 전에 실패하면, 이 경우 일부 참가자만 Commit을 수행하고 나머지 참가자는 Prepared 상태로 남아 있을 수 있습니다.
    • 이때 참가자들은 코디네이터의 복구나 새로운 코디네이터가 지정될 때까지 로그를 통해 자신의 상태를 유지하며 대기하게 됩니다.
    • 새로운 코디네이터는 각 참가자의 상태를 확인하여, 이미 Commit을 완료한 참가자가 있으면 전체 트랜잭션을 Commit하도록 모든 참가자에게 지시합니다.
  3. 최종적으로 Commit을 보장하기 위한 절차:
    • 새로운 코디네이터가 지정되면, 각 참가자에게 현재 트랜잭션 상태를 질의하고 이를 바탕으로 트랜잭션의 일관된 완료 상태를 결정합니다.
    • 만약 일부만 Commit을 완료한 상태로 확인되면, 모든 참가자에게 Commit 명령을 다시 전달하여 트랜잭션을 완결시킵니다.

이 과정을 통해 트랜잭션은 무조건 동일한 최종 상태(Commit 또는 Rollback)로 마무리되며, 코디네이터가 Commit 단계에서 실패하더라도 로그와 상태 확인을 통해 일관성을 보장합니다.

2PC의 장점

  1. 트랜잭션 일관성 보장:
    • 모든 참여 시스템이 트랜잭션을 동시에 커밋하거나 롤백하기 때문에 데이터 일관성을 유지할 수 있습니다. 이는 금융 시스템이나 다른 중요한 데이터가 관련된 애플리케이션에서 필수적입니다.
  2. 구현의 단순성:
    • 두 가지 단계(Prepare 및 Commit)로 이루어져 있어 구현이 상대적으로 단순합니다. 트랜잭션 관리가 필요한 경우 쉽게 적용할 수 있습니다.

2PC의 단점

  1. 코디네이터의 단일 실패:
    • 코디네이터가 실패하면 모든 참가자가 해당 트랜잭션에 대해 무기한으로 대기하게 되어 시스템이 불안정해집니다. 코디네이터 장애 복구가 어려워 전체 트랜잭션에 영향을 줄 수 있습니다.
  2. 참가자의 무한 대기 문제:
    • Prepare 단계에서 승인 후 // 코디네이터가 Commit이나 Rollback 명령을 전달하지 않으면 참가자들은 대기 상태에 빠집니다. 이는 네트워크 장애나 코디네이터 장애로 인한 무한 대기 문제로 이어질 수 있습니다.
  3. 락 유효성 문제
    • 2PC 프로토콜에서는 참가자들이 트랜잭션 상태를 준비하는 동안 데이터에 락을 걸고 대기하므로, 데이터베이스 자원의 락이 장기간 유지될 수 있습니다.
    • 트랜잭션이 길어지면 데이터베이스 자원에 대한 경합이 심해져, 다른 트랜잭션들이 성능 저하 겪을 수 있습니다.
  4. 네트워크 지연 문제:
    • 코디네이터와 각 참가자 간의 통신에서 지연이 발생할 경우 트랜잭션 완료까지 시간이 길어집니다. 이로 인해 자원이 오랫동안 잠금 상태로 유지되어 성능 저하가 발생할 수 있습니다.
  5. 네트워크 파티션 문제:
    • 2PC는 네트워크 파티션이 발생할 경우 각 노드가 올바른 결정을 내리기 어려운 문제가 있습니다. 네트워크가 복구될 때까지 모든 시스템이 일관성을 보장할 방법이 없어 데이터 일관성 유지가 어려워질 수 있습니다.
  6. 확장성 제한:
    • 2PC동기화 방식으로 작동하므로 확장성(scalability) 문제에 직면할 수 있습니다. 분산 시스템에서 많은 참가자가 동시에 참여하는 경우, 각 단계에서 지연이 누적되기 때문에 트랜잭션의 성능 저하가 발생할 수 있으며, 네트워크 지연, 대기 시간, 동기화 비용 등이 시스템 성능에 큰 영향을 미칠 수 있습니다.

로그 활용과 복구 절차

  • 참가자와 코디네이터의 로그 기록: 모든 참여자는 트랜잭션 진행 상황을 로그에 기록하여, 장애 발생 시 트랜잭션 상태를 복구하는 데 사용합니다. 예를 들어, Prepare 승인 여부, Commit 및 Rollback 상태 등을 기록합니다.
  • 복구 절차:
    • 코디네이터 복구: 코디네이터는 복구 시 자신의 로그를 확인하여 아직 완료되지 않은 트랜잭션을 찾고, 참가자에게 나머지 명령을 수행하도록 합니다.
    • 참가자 복구: 참가자는 복구 시, 마지막 로그 상태에 따라 트랜잭션을 Commit 또는 Rollback합니다.

동기화 문제와 대안

  • 2PC는 장애 시 동기화 문제로 인해 성능 저하가 발생할 수 있습니다. 이런 상황을 최소화하기 위해 많은 분산 시스템에서는 SAGA 패턴과 같은 비동기 트랜잭션 관리 방식을 선택하기도 합니다.
  • SAGA 패턴은 복구(데이터 일관성이 맞던 시점으로 돌아가) 및 보상 트랜잭션(되돌리기; 롤백)을 사용하여, 전체 시스템을 잠그지 않고 트랜잭션을 처리하는 대안을 제공합니다.
  • 2-Phase Commit (2PC)은 일반적으로 동기적으로 동작합니다. 즉, 모든 참가자가 각 단계에서 응답을 제공하기 전까지 다음 단계로 진행하지 않는 구조입니다.
  1. Prepare 단계의 동기성:
    • 코디네이터는 각 참가자에게 Prepare 요청을 보내고, 모든 참가자가 성공을 응답할 때까지 대기합니다. 모든 참가자가 준비 완료 상태임을 확인할 때까지 다음 단계인 Commit으로 넘어가지 않습니다.
    • 모든 응답을 기다리기 때문에 각 참가자는 해당 트랜잭션에 대해 락을 걸고 대기하며, 이는 다른 트랜잭션의 접근을 막아 동시성에 영향을 미칩니다.
  2. Commit/Abort 단계의 동기성:
    • 모든 참가자가 Prepare에 응답한 후, 코디네이터는 각 참가자에게 Commit 또는 Abort 명령을 동기적으로 보냅니다.
    • 코디네이터는 모든 참가자의 Commit 응답이 도착할 때까지 최종 완료를 확인하지 않으며, 트랜잭션이 완전히 완료된 것을 보장하기 위해 이 과정을 동기적으로 처리합니다.

동기적 특성으로 인한 제약사항

  • 성능 저하: 모든 참여자의 응답을 기다리는 과정에서 응답 지연이 발생할 수 있습니다.
  • 지연 시간 증가: 네트워크 지연이나 참가자의 성능 문제로 인해 2PC의 완료 시간이 길어질 수 있습니다.
  • 확장성 제한: 참가자가 늘어날수록 동기적으로 기다려야 하는 응답이 많아져 확장성이 제한됩니다.
  • 고가용성 문제: 코디네이터나 참가자가 중간에 실패할 경우 전체 트랜잭션이 중단되며, 동기성으로 인해 대기 상태에 빠지게 됩니다.

코디네이터는 누가 어떻게?

1. 트랜잭션 코디네이터 역할

  • 트랜잭션 시작: 트랜잭션을 시작하고, 모든 참여 노드(예: 여러 DB 인스턴스, 서비스 등)에게 트랜잭션 참여 요청을 전달합니다.
  • Prepare 단계 관리: 모든 노드에 Prepare 요청을 보내고, 각 노드가 트랜잭션을 커밋할 준비가 되었는지 확인합니다.
  • Commit 또는 Rollback 결정: 모든 노드가 "Prepare 성공" 응답을 반환하면 Commit을, 실패 응답이 있으면 Rollback을 지시합니다.
  • 상태 관리 및 오류 처리: 네트워크 오류나 장애가 발생하면 트랜잭션을 적절하게 중단시키고, 필요 시 롤백합니다.

2. 트랜잭션 코디네이터를 수행하는 시스템

  • 데이터베이스 관리 시스템(DBMS):
    • 많은 DBMS(예: Oracle, PostgreSQL, MySQL 등)에서 자체적으로 2PC를 지원하는 경우 DB 인스턴스 자체가 트랜잭션 코디네이터 역할을 할 수 있습니다.
    • 복수의 DB 노드가 분산 트랜잭션에 참여해야 할 때, DBMS가 코디네이터가 되어 트랜잭션을 조율합니다.
  • 트랜잭션 관리 시스템(TMS):
    • **Java EE 서버(JBoss, WebSphere)**와 같은 엔터프라이즈 애플리케이션 서버는 **JTA(Java Transaction API)**를 통해 트랜잭션을 관리하며, 코디네이터 역할을 할 수 있습니다.
    • JTA는 XA 프로토콜을 사용해 DBMS와 메시지 큐 시스템이 동시에 참여하는 분산 트랜잭션을 조율할 수 있습니다.
  • 클라우드 및 분산 시스템:
    • 클라우드 환경에서는 Google Spanner, Amazon Aurora, Microsoft Azure SQL Database 같은 관리형 데이터베이스 서비스가 트랜잭션 코디네이터 기능을 제공합니다.
    • Kubernetes와 같은 환경에서는 외부 트랜잭션 관리 툴을 통해 분산 트랜잭션을 관리할 수도 있습니다.

3. 트랜잭션 코디네이터의 필요성과 한계

  • 2PC 코디네이터는 분산 트랜잭션에서 데이터 일관성을 보장하는 중요한 역할을 하지만, 네트워크 지연데드락 위험 때문에 트랜잭션 수행 속도가 느려질 수 있습니다.
  • 최근에는 이러한 한계를 극복하기 위해 SAGA 패턴과 같은 분산 트랜잭션 대안이 각광받고 있습니다.

3PC의 단계와 개선 내용

  1. Can Commit 단계:
    • 코디네이터가 트랜잭션을 수행할 준비가 되었는지 모든 참여자에게 묻습니다.
    • 각 참여자는 승인 가능 여부를 응답하고, 타임아웃이 지나면 No로 간주됩니다.
    이 단계는 기존 2PC와 비슷하지만, 참가자가 제한 시간 내 응답을 못하면 자동으로 No로 처리되므로 무기한 대기가 줄어듭니다.
  2. Pre-Commit 단계 (3PC에서 추가된 단계):
    • 코디네이터가 모든 참여자로부터 Yes 응답을 받으면, Pre-Commit 요청을 보냅니다.
    • 이때 각 참가자는 트랜잭션을 일시적으로 저장하지만 실제 커밋하지 않고 대기합니다.
    • 이 과정에서도 타임아웃이 강제되어 응답이 지연되면 트랜잭션을 롤백할 수 있습니다.
    이 단계가 추가됨으로써 참여자들은 코디네이터나 다른 참가자가 실패하더라도 롤백으로 일관성을 유지할 수 있습니다.
  3. Commit 단계:
    • 코디네이터가 최종 커밋 명령을 보내며, 모든 참가자는 타임아웃 내에 커밋을 완료합니다.
    • 코디네이터가 실패하더라도 참가자들이 Pre-Commit 단계를 통해 트랜잭션을 커밋하거나 롤백할 수 있는 상태가 되므로, 무한 대기를 피하고 일관성을 유지할 수 있습니다.

3PC의 주요 개선점: 복구 및 안정성

  • 무한 대기 방지: 각 단계에 타임아웃을 설정하여 코디네이터 또는 참여자가 응답하지 않을 경우에도 결정할 수 있습니다.
  • 비동기적 장애 복구 가능: Pre-Commit 단계를 통해 참여자들이 커밋을 확정하기 전 준비 상태에서 롤백할 수 있어, 코디네이터가 중간에 실패하더라도 참여자들은 대기 없이 결정할 수 있습니다.
  • 시스템 신뢰성 증가: 네트워크 장애나 일시적인 서버 장애가 있어도 참여자들이 독립적으로 커밋/롤백을 결정할 수 있어, 전체 시스템의 신뢰성을 높입니다.

3PC(3-Phase Commit)는 기본적으로 동기 방식의 트랜잭션 프로토콜입니다. 하지만 비동기 처리와 관련된 개념이 몇 가지 존재합니다. 

동기 방식

  • 각 단계에서의 대기: 3PC는 각 단계(Prepare, Pre-Commit, Commit)에서 코디네이터와 참가자 간의 메시지 전송이 이루어지며, 코디네이터는 각 참가자로부터 응답을 기다립니다. 이 과정에서 모든 참가자가 응답할 때까지 대기하는 방식이므로 동기적입니다.
  • 모든 참여자와의 동기화: 트랜잭션의 일관성을 유지하기 위해 코디네이터는 모든 참가자로부터 동기적으로 응답을 받아야 하며, 이를 통해 트랜잭션을 진행합니다.

비동기 처리의 개념

  • 타임아웃 및 복구: 3PC에서는 각 단계에 타임아웃이 설정되어 있어, 특정 참가자가 응답하지 않으면 자동으로 트랜잭션을 롤백할 수 있습니다. 이로 인해 비동기적 장애 복구가 가능해지며, 대기하지 않고 다른 작업을 수행할 수 있는 가능성이 생깁니다.
  • Pre-Commit 단계: Pre-Commit 단계에서 각 참가자는 트랜잭션을 준비하지만, 실제로 커밋하기 전까지는 대기합니다. 이 상태에서 참가자는 코디네이터의 요청이 없더라도 자신이 결정할 수 있는 상태가 되므로, 이 점에서 비동기적인 특성을 가질 수 있습니다.

2PC에서의 상태 확인:

  • 2PC에서도 참가자는 로그를 통해 자신의 상태를 확인할 수 있습니다. 예를 들어, Prepare 단계에서 참가자가 Vote to Commit을 보낸 후, 이 정보는 참가자의 로그에 기록됩니다.
  • 그러나 코디네이터가 실패한 경우, 참가자는 여전히 트랜잭션이 완료되었는지, 롤백되었는지 알 수 없습니다. 코디네이터가 실패하면 참가자는 대기해야 하고, 자신의 상태만으로는 트랜잭션을 커밋할지 롤백할지 결정을 내릴 수 없습니다.
    • 참가자는 코디네이터의 결정을 기다려야 하기 때문입니다.
    • 2PC에서는 코디네이터가 트랜잭션을 완료할지 롤백할지를 최종적으로 결정합니다.

3PC에서의 복구 가능성:

  • 3PCPreCommit 단계를 추가로 도입하여, 참가자가 자신의 상태를 확인하고, 트랜잭션을 진행할 수 있는 준비 상태에 있다는 사실을 명확히 알 수 있게 합니다.
  • 코디네이터가 실패하면, 참가자는 PreCommit 상태에서 자기 상태를 확인하고 복구된 코디네이터가 트랜잭션을 커밋할지 롤백할지를 최종적으로 결정할 수 있도록 대기하는 상태로 넘어갑니다.
  • 참가자는 자신이 PreCommit 상태라는 정보를 가지고 있으며, 복구 후 트랜잭션을 진행할 준비가 되었다는 것을 알지만, 최종적인 결정은 코디네이터가 내리기 때문에 대기하는 것입니다.

결론:

  • 2PC에서는 참가자가 자신의 상태를 로그에서 확인할 수 있지만, 코디네이터가 실패한 경우 참가자는 대기해야 하며 자기 혼자서 결정을 내리기 어렵습니다.
  • 3PC에서는 PreCommit 상태로 참가자가 자기 준비 상태를 확인할 수 있지만, 결정은 여전히 코디네이터가 내리게 됩니다. 다만, PreCommit 상태로 명확한 정보를 제공하여, 복구 후 결정을 더 빨리 내릴 수 있는 장점이 있습니다.
728x90
반응형
반응형

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C-%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C%EC%84%9C%EB%B9%84%EC%8A%A4/dashboard

 

Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA) 강의 - 인프런

Spring framework의 Spring Cloud 제품군을 이용하여 마이크로서비스 애플리케이션을 개발해 보는 과정입니다. Cloud Native Application으로써의 Spring Cloud를 어떻게 사용하는지, 구성을 어떻게 하는지에 대해

www.inflearn.com

해당 강의를 들으면서 note taking이 필요한 부분 정리

강의는 springboot2.4를 기준으로 하고있지만, 나는 springboot2.7을 기준으로 하였기 때문에 설정에 변경이 필요한 부분이 많이 있었음..

 

관련 글

2024.01.12 - [서버 세팅 & tool] - [mvn] springboot 프로젝트 바로/여러 인스턴스로 실행하기

 

[mvn] springboot 프로젝트 바로/여러 인스턴스로 실행하기

환경: 윈도우, maven 3.8이 설치되어 있음 터미널로 실행하는 명령어 pom.xml 이 있는 폴더로 가서 아래와 같이 명령어를 주면 실행된다. mvn spring-boot:run # 추가적으로 포트를 수정해야한다면 mvn spring-

bangpurin.tistory.com

2024.01.15 - [개발/spring] - [h2] h2를 기본 데이터베이스로 사용하기

 

[h2] h2를 기본 데이터베이스로 사용하기

환경: springboot2.7, java 17, maven h2를 내장하는 테스트 프로젝트 생성 아래와 같이 설정했다고 가정 com.h2database h2 1.4.200 runtime # 1.3.176으로 낮추면 해결됨 ((최신 버전으로 해도 그러는지 확인 필요)) h

bangpurin.tistory.com

2024.01.27 - [개발/spring] - [security] jwt NoClassDefFoundError: javax/xml/bind/DatatypeConverter

 

[security] jwt NoClassDefFoundError: javax/xml/bind/DatatypeConverter

환경: java 17, springboot 2.7.6 아래 라이브러리를 사용하여 JWT토큰 파싱할 때 에러날 경우 소스: io.jsonwebtoken jjwt 0.9.1 subject = Jwts.parser().setSigningKey(environment.getProperty("token.secret")) .parseClaimsJws(jwt).getBody

bangpurin.tistory.com

2024.01.29 - [개발/spring-cloud] - [cloud] 파일을 동적으로 관리하는 config server

 

[cloud] 파일을 동적으로 관리하는 config server

환경: springboot2.7.6, java 17, springcloud 2021.0.8 application.properties/yml과 같은 설정파일을 수정하면 서버를 재시작해야 한다는 부담이 있다. spring cloud에서 제공하는 config server를 이용하면 설정 파일을

bangpurin.tistory.com

2024.01.29 - [개발/spring-cloud] - [cloud] spring cloud bus

 

[cloud] spring cloud bus

환경: springboot2.7.6, java 17, springcloud 2021.0.8 사용 이유: 분산 시스템의 노드(서비스들)를 경량 메시지 브로커(rabbit mq)와 연결하여 상태 및 구성에 대한 변경 사항을 연결된 노드에게 전달(broadcast)한

bangpurin.tistory.com

2024.01.29 - [서버 세팅 & tool/rabbitmq] - [windows] rabbitmq cmd 설치

 

[windows] rabbitmq cmd 설치

환경: windows11 프로, 64비트 윈도우에서 rabbitmq 설치 시 erlang을 필수로 설치해야한다. 딱히 호환되는 버전 지정 없이, 최신버전들로 설치해도 문제없다. powershell 관리자 권한 실행 ctrl + r powershell

bangpurin.tistory.com

2024.01.29 - [개발/spring-cloud] - [cloud] property값 암호화하여 사용하기

 

[cloud] property값 암호화하여 사용하기

환경: springboot2.7.6, java 17, springcloud 2021.0.8 이전글: 2024.01.29 - [개발/spring] - [cloud] 파일을 동적으로 관리하는 config server 2024.01.29 - [개발/spring] - [cloud] spring cloud bus spring cloud config service에서 파일로

bangpurin.tistory.com

2024.02.04 - [서버 세팅 & tool/kafka] - [windows] kafka 실행

 

[windows] kafka 실행

환경: 윈도우11, kafka2.13-3.6.1 카프카는 공홈에서 받아주고, 압축을 풀어준다. 카프카/주키퍼 실행 시 아래와 같은 에러 발생한다. 확인해보니 kafka-server-start.bat실행 시 같은 폴더 안에 있는 kafka-run

bangpurin.tistory.com

2024.02.04 - [서버 세팅 & tool/kafka] - [windows] kakfa connect; mariadb 설치

 

[windows] kakfa connect; mariadb 설치

환경: windows11, java17, springboot2.7.6 kakfa connect를 통해 데이터를 import/export 가능 코드 없이 configuration으로 데이터 이동 가능 Standalone mode, distribution mode 지원 restfult API 지원 stream, batch 형태로 데이터

bangpurin.tistory.com

2024.02.04 - [서버 세팅 & tool/kafka] - [windows] kakfa connect 연동

 

[windows] kakfa connect 연동

2024.02.04 - [서버 세팅 & tool/kafka] - [windows] kakfa connect; mariadb 설치 사용하게 된 배경: 기존의 서버가 h2 디비를 사용하여 1 인스턴스 - 1 디비를 사용하고 있었는데, 이렇게 되면 여러 인스턴스를 띄

bangpurin.tistory.com

2024.02.04 - [서버 세팅 & tool/kafka] - kakfa 작업시 띄울 것

2024.02.08 - [개발/kafka] - [spring-kafka] producer, consumer 기초

 

[spring-kafka] producer, consumer 기초

환경: springboot2.7.6, java11, h2 연결 producer 정보 보내는 쪽 1. pom.xml 추가 org.springframework.kafka spring-kafka 2. producer kafka 연결 설정 @EnableKafka @Configuration public class KafkaProducerConfig { @Bean public ProducerFactory pr

bangpurin.tistory.com

2024.02.08 - [개발/kafka] - [spring-kafka] 데이터 저장 시 sink connect 사용하여 단일 디비로

 

[spring-kafka] 데이터 저장 시 sink connect 사용하여 단일 디비로

이전 작업: 2024.02.04 - [서버 세팅 & tool/kafka] - [windows] kakfa connect 연동 2024.02.08 - [개발/kafka] - [spring-kafka] producer, consumer 기초 환경: springboot 2.7.6, spring-kafka, java11 목표: 인스턴스 별로 하나씩 있던 디

bangpurin.tistory.com

2024.02.08 - [개발/spring-cloud] - [resilience4j] circuit breaker

 

[resilience4j] circuit breaker

환경: springboot2.7.6, java11 circuit breaker 장애가 발생하는 서비스에 반복적인 호출이 되지 못하게 차단 특정 서비스가 정상적으로 동작하지 않을 경우 다른 기능으로 대체수행하여 장애를 회피함 ope

bangpurin.tistory.com

2024.02.08 - [개발/spring-cloud] - [spring-cloud] zipkin 분산 환경 모니터링

 

[spring-cloud] zipkin 분산 환경 모니터링

환경: springboot2.7.6, spring cloud2021.0.8, java17 zipkin 분산 환경의 데이터 수집, 추적 시스템(오픈소스, 트위터 시작, google drapper에서 발전) 분산 환경에서의 시스템 병목 현상 파악 collector, query service, da

bangpurin.tistory.com

2024.02.08 - [개발/spring-cloud] - [spring-cloud] micrometer, prometheus

 

[spring-cloud] micrometer, prometheus

환경: springboot2.7.6, java17 micrometer jvm 기반의 애플리캐이션 metrics 제공 springboot2 + premetheus 등 다양한 모니터링 시스템 지원 (구) turbine server -> hystrix client timer 짧은 지연 시간, 이벤트의 사용 빈도

bangpurin.tistory.com

2024.02.08 - [서버 세팅 & tool] - [windows] prometheus & grafana 설치

 

[windows] prometheus & grafana 설치

환경: windows11, springboot2.7.6, java17 prometheus(저장 서버) metrics를 수집하고 모니터링 및 알람에 사용되는 오픈소스 애플리케이션 시간순으로 데이터가 남음(time series database; TSDB) pull 방식의 구조와

bangpurin.tistory.com

2024.02.10 - [서버 세팅 & tool/docker] - [windows] docker; 컨테이너 가상화

 

[windows] docker; 컨테이너 가상화

환경: windows11 virtualization 물리적인 컴퓨터 리소스를 다른 시스템이나 애플리케이션에서 사용할 수 있도록 제공 플랫폼 가상화 리소스 가상화 하이퍼바이저(hypervisor) Virtual machine manager(VMM) 다수

bangpurin.tistory.com

2024.02.10 - [서버 세팅 & tool/docker] - [windows] docker 이미지 만들고 올리고 실행

 

[windows] docker 이미지 만들고 올리고 실행

환경: windows11, 아래 설치 진행 2024.02.10 - [서버 세팅 & tool/docker] - [windows] docker; 컨테이너 가상화 [windows] docker; 컨테이너 가상화 virtualization 물리적인 컴퓨터 리소스를 다른 시스템이나 애플리케이

bangpurin.tistory.com

2024.02.12 - [서버 세팅 & tool/docker] - [windows] 네트워크 세팅, rabbitmq 세팅, config server 세팅

 

[windows] 네트워크 세팅, rabbitmq 세팅, config server 세팅

환경: windows11, springboot2.7.6, java17 2024.02.10 - [서버 세팅 & tool/docker] - [windows] docker 이미지 만들고 올리고 실행 [windows] docker 이미지 만들고 올리고 실행 환경: windows11, 아래 설치 진행 2024.02.10 - [서버

bangpurin.tistory.com

2024.02.18 - [서버 세팅 & tool/docker] - [windows] discovery server 세팅, docker 배포

 

[windows] discovery server 세팅, docker 배포

환경: windows11, springboot2.7.6, java17 2024.02.12 - [서버 세팅 & tool/docker] - [windows] 네트워크 세팅, rabbitmq 세팅, config server 세팅 [windows] 네트워크 세팅, rabbitmq 세팅, config server 세팅 환경: windows11, springboot2

bangpurin.tistory.com

2024.02.18 - [서버 세팅 & tool/docker] - [windows] gateway server 세팅, docker 배포

 

[windows] gateway server 세팅, docker 배포

환경: windows11, springboot2.7.6, java17 2024.02.12 - [서버 세팅 & tool/docker] - [windows] 네트워크 세팅, rabbitmq 세팅, config server 세팅 2024.02.18 - [서버 세팅 & tool/docker] - [windows] discovery server 세팅, docker 배포 gatew

bangpurin.tistory.com

2024.02.18 - [서버 세팅 & tool/docker] - [windows] mariadb 세팅, docker 배포

 

[windows] mariadb 세팅, docker 배포

환경: windows11, springboot2.7.6, java17 2024.02.18 - [서버 세팅 & tool/docker] - [windows] gateway server 세팅, docker 배포 2024.02.04 - [서버 세팅 & tool/kafka] - [windows] kakfa connect; mariadb 설치 마리아 DB는 프로젝트가 아

bangpurin.tistory.com

2024.02.25 - [서버 세팅 & tool/docker] - [windows] kafka/zookeeper docker배포, docker compose

 

[windows] kafka/zookeeper docker배포, docker compose

환경: windows11, springboot2.7.6, java17 DOCKER COMPOSE? Simplified control: Docker Compose allows you to define and manage multi-container applications in a single YAML file. https://docs.docker.com/compose/intro/features-uses/#:~:text=Simplified%20cont

bangpurin.tistory.com

2024.02.25 - [서버 세팅 & tool/docker] - [windows] zipkin 서버 docker 배포

 

[windows] zipkin 서버 docker 배포

환경: windows11, springboot2.7.6, java17 공식 사이트에서 제공하는 도커 이미지를 띄워보기 https://zipkin.io/pages/quickstart.html Quickstart · OpenZipkin Quickstart In this section we’ll walk through building and starting an instan

bangpurin.tistory.com

2024.02.25 - [서버 세팅 & tool/docker] - [windows] prometheus+grafana docker 배포

 

[windows] prometheus+grafana docker 배포

환경: windows11, springboot2.7.6, java17 공식 사이트에서 제공하는 도커 이미지를 띄워보기 도커이미지 프로메테우스 https://hub.docker.com/u/prom Docker hub.docker.com 그라파나 https://grafana.com/docs/grafana/latest/setu

bangpurin.tistory.com

2024.02.29 - [서버 세팅 & tool/docker] - [windows] user-service server 세팅, docker 배포

 

[windows] user-service server 세팅, docker 배포

환경: windows11, springboot2.7.6, java17 springboot 프로젝트인 user service 를 도커에 올려본다. 1. pom.xml 경로에 Dockerfile 생성 FROM openjdk:17-ea-slim-buster VOLUME /tmp COPY target/user-service-1.0.jar user-service.jar ENTRYPOINT ["

bangpurin.tistory.com

2024.02.29 - [서버 세팅 & tool/docker] - [windows] order-service server 세팅, docker 배포

 

[windows] order-service server 세팅, docker 배포

환경: windows11, springboot2.7.6, java17 springboot 프로젝트인 order service 를 도커에 올려본다. 1. pom.xml 경로에 Dockerfile 생성 FROM openjdk:17-ea-slim-buster VOLUME /tmp COPY target/order-service-1.0.jar order-service.jar ENTRYPOINT

bangpurin.tistory.com

2024.02.29 - [서버 세팅 & tool/docker] - [windows] catalog-server 세팅, docker 배포

 

[windows] catalog-server 세팅, docker 배포

환경: windows11, springboot2.7.6, java17 springboot 프로젝트인 catalog service 를 도커에 올려본다. 1. pom.xml 경로에 Dockerfile 생성 FROM openjdk:17-ea-slim-buster VOLUME /tmp COPY target/catalog-service-1.0.jar catalog-service.jar ENTR

bangpurin.tistory.com

2024.02.29 - [개발/spring] - [application.yml] 프로파일 옵션으로 배포 설정 분리

 

[application.yml] 프로파일 옵션으로 배포 설정 분리

환경: springboot2.7.6 로컬에서 개발할 때, 그리고 운영 환경으로 배포할 때 내용물에 따라 설정파일을 분리할 수 있으며, 환경에 따라 다르게 가져가야 한다. -- 소스 실행 mvn spring-boot:run -Dspring-boot.

bangpurin.tistory.com

2024.02.29 - [architecture/micro service] - [arch] event sourcing, cqrs, saga

 

[arch] event sourcing, cqrs, saga

event sourcing event driven architecture monolithic 단일 데이터베이스 트랜잭션 처리를 완벽하게 -> ACID atomicity consistency isloation durable msa 각 서비스마다 독립적인 데이터베이스(polyglot) API를 통해 접근 atomicy

bangpurin.tistory.com

 

도커에 모두 구성하고 최종 테스트

1. 유저 생성

2. 주문

3. 주문 후 수량 감소 확인

4. 주문 후 유저 매핑 확인

728x90
반응형

'architecture > micro service' 카테고리의 다른 글

2PC vs 2PL  (1) 2024.11.06
[arch] EDA, event sourcing, saga, 2pc  (0) 2024.02.29
[gRPC] gRPC gateway란  (0) 2022.01.24
[arch] gRPC란?  (0) 2022.01.20
[arch] DDD pattern 와 aggregate란  (0) 2022.01.13
반응형

유지보수하기 좋은 코드를 구현하는 개발 문화 어떻게 만들 것인가? by 박재성님

 

1. 변화를 어떻게 가져오는가

  • 의지력이 아닌 환경. 환경(상황)을 바꿔라
    • 퇴근 후 다른 곳(스터디 카페)으로 퇴근한다
    • 티비를 버린다, 폰을 버린다. 앱을 삭제한다.. 등
  • 책임감
    • 삶이 앞으로 나아가는데 필요한 견인력

 

2. 의식적인 연습

  • 그냥 한다고 다 되는건 아닌건 아니다. 목적이 있는, 의식이 있는 연습이 필요하다.
  • comfort zone을 벗어난 지점에서 진행, 자신의 현재 능력을 살짝 넘어가는 작업을 지속적으로 시도
  • 명확하고 구체적인 목표를 가지고..
  • 신중하고 계획적으로, 온전히 집중하고 의식적으로 행동할 것을 요구
  • 피드백과 피드백에 따른 행동 변경

2-1. 요즘 제일 비싼 비용은? 인건비!! => 가독성이 제일 중요; 읽기 좋은 코드

  • 인덴트를 줄이고
  • else를 없애고
  • stream을 써보고
  • 메서드 분리! 

 

  • 모든 원시값과 문자열을 포장한다.
  • 일급 콜렉션
  • 3개 이상의 인스턴스 변수를 가진 클래스를 쓰지 않는다.
  • 함수의 인자 수를 줄인다. 3개 이상은 가급적 피한다.
  • 클래스 분리

 

3. 리팩하려면 테스트 코드가 기반이 되어야 함

 

4. 개인 -> 동료로 영향력 확대 => 힘든게 당연하다.

변화를 만들려면 리더쉽을 발휘하고 감정 노동을 해야한다.

리더쉽 / 감정 노동은 AI 시대에 가장 필요한 역량이다...ㅋ

- 사람은 변화를 거부해

- 팀은 더 거부해

- 대부분의 사람들은 변화에 실패해봤어

 

4-1. 시작

묵묵히 혼자 진행!! 내가 맡은 기능에는 적용. 나를 위해서

-> 관심있는 사람이 생기면 전파

-> 작은 성공 경험

 

4-2. 리팩기준(레이어드 아키텍처)

서비스의 로직을 도메인으로...

-> TDD하기 쉬움

- 서비스 : 도메인 객체 생성, 메세지 보내는 역할, 외부에 전달 only

- 도메인에 로직 구현하면 mock할게 없으니까 테스트가 쉽다는거임..

 

5. 리더/시니어로서 만들고 싶은 개발 문화

거창한 포부! 야 우리 같이 성장하쟈???

* 아웃사이드 인 접근 방식: 외부에, 과거에 좋았다고 한 것들을 그대로 도입(탑다운)

-> 실패의 지름길

 

* 인사이드 아웃 접근 방식: 팀원들의 의견에 의한 변화; 시간이 오래걸림(바텀업)

  • 리더가 하자고하면 싫어함(뭘 듣고 왔다냐)
  • 팀원들은 침묵을 선택한다. 나한테 이득이 어딧나
  • 팀원들 말문이 트어야 한다.
  • 어떤 의견을 제기해도 벌을 받거나 보복당하지 않을 거라고 믿는 조직
  • 팀원들과의 신뢰 형성이 우선
    • 1:1 면담
      • 어떻게 하면 될까? 너라면 어떻게 할래? -> 해답을 스스로 제시하도록
    • 잘 듣고 힘들겟구나 공감하고, 반문
    • 이 중 우선순위 높고, 가장 효과있을 것 하나 골라서 시작, 익숙해질 때 까지 집중
    • 하나만 성공하도록 -> 성공 경험이 중요; 한번에 한 가지에 집중 -> 작은 성공

> 도서 "두려움 없는 조직" 추천

- 심리적 안정감! 이 필요


정리

  • 새로운 문화를 정착하기 위해 가장 중요한 것은 리더의 인내심의 용기
  • 새로운 문화를 만들면서 초기 학습 비용 등으로 인해 생산성 저하
  • 안정화하는데 최소 1년 이상의 시간을 투자해야 한다는 마음으로 믿고 기다려야 함
  • 현재보다 조금씩 나아지고 있다는 방향성이 중요
    • 중요한 것은 지금 어떤 practice를 적용하는가가 아님
  • 문화를 만들고 변화를 만드는 일은 리더만의 책임이 아니다.
  • 누구도 대체할 수 없는 존재가 되고 싶으면 지금 당장 도전
  • 좋은 회사는 실패해도 같이 도전하는 사람을 원한다.
  • 실패의 책임을 묻는다면 그만둔다. 굳

 

사람에 대한 존중, 신뢰, 심리적 안정감이 기반되어야 한다.

728x90
반응형

'architecture > knowledge' 카테고리의 다른 글

[http] http 기본 지식  (0) 2022.05.19
웹브라우저 요청 흐름  (0) 2022.05.19
[webwork] struts? webwork? xwork?  (0) 2022.01.17
반응형

람다 아키텍처

 대규모 데이터 처리 시스템을 위한 아키텍처 패턴

: 실시간 분석, 추천, 모니터링 등에 사용

  • 과거 데이터: summary data 있고
  • 신규 데이터: 최신 데이터
    • 두 개를 조합

실시간으로 들어오는 데이터와 배치 처리가 필요한 대용량 데이터를 동시에 처리하는 구조를 제공하여, 빠른 응답성과 정확성을 모두 확보하는 데 중점을 둡니다. 데이터의 수집, 처리, 분석을 효과적으로 수행하기 위해 다음과 같은 3가지 계층으로 나뉩니다.

1. 배치 레이어 (Batch Layer)

  • 역할: 대량의 데이터에서 정확한 집계와 분석을 위해 주기적인 배치 처리를 수행합니다.
  • 특징: 배치 레이어에서는 데이터가 정해진 주기에 따라 한 번에 대량으로 처리됩니다. 이때 데이터의 불변성을 유지하여 전체 데이터를 매번 다시 계산해 정확도를 보장합니다.
  • 사용 예: Hadoop, Apache Spark 등 분산 배치 처리 시스템.
  • 장점: 모든 데이터를 기반으로 계산하기 때문에 데이터 손실이 없고 최종적으로 신뢰할 수 있는 결과를 제공합니다.

2. 실시간 레이어 (Speed Layer)

  • 역할: 실시간으로 들어오는 데이터를 빠르게 처리하여 최신의 데이터에 대한 결과를 제공합니다.
  • 특징: 배치 레이어가 대규모 데이터에 대해 전체적으로 정확한 처리를 수행하는 반면, 실시간 레이어는 최신 데이터에 대한 빠른 처리와 분석을 제공합니다. 이 레이어에서는 배치 레이어에서 처리된 데이터와 별도로 결과를 제공하여 빠르게 대응할 수 있도록 합니다.
  • 사용 예: Apache Storm, Apache Kafka, Apache Flink.
  • 단점: 실시간 처리는 모든 데이터를 종합하지 않기 때문에 정확도에 제한이 있을 수 있습니다.

3. 서빙 레이어 (Serving Layer)

  • 역할: 배치 레이어와 실시간 레이어의 결과를 결합하여 사용자에게 최종적인 분석 결과를 제공합니다.
  • 특징: 서빙 레이어는 배치 및 실시간 레이어에서 계산된 결과를 사용자에게 빠르게 응답할 수 있도록 구성됩니다. 두 레이어의 결과를 결합하여 정확하고 최신화된 정보를 제공하는 역할을 합니다.
  • 사용 예: Apache HBase, Cassandra와 같은 NoSQL 데이터베이스.

람다 아키텍처의 장단점

  • 장점
    • 확장성: 대규모 데이터와 실시간 데이터를 모두 효율적으로 처리할 수 있어 시스템 확장이 용이합니다.
    • 내결함성: 실시간 처리가 실패해도 배치 처리가 보완할 수 있는 구조입니다.
    • 정확성: 실시간 데이터는 빠르게 처리하고, 배치 처리는 전체 데이터를 기준으로 정확도를 보장합니다.
  • 단점
    • 복잡성: 배치 레이어와 실시간 레이어를 동시에 관리하고 결합해야 하므로 시스템이 복잡해질 수 있습니다.
    • 유지보수 부담: 실시간과 배치 두 가지 흐름을 동시에 관리해야 하므로 유지보수가 어려울 수 있습니다.
  • 고민
    • 배치로 중간 데이터를 만들었는데.. 지나고 이전 데이터가 들어온다면  지난 데이터를 버릴 건지 다시 배치를 돌릴 건지??

 

-> 카파 아키텍처(kappa)

카파 아키텍처(Kappa Architecture)는 대용량의 실시간 데이터 처리를 위해 설계된 아키텍처로, 람다 아키텍처의 복잡성을 줄이기 위해 제안되었습니다. 카파 아키텍처는 실시간 스트리밍 데이터의 분석과 처리를 중점으로 하며, 배치 레이어 없이 단일 데이터 처리 경로만을 사용하는 점이 특징입니다. 이는 시스템의 단순성과 유지보수를 고려한 접근 방식으로, 변화가 빠른 환경에서도 효율적으로 동작합니다.

카파 아키텍처의 주요 특징

  1. 단일 데이터 경로 (Single Pathway)
    • 카파 아키텍처에서는 데이터를 오직 하나의 경로로 처리합니다. 이 데이터 경로는 실시간 스트리밍 처리를 위한 스트림 처리 엔진을 사용하며, 람다 아키텍처의 배치 레이어가 없는 구조입니다.
    • 데이터가 들어오면 스트림 처리 시스템을 통해 처리되며, 필요한 경우 결과를 실시간으로 업데이트합니다.
  2. 실시간 데이터 처리
    • 카파 아키텍처는 실시간 처리를 핵심으로 하여, 들어오는 데이터를 신속하게 처리하고 분석하는 데 집중합니다.
    • 지속적인 스트림 데이터와 그 결과를 실시간으로 쌓아 두기 때문에 새로운 데이터에 빠르게 대응할 수 있습니다.
  3. 데이터의 불변성 유지
    • 카파 아키텍처에서도 데이터는 원본 형태로 저장되고, 필요에 따라 재처리할 수 있도록 불변성을 유지합니다.
    • 스트림 처리 엔진을 통해 재처리가 필요할 경우 저장된 원본 데이터를 다시 처리할 수 있습니다.
  4. 간단한 구조
    • 배치 처리를 제거하고 스트림 처리를 중심으로 설계해 단순한 아키텍처를 유지합니다.
    • 이는 개발 및 유지보수의 복잡성을 크게 줄여 주며, 특히 운영과 관리 측면에서 효율적입니다.

카파 아키텍처의 구현 방식

  • 스트림 처리 엔진: 카파 아키텍처에서 중요한 역할을 하는 요소로, Apache Kafka, Apache Flink, Apache Samza 등이 자주 사용됩니다. 이들 엔진은 대용량의 스트리밍 데이터를 고성능으로 처리하는 데 적합합니다.
    • 카프카에서 데이터를 재정렬, 필터링 등 여러 액션을 할 수 있음
  • 데이터 저장소: 원본 데이터를 저장하는 시스템으로, Apache HBase, Cassandra, Elasticsearch와 같은 NoSQL 데이터베이스나 Kafka 같은 메시징 시스템이 사용됩니다.
    • Apache Iceberg 사용하는 추세
      • Apache Iceberg는 대규모 분석 데이터 테이블을 위한 고성능 오픈 소스 테이블 포맷입니다. Iceberg는 데이터를 대규모로 효율적으로 관리하고 처리할 수 있도록 설계되었으며, 특히 빅데이터 환경에서 기존 테이블 포맷의 문제를 해결하는 데 중점을 두고 있습니다. Iceberg는 데이터 레이크에서 다양한 저장소 및 파일 포맷을 지원하면서도 ACID 트랜잭션을 제공하고, 강력한 스키마 관리와 높은 쿼리 성능을 제공합니다.
      • 과거와 현재 데이터를 중간에 스냅샷을 찍어서 관리하는 구조

카파 아키텍처의 장단점

  • 장점
    • 단순성: 배치 레이어를 제거하고 스트림 처리만 사용하여 시스템 구조가 단순합니다.
    • 빠른 대응: 실시간 데이터를 실시간으로 처리할 수 있어 최신 데이터를 활용한 분석이 용이합니다.
    • 유지보수 용이: 단일 데이터 경로만 관리하므로 복잡한 유지보수 작업을 줄여줍니다.
    • 읽기 속도가 좋고 람다보다 유연
  • 단점
    • 재처리 문제: 배치 처리가 없기 때문에 모든 데이터를 실시간으로 처리하며, 재처리가 필요한 경우 스트림 처리 엔진에 추가적인 부담이 될 수 있습니다.
    • 적용 한계: 대용량 데이터의 정확한 분석이 필요하거나 일괄처리가 필요한 환경에서는 적합하지 않을 수 있습니다.

카파 아키텍처 vs 람다 아키텍처

카파 아키텍처는 람다 아키텍처와는 달리 실시간 스트리밍 처리만을 사용하여 시스템을 단순화합니다. 이를 통해 람다 아키텍처에서 필요했던 두 경로의 중복 코드나 복잡한 데이터 일관성 유지 문제를 해결할 수 있습니다. 그러나 재처리나 정밀한 배치 처리가 필요한 환경에서는 여전히 람다 아키텍처가 유리할 수 있습니다.

728x90
반응형

'architecture > sw architecture' 카테고리의 다른 글

[OpenTelemetry] observability 아키텍쳐  (0) 2025.02.25
[design] proxy pattern 프록시 패턴  (0) 2022.04.25
반응형

팀 내에서 코드 리뷰를 하고 있지만 어떻게 하는 것이 서로에게 좋은 시너지를 낼 수 있는 방법인지 확신이 서지 않을 때가 많았다. 누구 하나 가이드를 주지 않고 작성하다 보니 종종 의도하지 않은 상처를 준다거나 상처를 받았던 경우가 생기는 것 같아 더 나은 협업을 위한 방법을 모색하게 된다.

아래 영상은 그 일환으로 시청했던 것인데 매우 유익하고 공감 가는 내용이 많아서 정리하려고 한다.

 

1. 효율적인 코드 리뷰하기

코드 리뷰의 어려움:

  • 생각을 글로 전하는 것에 대한 어려움, 피드백을 조심스럽게 표현하는 것이 더 중요.

 

팀 내의 노력:

  • 지루한 작업은 컴퓨터로 처리(공백, 들여 쓰기 등)
  • 스타일 가이드를 통해 스타일 논쟁 해소
  • 모두를 포함하라

 

저자의 노력:

  • 의미 있는 커밋으로 분리(나중에 나의 코드조차 낯설다, 커밋도 로그, 잘 정리하면 미래에 모두에게 도움이 된다)
  • pr 올릴 때 주석 달기
  • 저자가 먼저 읽어보고 -> 리뷰어들을 위한 설명을 코멘트로 남겨서 -> 리뷰어들의 시간을 절약할 수 있게 하라
  • pr은 적게(반나절 작업한 정도) 자주 올리는 게 좋다(리뷰할 시간이 없다고 생각하면 안 됨)

 

리뷰어의 노력:

  • 리뷰는 즉시 시작하라
  • 고수준 피드백(버그, 장애, 성능, 보안)에 대해 먼저 잡고 -> 저수준 피드백(설계 개선, 변수명, 주석 등)을 남기자
  • 리뷰 라운드에서 너무 많은 의견을 남기면 저자가 당황할 수도.. 한 라운드에 20~50개는 위험의 시작.
  • 한 두 등급만 코드 레벨을 올리는 것을 목표로, 완전하지는 않아도 충분히 좋은 코드가 되도록
  • Nit 태그: 고치면 좋지만 아니어도 그만, 개선할 수 있는 의견을 자유롭게 남길 수 있어야 함

 

피드백 방법:

  • 진정한 칭찬이 필요 -> 우리는 잔인한 감시자가 아니라 도와주려는 팀 동료
  • 피드백은 명령이 아니라 요청(나의 걱정): 하세요 XXX ~하는 게 어떨까요? OOO
  • 원칙에 기반한 제안(~에 맞으려면 이렇게 하는 게 더 좋을 것 같아요)
  • 항상 원칙에 기반하여 설명할 수 있는건 아니다. 이럴 땐 무엇을 할 수 있을지 객관적인 설명이 필요하다.
  • 반복적인 이슈는 다 말할 필요 없다(2~3개의 예시를 언급하고 그 이상은 비슷한 패턴에 대해 수정 요구)
  • 그러려니~ 하는 마인드 필요, 우리는 싸우려고 코드 리뷰하는 게 아니다. 동료와의 협업이 훨씬 중요한 것이다.
  • 팀을 유지하기 위해 불완전한 해결책을 받아들여라. 모든 결함이 항상 문제가 되지는 않음
  • 코드 리뷰의 목적은 비난이 아니라 배움이다.

 


 

2. git commit message structure

기본적으로 커밋 메시지는 아래와 같이 제목(subject), 본문(body), 꼬리말(footer)로 구성된다.

<타입>[적용 범위(선택 사항)]: <설명>

[본문(선택 사항)]

[꼬리말(선택 사항)]
  • <설명>은 50자 이내로 작성, 마침표 찍지 않는다.
  • 타입에는 아래와 같은 값들이 올 수 있다.

commit types

  • body는 선택사항으로 모든 커밋에 작성할 필요는 없지만 부연설명이 필요할 경우 72자 이내로 작성한다. 제목과 구분하기 위해 한 칸 띄어 쓰고 시작한다.
  • footer는 issuer trackerId(이슈 문서 id 등)를 기입하는데 주로 사용된다.

 

참고: 더 디테일한 commit message

https://medium.com/humanscape-tech/%ED%9A%A8%EC%9C%A8%EC%A0%81%EC%9D%B8-commit-message-%EC%9E%91%EC%84%B1%EC%9D%84-%EC%9C%84%ED%95%9C-conventional-commits-ae885898e754

 

효율적인 commit message 작성을 위한 conventional commits

안녕하세요 휴먼스케이프 개발자 Jake 입니다.

medium.com

https://haesoo9410.tistory.com/299

 

<Git> 커밋 메시지 컨벤션 : 중요성 및 규칙 (feat. 템플릿)

1. 커밋 메시지 * 중요성  - 다음은 자바 스프링의 오래된 커밋 로그이다. $ git log --oneline -5 --author cbeams --before "Fri Mar 26 2009" e5f4b49 Re-adding ConfigurationPostProcessorTests after its..

haesoo9410.tistory.com

 

2-1. 커밋 시 자동으로 commit format 띄우기

아래와 같이 format 파일을 만들고 커밋을 친다. 이름은 아무거나 해도 되는데 나는 /.github/.gitmessage 로 저장하였다.

# 제목은 대문자로 시작합니다.
# 제목에는 타입,콜론,스페이스로 시작합니다.
# ex. Fix: typo in baduk.js
# 본문과 푸터는 선택 사항 입니다.
#######제목#######
Add: commit format
#######본문#######

#######푸터#######

######### 타입 #########
# Fix : 수정
# Add : 추가
# Remove : 삭제
# Simplify : 단순화
# Update : 보완
# Implement : 구현
# Prevent : 방지
# Move : 이동
# Rename : 이름변경
##################

 

아래와 같이 템플렛으로 지정한다는 명령어를 터미널에 입력한다.

git config --global commit.template .github/.gitmessage editor
## --global 옵션을 주면 전 프로젝트에 적용된다.

git config --unset-all --global commit.template
## 템플렛 취소

commit.template로. gitmessage라는 파일을 사용한다는 뜻이고, 마지막에 editor는 커밋할 때마다 editor가 떠서 메시지를 수정하게 한다는 뜻이다(vim으로 지정해도 된다).

이를 활용하여 커밋하려고 하면 터미널에 아래와 같은 순으로 작업한다.

git add [파일명]
git commit
## //-> 이러면 premade한 에디터가 뜨고 메세지를 수정 후 :wq 로 저장하고 나온다.
git push

이 방법의 문제는

  1. 개개인별로 설정해야 한다. 팀에 일괄 설정 안 됨
  2. 터미널에서밖에 안된다. git kraken이나 sourcetree 같은 툴에서는 주석이 먹지 않아서.. 매우 번거로워진다.

 

참고로 한글로 메시지를 쓸 경우 깨지는 경우가 허다.. 해서 아래와 같은 추가 노력이 필요할 수 있다.

https://velog.io/@haejung/Git-%EC%BB%A4%EB%B0%8B-%EB%A9%94%EC%8B%9C%EC%A7%80%EB%A5%BC-%EC%9C%84%ED%95%9C-Editor-%EC%84%A4%EC%A0%95-5072

 

Git 커밋 메시지를 위한 Editor 설정 (50/72)

앞서 소개했던 50/72 규칙에 맞는 커밋 메시지 작성을 조금더 수월하게 하기 위한 Editor 설정을 소개합니다. 아래 다른 블로그의 내용을 참조했습니다.Mac OSGitVSCode (커밋 메시지 Editor)D2Coding 글꼴커

velog.io


 

3. git pr format 생성

좋은 코드 리뷰란?
저자가 고생해서 리뷰어의 시간을 아껴줘야

https://www.youtube.com/watch?v=TAPviNhFuSg

  • git 자동으로 pr format 생성하는 법
  • pull_request_template.md 파일을 아래 링크처럼 생성하고
  • 이 파일을 git의 default branch(보통 master or main)에 커밋을 해야! 그다음부터 적용된다.

https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/creating-a-pull-request-template-for-your-repository

 

Creating a pull request template for your repository - GitHub Docs

For more information, see "About issue and pull request templates." You can create a PULL_REQUEST_TEMPLATE/ subdirectory in any of the supported folders to contain multiple pull request templates, and use the template query parameter to specify the templat

docs.github.com

 

728x90
반응형
반응형

인프런, 김영한님의 모든 개발자를 위한 http 웹 기본 지식 강의를 기반으로 함.

 

post를 사용한 등록

  • POST /members
  • 서버가 새로 등록된 리소스 uri를 생성해준다.
  • collection(컬랙션)
    • 서버가 관리하는 리소스 디렉토리
    • 서버가 리소스 uri를 생성하고 관리
    • 위 예시에서 컬랙션은 /members

 

put을 사용한 등록

  • PUT /files/star.jpg
  • 클라이언트가 직접 리소스의 uri를 지정한다.
  • store(스토어)
    • 클라이언트가 관리하는 리소스 저장소
    • 클라이언트가 리소스 uri를 알고 관리
    • 위 예시에서 스토어는 /files

 

html form :

  • GET/POST 만 지원
  • 헤더:Content-Type: application/x-www-form-urlencoded
  • 파일 업로드 같은 바이너리 데이터 전송 시 헤더; Content-Type: multipart/form-data
  • GET/POST만 지원하기 때문에 control-uri를 사용하여 부가적인 설명을 함(/edit, /delete 등)

 

관련 용어

관련 용어

 

PRG: post/redirect/get; 일시적인 리다이렉션(307)

  • POST로 주문후에 새로 고침으로 인한 중복 주문 방지
  • POST로 주문후에 주문 결과 화면을 GET 메서드로 리다이렉트
  • 새로고침해도 결과 화면을 GET으로 조회
  • 중복 주문 대신에 결과 화면만 GET으로 다시 요청

PRG

 

 

 

 


api url naming 참고: https://restfulapi.net/resource-naming/

 

REST Resource Naming Guide

In REST, having a strong and consistent REST resource naming strategy – will prove one of the best design decisions in the long term.

restfulapi.net

 

728x90
반응형
반응형

김영한님 버전

1. 도메인 주소 치고 엔터

2. 웹브라우저가 DNS 서버 조회 -> ip/port 정보를 찾아와 -> http 요청 메시지 생성

[DNS 흐름]

(로컬피씨) 브라우저 캐시 -> 로컬 DNS(OS) 캐시 -> 호스트파일

(외부)  <-> 로컬 DNS서버(ISP나 회사 네트워크):: 캐시 <-> 루트 네임서버 <-> TLD네임서버(.com) <-> 권한있는 네임서버

 

3. 브라우저는 http 메세지 생성 후 -> 소캣 라이브러리를 이용해서 tcp/ip 3 hand shake 후 데이터 전달 -> 패킷 생성

4. 인터넷 망으로 던져, ip 찾아가

5. 도착하면 tcp/ip까서 버리고 http메시지만 꺼내서 해석

6. 응답 메세지 만들어서 tcp/ip 씌워서 전송

7. 다시 응답을 받고, http메시지 꺼내서 그 결과를 브라우저에 출력(html 렌더링)

728x90
반응형
반응형

프록시 패턴

  • 인터페이스를 구현을 통해 진짜 구현체를 대신하여 부가기능을 제공하거나 리턴 값을 변경할 수 있도록 대리자(surrogate)나 자리표시자(placeholder)의 역할을 하는 객체를 제공하는 패턴

각 클래스는 자신이 해야 할 일(SRP: Single Responsibility Principle)만 해야하는데 부가적인 기증을 제공할 때 이런 패턴을 주로 사용함

하지만 부가적인 기능을 추가할 때마다 위임하는 코드가 중복해서 발생할 수 있음

코딩 예시: https://bamdule.tistory.com/154

 

[디자인 패턴] 프록시 패턴 (Proxy Pattern)

1. 프록시 패턴이란? 실제 객체를 바로 이용하는 것 대신 가상 객체에 실제 객체를 선언하여 실제 객체의 기능과 추가적인 기능을 사용함으로 써 기능의 흐름을 제어하는 디자인 패턴입니다. 2.

bamdule.tistory.com

 


매번 클래스를 만드는게 아니라 동적으로 생성하는 방식

-> java reflextion을 활용한 다이내믹 프록시 사용

  • (컴파일 타임이 아닌) 런타임에 인터페이스를 구현하는 클래스/프록시 인스턴스를 만들어 사용하는 프로그래밍 기법

프록시 인스턴스 만들기

  • Object Proxy.newProxyInstance(ClassLoader, Interfaces, InvocationHandler)
    • object로 리턴되기 때문에 type casting 필요
//BookService는 반드시 인터페이스여야 함
BookService bookService = (BookService) Proxy.newProxyInstance(BookService.class.getClassLoader(), new Class[]{BookService.class},
        new InvocationHandler() {
            BookService bookService = new DefaultBookService();
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                if (method.getName().equals("rent")) { //rent 라는 method에만 적용하고 싶다면
                    System.out.println("aaaa");
                    Object invoke = method.invoke(bookService, args);
                    System.out.println("bbbb");
                    return invoke;
                }
             //나머지 method는 그대로 리턴
                return method.invoke(bookService, args);
            }
        });

근데 매번 이렇게 구현하는 게 더 복잡, 유연한 구조가 아님.

그리고 클래스 기반의 (자바가 제공하는) proxy를 만들 수 없음.

-> 그래서 Spring AOP(프록시 기반의 AOP)가 등장

 


클래스의 프록시가 필요하다면?

-> subclass를 만들어서 프록시를 만드는 라이브러리를 사용

 

CGlib lib 사용

  • https://github.com/cglib/cglib/wiki
  • 스프링, 하이버네이트가 사용하는 라이브러리
  • 버전 호환성이 좋지 않아서 서로 다른 라이브러리 내부에 내장된 형태로 제공되기도 한다.
MethodInterceptor handler = new MethodInterceptor() {
    BookService bookService = new BookService(); //class
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        if(method.getName().equals("rent")){ //method 이름이 rent 일 때만 작업
            log.info("aaa");
            Objet invoke = method.invoke(bookService, args);
            log.info("bb");
            return invoke;
        }
        //나머지 method는 그대로 리턴
        return method.invoke(bookService, args);
    }
};

BookService bookService = (BookService) Enhancer.create(BookService.class, handler);

 

ByteBuddy lib 사용

  • https://bytebuddy.net/#
  • 스프링에서 버전 관리해줌
  • 바이트 코드 조작뿐 아니라 런타임(다이내믹) 프록시를 만들 때도 사용할 수 있다.
Class<? extends BookService> proxyClass = new ByteBuddy().subclass(BookService.class)
        .method(named("rent")) //method 이름이 rent면 적용
        .intercept(InvocationHanderAdaptor.of(new InvocationHander(){
            BookService bookService = new BookService();
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
                log.info("aaa");
                Object invoke = method.invoke(bookService, args);
                log.info("Bbb");
                return invoke;
            }
        }))
        .make().load(BookService.class.getClassLoader()).getLoaded();
BookService bookService = proxyClass.getConstructor(null).newInstance();

 

서브 클래스를 만드는 방법의 단점

  • 상속(extends)을 사용하지 못하는 경우 프록시를 만들 수 없음
    • private 생성자(하위 클래스에서 항상 부모의 생성자를 호출한다)
    • final 클래스
  • 인터페이스가 있을 때는 인터페이스의 프록시를 만들어 사용할 것.

 

다이내믹 프록시 기법이 사용되는 곳

  • 스프링 데이터 JPA
  • 스프링 AOP
  • Mockito
  • 하이버네이트 lazy initialization(@OneToMany 등 entity 들고 있을 때 프록시 객체로 처음에 리턴)

 

728x90
반응형
반응형

gRPC proxy? gateway?

두 명칭이 혼용되는 것 같으나, 개념을 보면 같은 것을 알 수 있음

Grpc-gateway, a server for gRPC and RESTful styles Grpc-gateway is a server that routes HTTP/1.1 request with JSON bodies to gRPC handlers with protobuf bodies. This means you can define your entire API as gRPC methods with requests and responses defined as protobuf, and then implement those gRPC handlers on your API server. Grpc-gateway can then transform your gRPC service into a RESTful API.

gRPC gateway는 client로부터 restfulAPI형식으로(HTTP JSON) 정보를 받고, 이 정보를 gRPC server 서비스의 형식대로 protobuf로 변환한 다음에 그 message를 gRPC server에 gRPC로 보내는 서버다. 주로 rpc 통신이 힘든 경우 converter로 사용한다. 

gRPC gateway

gRPC Gateway 플러그인을 사용하면 gRPC 서비스에 REST API 인터페이스를 제공할 수 있도록 go 런타임에서 작동하는 프록시 서버와 Swagger 문서를 generate 해준다. (go 이외 다른 언어는 미지원) 

https://medium.com/@thinhda/compare-grpc-web-with-grpc-gateway-fa1e2acdf29f

 

Compare gRPC-Web with grpc-gateway

gRPC-Web and grpc-gateway have advantages and disadvantages. Depending on your business, what you have and what you need, …

medium.com

https://deepbaksu.github.io/2021/05/01/how-to-REST-from-gRPC/

 

gRPC에서 REST까지

gRPC를 통해 REST 서버를 만들어 보자. gRPC 클라이언트로 연결할 수 있으면 좋지만, REST가 보편적이기 때문에 REST API를 구현해줘야 할 필요가 있다. 또한, Heroku에서는 HTTP/2 를 지원하지 않기 때문에

deepbaksu.github.io

 

js에서 바로 gRPC 서버로 통신을 하려고 하는 경우?

JavaScript running in the browser does not provide full control over HTTP2.
The gRPC protocol uses features of HTTP/2 that cannot be controlled by JavaScript.
So that a proxy is required.

gRPC-WEB은 gRPC를 브라우저에서 사용가능하도록 브라우저 지원을 추가한 스펙이다. 현재 브라우저 API가 HTTP/2 엑세스를 지원하지 않기 때문에 gRPC-WEB을 사용하여 브라우저에서 서버로 직접 통신을 할 수는 없다.

즉, js단에서 gRPC-WEB 으로 개발해도 브라우저가  HTTP/2 통신을 지원하지 않기 때문에 proxy가 필요한 것.

https://velog.io/@kyusung/grpc-web-example

 

gRPC-web 삽질기

Javascript 기반으로 브라우저에서 gRPC를 사용하려고 하였지만, 적용하지 못한 내용에 대한 기록입니다.gRPC에 대해서 간략히 설명하고 gRPC 라이브러리를 이용하여 node.js 기반의 Application을 만드는

velog.io

https://medium.com/@denis.zhbankov/grpc-web-via-http2-b05c8c8f9e6

 

gRPC-Web via HTTP2

Lately, my backend colleagues and I decided to give gRPC framework a try instead of Protocol Buffers serialiser over WebSockets transport.

medium.com


사실 이 모든 글이 보고있던 프로젝트의 아래 설정 값 하나로부터 시작되었는데.. 혹시 spring/grpc에 haproxy 설정이 가능한지 궁금하여 이모저모 살펴본 것이다. 그러던 중 위 내용을 확인하였고 아래 값은 그냥 (개발자가 만든) 커스텀 값임을 파악하게 되었다.

grpc.use-haproxy=true

그래도 관련 내용 살펴본게 아까워서 추가적으로 적어본다.

HAProxy?

= software loadbalaner, reverse proxy

https://leffept.tistory.com/309

 

[HAProxy]HAProxy 란?

HAProxy 란? HAProxy는 기존의 하드웨어 스위치를 대체하는 소프트웨어 로드 밸런서로, 네트워크 스위치에서 제공하는 L4, L7 기능 및 로드 밸런서 기능을 제공한다. 설치가 쉽고 빠르기에 서비스 이

leffept.tistory.com

https://prohannah.tistory.com/65

 

로드밸런서 (L4, L7, NginX, HAProxy)

네트워크 로드밸런싱에서 주로 언급되는 로드밸런서 L4, L7, HAProxy 위주로 설명하겠다. L4 (Transport Layer) L4는 IP, Port, Session 기반으로 로드밸런싱하며 웬만한 서비스에서는 이것만으로 부하 분산이

prohannah.tistory.com

 

HAProxy vs nginx?

Nginx는 웹서버로서 load balancing, reverse proxy 기능 또한 제공.
굳이 웹 서버로서의 역할이 필요가 없다면(캐싱) HAProxy의 load balancing이 헬스체크가 가능하기도 하고 좀 더 가벼움

https://seokjun.kim/haproxy-and-nginx-load-balancing/

 

HAProxy 와 Nginx 의 로드밸런싱

NGINX Nginx 는 대표적인 웹서버인 Apache 의 문제점을 해결하면서 만들어진 웹서버로 비동기 방식으로 개발되어 가볍고 빠른 것으로 유명한 오픈소스 어플리케이션이다. Nginx 는 http 나 reverse proxy 같

seokjun.kim


완전 다른 내용/ 참고..

ingress proxy?

일반적인 Ingress는 외부로부터 서버 내부로 유입되는 네트워크 트래픽을, egress는 서버 내부에서 외부로 나가는 트래픽을 의미. 
쿠버네티스에서의 Ingress는 외부에서 실행 중인 Deployment와 Service에 접근하기 위한, 일종의 관문 (Gateway) 같은 역할을 하며 L7에서의 요청을 처리한다.

https://kubernetes.io/ko/docs/concepts/services-networking/ingress/

 

인그레스(Ingress)

FEATURE STATE: Kubernetes v1.19 [stable] 클러스터 내의 서비스에 대한 외부 접근을 관리하는 API 오브젝트이며, 일반적으로 HTTP를 관리함. 인그레스는 부하 분산, SSL 종료, 명칭 기반의 가상 호스팅을 제공

kubernetes.io

https://blog.naver.com/alice_k106/221502890249

 

162. [Kubernetes] 1편 : 쿠버네티스 Ingress 개념 및 사용 방법, 온-프레미스 환경에서 Ingress 구축하기

이번 포스트에서는 쿠버네티스에서 인그레스 (Ingress) 를 사용하는 방법, 그리고 Public 클라우드를 쓰...

blog.naver.com

 

728x90
반응형
반응형
gRPC is a modern open source high performance Remote Procedure Call (RPC) framework that can run in any environment.

 

RPC(Remote Procedure Call)?

  • 별도의 원격 제어를 위한 코딩 없이 다른 주소 공간에서 함수나 프로시저를 실행할 수 있게하는 프로세스 간 통신 기술
  • 개발자가 원격 상호 작용에 대한 세부 정보를 명시적으로 코딩하지 않아도 프레임워크가 자동 핸들링함
  • 클라이언트 코드에서는 직접 서버 코드의 함수를 호출하는 것처럼 보임
  • 언어에 구애받지 않고 원격의 프로시져를 호출가능(즉, 클라이언트 코드 언어와 서버 코드 언어가 다른 언어로 쓰일 수 있음 )

grpc

gRPC?

  • RPC인데 구글이 만든 RPC이다. g가 구글인줄 알았는데 그건 또 아니라고 반박함ㅋㅋㅋ
    https://github.com/grpc/grpc/blob/master/doc/g_stands_for.md
  • IDL: proto 사용
  • http/2 기반 통신
  • json 기반의 통신보다 가볍고 속도가 빠르다.(성능이점)
  • 클라이언트에는 서버와 통신 시 Stub을 inject 하여 통신하며 소스에 바로 로딩하여 사용가능
  • protoc 파일을 작성 시 request이나 response앞에 붙은 'stream' 유무에 따라 4가지 방식이 있음
    • unary(단방향): 클라이언트가 서버에 단일 요청을 보내고 일반 함수 호출처럼 단일 응답을 받음(1개 request , 1개 respone)
      • rpc SayHello(HelloRequest) returns (HelloResponse);
    • server stream(서버 스트리밍): 서버가 클라이언트의 요청에 대한 응답으로 메시지 스트림을 반환(1개 request, n개 response)
      • rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);
    • client stream(클라이언트 스트리밍): 클라이언트가 단일 메시지 대신 서버에 메시지 스트림을 보냄(n개 request, 1개 response)
      • rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);
    • bi-directional(양방향): 서버, 클라이언트 양쪽에서 메시지 스트림을 보냄(n개 request, n개 response)
      • rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);
  • 클라이언트 stub: 서버를 추상화해놓은 것 / 클라이언트의 수신처리 방법
    • BlockingStub: 동기적으로 통신하는 방법으로, 서버로부터 응답이 올 때까지 대기.
      • Unary RPC와 Server Streaming RPC에서만 사용
    • AsyncStub (Stub): 비동기적으로 통신하는 방법으로, 서버로부터 오는 응답을 StreamObserver 객체가 대신 받아서 처리
      • 모든 방식의 RPC에서 사용
    • FutureStub: 비동기적으로 통신하는 방법으로, 서버로부터의 응답 도달에 상관 없이 일단 ListenableFuture로 래핑된 객체를 반환. 서버로부터 오는 응답이 오면 ListenableFuture 객체를 통해 전달받은 메시지를 언래핑할 수 있음.
      • Unary RPC에서만 사용

즉 위 내용을 모두 합치면 아래와 같은 7가지 통신방법이 존재한다.

  unary server stream client stream bi-directional
blocking o o x x
asyn o o o o
future o x x x

 

gRPC 단점

  • 브라우저에서 직접 gRPC 통신 불가, proxy 를 통하거나 브라우저 -> 클라이언트 연동 서버 -> gRPC 서버 순으로 요청해야 함
  • protobuf(이진형식)으로 인코딩되어 송수신에 효율적이나 사람이 읽을 수 없는 데이터라 네트워크 단에서 볼 때 어려움

 

왜 MSA에서 많이 쓰이나 싶었는데, MSA구조의 특정 상 안 그래도 많은 api 콜을 gRPC로 대체하면 성능 향상에 도움이 될 것 같다..

다음 글에서는 간단하게 서버와 클라이언트를 구현해본다.

2022.01.20 - [개발/spring] - [grpc] springboot2 grpc server/client coding

 

[grpc] springboot2 grpc server/client coding

목표: java11 / gradle 7.3.3 multi project / springboot 2.6.2 / grpc server & client 개발 참고 블로그: https://velog.io/@chb1828/Spring-boot%EB%A1%9C-Grpc%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%B4%EB%B3%B..

bangpurin.tistory.com


IDL(Interface Definition Language)?
: 정보를 저장하는 규칙

1. xml
2. json
3. proto

Protocol buffers(proto)?

  • 직렬화 데이터 구조, 데이터를 전송할 때 구조화된 데이터를 전환하는 방법 중 하나
  • XML의 문제점을 개선하기 위해 제안된 IDL이며, XML보다 월등한 성능을 지님
  •  .proto 파일에 protocol buffer 메세지 타입/구조를 정의
  • message = '이름-값'의 쌍을 포함하는 작은 논리적 레코드
  • protoc 컴파일러로 컴파일 하면 데이터에 접근할 수 있는 각 언어에 맞는 형태의 데이터 클래스를 생성해주며 만들어진 클래스는 각 필드를 위한 접근자 뿐 아니라 전체 구조를 바이트로 직렬화하거나 바이트로부터 전체 구조를 파싱하는 메서드들을 제공함

xml 보다..

  • XML보다 작고 빠르고 간단함
  • 파일 크기가 3에서 10배 정도 작음
  • 속도가 20에서 100배 정도 빠름
  • XML보다 가독성이 좋고 명시적

 


참고자료

https://tech.lattechiffon.com/2021/06/30/grpc-%EC%84%B8-%EA%B0%80%EC%A7%80-streaming-rpc-%EA%B5%AC%ED%98%84-java/

 

gRPC 세 가지 Streaming RPC 구현 (Java) – 라떼쉬폰의 코드 베이커리

이전 글에서 gRPC를 이용하여 Unary RPC를 구현했던 것에 이어서, 이번에는 Server Streaming, Client Streaming 및 Bidirectional Streaming RPC를 Java로 구현해보도록 하겠습니다. Streaming 패턴 구현에 앞서 gRPC에서

tech.lattechiffon.com

 

https://qwer9412.tistory.com/40

 

4. grpc의 여러가지 통신 기법

grpc는 4개의 통신을 지원한다. - unary (1개 request , 1개 respone) - server stream (1개 request, n개 response) - client stream (n개 request, 1개 response) - bi stream (n개 request, n개 response) 그리..

qwer9412.tistory.com

 

728x90
반응형

+ Recent posts