0

디자인 문제에 대한 답을 찾고 있는데,이 문제에 대한 모든 문헌에서 답을 찾지 못했습니다. 유스 케이스에 대한 설명과 그에 대한 해결책을 설명하고 주제 전문가로서 의견을 말하도록하십시오.마이크로 서비스간에 데이터 공유

사용 사례 : 우리는 서로 다른 비즈니스 도메인의 일부 형식의 콘텐츠를 반환하는 여러 가지 마이크로 서비스를 제공합니다. 우리는 Spring Cloud Netflix를 사용하고 있으므로 게이트웨이 서비스는 트래픽을 컨텐츠 서비스로 라우팅합니다. 이러한 서비스 중 일부는 전부는 아니지만 요청에서 파생 된 데이터를 필요로하며 변경 불가능합니다. 사소한 예는 로캘이지만 다른 독점 정보도 있습니다.

솔루션 : 현재 게이트웨이 서비스에서 공유 데이터를 가져 와서 고유 키가있는 NoSQL 데이터베이스에서 JSON으로 유지합니다. 그런 다음 요청을 라우팅하기 전에 요청 헤더로 키를 추가합니다. 나는 콘텐츠 서비스가 빌드시에 포함하는 공유 라이브러리를 가지고 있으며, 요청 헤더에서 키를 읽고, 키를 사용하여 저장된 데이터를 가져오고 자체를 초기화하는 Spring bean을 포함한다. 따라서 컨텐츠 서비스가 기본 메커니즘을 몰라도 공유 된 데이터에 액세스 할 수 있습니다 (앞서 언급 한 bean을 간단히 주입하여). 콘텐츠 서비스가 다른 서비스를 호출하는 경우 고유 키를 요청 헤더로 추가해야합니다.

토론 : 내 동료들과 함께했습니다 논쟁은이 목적을 위해 공유 데이터 저장소를 사용할지 여부를 적절한 것입니다. 나는 서비스가 다른 사람에게 도메인 특정 데이터를 유출하는 것은 좋지 않다고 주장하지만 문제의 데이터는 특정 도메인이 아니므로 공유 데이터베이스를 사용하고 키를 전달하는 데는 아무런 문제가 없습니다. 대안은 내가 고려하는 공유 데이터를 모두 전달하는 것입니다.

당신의 생각은 무엇입니까?

편집 : 질문을 끝내기 위해 투표 한 사람이 나타납니다. Microservices 간의 데이터 공유에 대해 언급하는 참고 자료로 안내 할 수 없다면 그러한 정책은 의미있는 토론을 방해합니다. 모든 질문이 부울 예/아니오 응답 인 것은 아니며, 일부는 더 깊은 생각이 필요합니다.

+3

하나의 서비스가 데이터 저장소를 소유하고 관리해야한다고 말합니다. 데이터 저장소 자체는 공유하면 안됩니다. – duffymo

+0

@duffymo 인증의 결과 데이터는 어떻습니까? 당신은 모든 서비스가 동일한 정보를 추출하기 위해 JWT 토큰을 파싱해야한다고 생각합니까 아니면 일단 수행되어야하고 나중에 사용하기 위해 저장되어야합니까? 나는 공유 데이터에 대한 추상화를 만드는 데 아무런 문제가 없다. 내 질문에 Spring 빈이하는 일이다. –

+0

