- [C813] 마이크로 서비스를 구성할 때, 데이터베이스를 꼭 분리해야 하나요? 데이터가 한 곳에 모여있지 않고 중복되어도 괜찮은가요? 모범 사례를 알아보고, 이유를 함께 적어주세요.
마이크로 서비스는 데이터베이스는 분리해야 독립적으로 배포하거나 확장할 수 있으며 Monolithic 데이터베이스를 사용하는 설계는 서비스 변경 사항을 독립적으로 배포할 수 없도록 상호 간의 밀접한 결합 방식을 통해 무능력하게 만든다. 동일한 데이터베이스에 액세스 하는 여러 서비스가 있는 경우 어디서 어떤 데이터를 사용하는지 알 수 없기에 모든 서비스 간에 스키마 변경 사항을 조정해야 합니다. 변경 사항을 적용할 때 추가 작업에 대한 지연이 발생할 가능성이 큽니다.
단일 데이터베이스를 수평 확장할 수 있는 옵션만 있기에 애플리케이션 단에서 개별 서비스를 확장하는 것이 어렵습니다.
애플리케이션 성능을 향상하고자 할 때, 단일 데이터 베이스를 사용하면 여러 개의 큰 테이블을 조인하여 필요한 데이터를 가져와야 하기에 데이터 검색이 어려워집니다.
그리고 가장 큰 문제는 모든 어플리케이션에서 관계형 데이터베이스만 사용하도록 제한하게 됩니다. No-SQL 데이터베이스가 특정 서비스에 더 적합할 수 있어도 제한으로 인해 사용할 수 없게 됩니다.

각 시스템들은 모든 데이터들을 보관하면 안되고, 본인에게 꼭 필요한 최소 데이터만 보관한다. 물리적인 의존관계는 없지만, 데이터를 가지고있으면서 논리적인 의존관계가 생겨 가게 업주에서 무언가 데이터를 바꾸려 할 때, 데이터를 다 봐야 하는 상황이 생겼다.
그래서 최소한만 가지고있자 결정을 함.
2015년도 배달의 민족에서 루비라는 상상을 초월하는 사양의 단일 데이터베이스를 사용했는데 리뷰 테이블에 뭔가 문제가 있어서 데이터베이스 리소스 전체에 자꾸 영향을 주었고 리뷰에 관련한 DB 테이블들이 밀리면서 결국 루비 DB(MS SQL) 자체가 밀리기 시작했고 전체 서비스 시스템이 다 밀리면서 시스템 전체에 오류가 났다.
https://www.youtube.com/watch?v=BnS6343GTkY
- [C814] 여러 도메인을 가지고 있는 서비스에서, 하나의 서비스에서는 성공했지만 연관된 다른 서비스에서 실패하는 “부분 실패”의 경우 어떻게 처리해야 하나요? 음식 주문에서 결제에는 성공했지만, 주문에는 실패하는 경우를 예를 들어 설명하세요.
마이크로 서비스 기반 애플리케이션과 같은 분산 시스템에서는 부분적으로 실패할 위험이 있다. 예를 들어, 단일 마이크로 서비스/컨테이너가 실패하거나 짧은 시간 동안 응답하지 못할 수 있으며 단일 VM 또는 서버가 충돌될 수 있으며 클라이언트와 서비스는 별도의 프로세스이기 때문에 서비스가 클라이언트의 요청에 적시에 응답하지 못할 수 있습니다. 서비스가 오버로드되고 요청에 매우 느리게 응답하거나, 네트워크 문제로 인해 짧은 시간 동안 액세스하지 못할 수도 있습니다.
결제를 성공하여 주문에 요청을 보내는데 주문에 오류가 나 응답을 보내지 못하면 응답 대기를 하게 된다.
해결법
내부 마이크로 서비스 전체에 걸친 비동기 통신(메시지 기반 통신) 사용
잘못된 디자인은 결국 잘못된 중단의 결정적 원인이 되기 때문에 내부 마이크로 서비스 전역에 걸쳐 동기 HTTP 호출의 긴 체인을 만들지 않는 것이 바람직합니다. 반대로, 클라이언트 애플리케이션과 첫 번째 수준의 마이크로 서비스 또는 세분화된 API 게이트웨이 간의 프런트 엔드 통신을 제외하고 내부 마이크로 서비스 전역에 걸쳐 초기 요청/응답 주기를 넘어서 비동기(메시지 기반) 통신만 한 번 사용하는 것이 좋습니다. 결과적 일관성 및 이벤트 기반 아키텍처는 파급 효과를 최소화하는 데 도움이 됩니다. 이런 접근법은 높은 수준의 마이크로 서비스 자율성을 시행하고 따라서 여기서 지적된 문제를 예방할 수 있습니다.
네트워크 시간제한의 해결 방법
일반적으로 클라이언트는 응답을 기다릴 때 항상 시간제한을 사용하되 무기한 차단하지 않도록 설계되어야 합니다. 시간제한의 사용은 리소스가 절대 무기한으로 묶여 있지 않게 합니다.
회로 차단기 패턴 사용
이 방법에서 클라이언트 프로세스는 실패한 요청 횟수를 추적합니다. 오류율이 설정된 제한을 초과하는 경우 “회로 차단기”가 작동해 추가적인 시도는 즉시 실패합니다. (많은 요청이 실패하는 경우 서비스가 사용할 수 없게 되고 요청 전송이 무의미하다는 것을 의미합니다.) 제한 시간 경과 후 해당 클라이언트는 다시 시도해야 하며 새 요청이 성공하는 경우 회로 차단기를 닫습니다.
큐에 대기 중인 요청 수 제한
클라이언트는 클라이언트 마이크로 서비스가 특정 서비스에 보낼 수 있는 대기 중인 요청 수에 대한 상한값을 입력해야 합니다. 제한치에 도달한 경우 추가 요청을 하는 것은 무의미하며 이런 시도는 즉각 실패합니다. 구현 관점에서 Polly Bulkhead 격리 정책은 이 요구 사항을 충족하는 데 사용할 수 있습니다. 이 방법은 기본적으로 SemaphoreSlim을 구현으로 사용하는 병렬화 제한입니다. 또한 Bulkhead 외부에 "큐"를 허용합니다. 실행 전에도 과부하를 미리 줄일 수 있습니다(예를 들어, 용량이 가득 찼다고 여겨지기 때문에). 이렇게 하면 특정 오류 시나리오에 대한 응답이 회로 차단기보다 더 빠르게 됩니다. 회로 차단기는 오류를 대기하기 때문입니다. Polly의 BulkheadPolicy 개체는 Bulkhead와 큐가 얼마나 차 있는지 드러내며 오버플로에 대한 이벤트를 제공하므로 자동화된 수평 확장에 사용될 수 있습니다.