VTC가 StackOverflow에 게시되는 것과 관련이 있다고 생각합니다. [프로그래머 SE] (http : // 프로그래머)를위한 설계 논쟁 [http://meta.stackexchange.com/questions/124867/where-should-i-ask-software-architecture-design-questions] .stackexchange.com /). – Mitch

답변

0

대부분의 경우 복제 비용은 편의상 상쇄되지만 공유 데이터는 다른 서비스가 소유 한 것으로 간주 할 수 있습니다.

"공유"데이터에 대한 기록기가 하나만 있고 클라이언트의 독립적 인 버전을 허용하는 방식으로 액세스하는 경우 공유 데이터를 비 통상적으로 노출 된 서비스로 볼 수 있습니다.

예 :

  • 서비스 A는 표 A1과 같은 SQL 서버에 저장된 엔티티 A1을 소유
  • 서비스 B는 고전에서 A1 실체에서

데이터를 요구 엔티티 B1을 소유 레이아웃에서 서비스 B는 서비스 A에 대한 호출을 통해 A1에 액세스합니다.

Service B --HTTP--> Service A --SQL--> A1 

Alt 예를 들어 서비스 A는 서비스 B가 A1에 직접 액세스 할 수있게하는보기를 만들 수 있습니다.

Service B --SQL--> vwA1_version1 --SQL--> A1 

서비스 A는 필드의 레이아웃을 변경, 서비스 A는 기존 고객과의 역 호환성을 허용하는 vwA1_version1을 업데이트하고 새로운 고객을 vwA1_version2 정의합니다.

첫 번째 대답에 뜨거운 논쟁 후
+0

내 질문과 관련된 답변을 다시 말해주십시오. 공유 데이터 저장소에 대한 막연한 논의는 도움이되지 않습니다. –

+0

@AbhijitSarkar, 특정 질문을하지 않았습니다. 일반적인 질문을하셨습니다. "SOA에서 데이터 저장소를 공유 할 수 있습니까?"라는 질문에 대한 답변이 나옵니다. "JWT 또는 사용자 ID를 전달해야합니까?"라는 특정 답변을 원하면 토큰에 대한 격렬한 지원이 필요합니다. AAA는 일반적으로 대부분의 서비스가 데이터에 관계없이 액세스해야합니다. 서명 검증은 DB 호출보다 훨씬 저렴합니다. – Mitch

2

, 내가 어떤 관점을 빌려 보자

자주 온다 요청이 차례로 호출에있는 다음 첫 번째 서비스에 충돌 한 후 예를 들어 인증 정보를 처리하는 방법입니다

한 사용 사례 기타 서비스. 이제 문제는 대개 다음과 같습니다. 인증 정보 (사용자 이름 및 그룹 등)를 넘겨 주거나 클라이언트가 보낸 토큰을 넘겨주고 다음 서비스가 인증 정보를 다시 쿼리하게합니다.

내가 알 수있는 한, 마이크로 서비스 커뮤니티는 아직이 문제를 해결하는 "관용적 인"방법에 동의하지 않았습니다. 나는 그것에 대한 좋은 이유가 있다고 생각하며, 다양한 주제가이 주제에서 제기되는 다양한 요구 사항을 고려합니다. 때로는 인증은 외부 요청에 부딪히는 첫 번째 서비스에서만 필요할 수 있습니다. 그런 다음 인증에 너무 많은 작업을 투입하지 않아도됩니다. 아직도 내가 아는 대부분의 시스템은 더 높은 요구를 가지므로 인증 주제에 대해 다른 수준의 정교함이 필요합니다.

이 문제를 어떻게 해결할 수 있는지에 대해 알려 드리겠습니다. 가장 쉬운 방법은 클라이언트가 백엔드 서비스간에 보낸 액세스 토큰을 처리하는 것입니다. 예 -이 방법을 사용하면 모든 서비스가 요청에 부딪 힐 때마다 사용자 정보를 다시 요청해야합니다. 이 시스템에서이 양은 발생하지 않습니다. 요청 당 25 개의 교차 서비스가 있습니다. 이는 일종의 인증 서비스에서 25 번의 공격을 의미합니다. 대부분의 사람들은 이제이 끔찍한 복제에 대한 두려움에 시달리기 시작할 것입니다. 그러나 다른 방식으로 생각해 봅시다 : 동일한 시스템이 잘 구조화 된 단일체라면 여전히 다른 장소에서 이러한 호출을합니다 (아마 DB를 매번 때릴 것입니다). 당신의 과정. 마이크로 서비스 아키텍처에서 이러한 호출에 대한 큰 문제는 네트워크 오버 헤드이며, 사실입니다. 잘못하면 죽일 것입니다! 나는 우리에게 가져다 준 솔루션을 우리에게 줄 것이고, 그것은 우리에게 많은 부담을 안겨줄 것입니다 :

우리는 토큰 서비스를 개발했습니다 (곧 공개 될 예정입니다). 이 서비스는 토큰의 조합, 만료 날짜 및 일부 스키마가없는 JSON 컨텐트를 저장하는 것을 제외하고는 다른 작업을 수행하지 않습니다. 토큰과 그 내용을 작성, 무효화, 확장 및 읽을 수있는 매우 간단한 REST 인터페이스가 있습니다. 이 서비스에는 실행되는 환경에 따라 구성 할 수있는 여러 백엔드가 있습니다. 개발 목적으로 어떤 방식 으로든 동기화, 지속 또는 복제되지 않는 간단한 메모리 내 저장소가 있습니다. 프로덕션 환경에서 우리는 이러한 토큰을 여러 인스턴스 (쿼럼, 비동기 지속성 등 모든 항목 포함)간에 동기화하는 백엔드를 작성했습니다. 이 백 엔드는이 서비스를 매우 잘 확장 할 수있게 해줍니다. 이는 내가 제안하고있는 솔루션의 전제입니다. 모든 서비스 노드가 요청을받을 때마다 토큰과 관련된 정보를 얻어야하는 경우 - 서비스를 제공하는 서비스가 정말 빨라야합니다! 우리의 구현은 토큰과 그 정보를 5 밀리 초보다 빨리 되돌려 주며, 우리는이 측정 기준을 훨씬 더 낮출 수 있다고 확신합니다.

우리가 가지고있는 또 다른 전략은 토큰 서비스에 더 많은 쿼리를하는 서비스를 조율하는 것입니다 (토큰의 유효성/존재를 확인하는 것보다 콘텐츠를받는 것이 비용이 많이 듭니다). 따라서 동일한 물리적 노드에 있거나 네트워크 대기 시간을 최소화합니다.

보다 일반적인 메시지는 무엇입니까? 번호 또는 이러한 전화가 처리되는 콘텐츠의 양과 분리되어있는 한 서비스 간 통화가 두려워하지 마십시오 (불량 사례 here).더 자주 호출되는 서비스는 훨씬 더 신중하게 설계해야하며 성능은 마지막으로 가능한 밀리 초가되도록 최적화해야합니다. 예를 들어, 이런 종류의 시스템에 중요한 서비스의 DB 히트는 절대적인 Nogo입니다.하지만이를 피할 수있는 디자인 패턴과 아키텍처가 있습니다!

토론에 대한 질문에 직접 답변하지 않은 것을 이미 감지했을 수 있습니다. 왜? 나는 서비스간에 데이터베이스를 공유하는 것에 대해 열렬히 반대하고 있습니다. 이러한 데이터베이스가 스키마가없는 경우에도이 종속성을 볼 수 없으면 두 개의 서비스를 함께 연결합니다. 토큰 서비스에서 데이터를 재구성하기로 결정하고이 데이터베이스를 읽는 것만으로도 다른 서비스가 있습니다. 두 서비스를 망쳤으므로 종속성이 투명하지 않기 때문에 너무 늦었을 때 실현할 수 있습니다. 서비스의 상태/데이터는 잘 정의 된 인터페이스를 통해서만 액세스해야하며 따라서 잘 추상화되고 개발되고 독립적으로 테스트 될 수 있습니다. 필자가 생각하기에, 하나의 서비스에서 퍼시스턴스 기술이나 구조를 변경하면 다른 서비스에 변경이 가해지지 않아야합니다. API를 통해 독점적으로 서비스에 액세스하면 리팩토링, 리빌드 또는 심지어 완전히 재 작성하는 서비스를 제공 할 수 있습니다. 디커플링이라고 불립니다!

이것이 도움이되는지 아닌지 알려주세요.

+0

당신은 제가 주로 동의하는 좋은 점들을 만듭니다. 그 트릭은 고양이에게 벨을 울리는 법입니다. 잘 정의 된 인터페이스를 가진 서비스를 가질 수 있지만 호출하려면 입력 매개 변수가 필요합니다. 제 질문에 잘 정의 된 인터페이스는 공유 DB에서 데이터를 가져 오는 Spring 빈 (모든 인터페이스는 HTTP 여야 함)입니다. 이렇게하려면 키가 필요하며 키는 요청 헤더를 사용하여 서비스에서 서비스로 전달됩니다. –

관련 문제