API 게이트웨이 (REST) ​​+ 이벤트 중심 마이크로 서비스


16

API 게이트웨이 패턴에 따라 REST API를 통해 기능을 제공하는 마이크로 서비스가 많이 있습니다. 이 마이크로 서비스는 Spring Boot 애플리케이션이므로 Spring AMQP를 사용하여 이러한 마이크로 서비스 간의 RPC 스타일 동기 통신을 달성하고 있습니다. 지금까지 상황이 순조롭게 진행되었습니다. 그러나 이벤트 중심의 마이크로 서비스 아키텍처에 대해 읽고 Spring Cloud Stream과 같은 프로젝트를 볼수록 RPC, 동기식 접근 방식으로 잘못된 방식으로 작업을 수행 할 수 있다고 확신합니다 (특히 확장하려면이 작업이 필요하기 때문에) 클라이언트 응용 프로그램의 초당 수백 또는 수천 개의 요청에 응답하기 위해).

이벤트 중심 아키텍처의 요점을 이해합니다. 내가 이해하지 못하는 것은 모든 요청에 ​​대한 응답을 기대하는 모델 (REST) ​​뒤에 앉아있을 때 실제로 그러한 패턴을 사용하는 방법입니다. 예를 들어 API 게이트웨이를 마이크로 서비스로 사용하고 사용자를 저장하고 관리하는 다른 마이크로 서비스를 사용 GET /users/1하는 경우 순수하게 이벤트 중심 방식 으로 모델링하는 방법은 무엇입니까?

답변:


9

나를 따라 반복

REST 및 비동기 이벤트는 대안이 아닙니다. 그들은 완전히 직교합니다.

둘 중 하나를 가질 수 있습니다. 그것들은 완전히 다른 문제 영역을위한 완전히 다른 도구입니다. 실제로, 범용 요청-응답 통신은 절대적으로 비동기식, 이벤트 중심 및 내결함성이 있습니다.


간단한 예로, AMQP 프로토콜은 TCP 연결을 통해 메시지를 보냅니다. TCP에서 모든 패킷은 수신자가 확인해야합니다 . 패킷을 보낸 사람이 해당 패킷에 대한 ACK를받지 못하면 해당 패킷이 ACK 될 때까지 또는 응용 프로그램 계층이 "제공"하여 연결을 포기할 때까지 해당 패킷을 다시 보냅니다. 모든 "패킷 전송 요청"때문에 명확하게 비 내결함성 요청 - 응답 모델이다 있어야 실패 전체 연결의 응답 결과에 첨부 된 "패킷 수신 확인 응답", 실패가있다. 그러나 비동기식 내결함성 메시징을 위해 표준화되고 널리 채택 된 프로토콜 인 AMQP는 TCP를 통해 통신됩니다! 무엇을 제공합니까?

여기서 핵심 개념은 확장 가능한 느슨하게 결합 된 내결함성 메시징이 메시지 전송 방식이 아니라 전송하는 메시지에 의해 정의된다는 입니다. 다시 말해, 느슨한 결합은 응용 계층에서 정의됩니다 .

RESTful HTTP와 직접 또는 AMQP 메시지 브로커와 간접적으로 통신하는 두 당사자를 살펴 보자. 당사자 A가 이미지를 선명하게하거나 압축하거나 향상시키는 JPEG 이미지를 당사자 B에 업로드한다고 가정합니다. 당사자 A는 처리 된 이미지를 즉시 필요로하지 않지만 나중에 사용하고 검색하기 위해 이미지를 참조해야합니다. REST에 들어갈 수있는 한 가지 방법은 다음과 같습니다.

  • 당사자 A는 다음과 같이 HTTP POST요청 메시지를 당사자 B 에게 보냅니다.Content-Type: image/jpeg
  • 파티 A가 대기하는 동안 파티 B는 이미지를 처리하고 (큰 경우 오랫동안) 다른 작업을 수행 할 수 있습니다.
  • 당사자 B는 처리 된 이미지에 링크 201 Created되는 Content-Location: <url>헤더 와 함께 HTTP 응답 메시지를 당사자 A 에게 보냅니다.
  • 파티 A는 이제 처리 된 이미지에 대한 참조가 있으므로 작업이 완료된 것으로 간주합니다.
  • 나중에 당사자 A가 처리 된 이미지를 필요로하는 경우 이전 Content-Location헤더 의 링크를 사용하여 이미지를 가져옵니다.

201 Created응답 코드는 자신의 요청이 성공적으로뿐만 아니라 클라이언트를 알려줍니다, 그것은 또한 새로운 자원을 만들었습니다. 201 응답에서 Content-Location헤더는 작성된 자원에 대한 링크입니다. 이것은 RFC 7231 섹션 6.3.2 및 3.1.4.2에 지정되어 있습니다.

이제이 상호 작용이 AMQP의 가상 RPC 프로토콜을 통해 어떻게 작동하는지 살펴 보겠습니다.

  • 당사자 A는 이미지를 포함하는 AMQP 메시지 브로커 (메신저라고 함)를 전송하고 처리를 위해 이미지를 당사자 B로 라우팅하기위한 지시 사항을 보낸 다음 이미지에 대한 일종의 주소로 당사자 A에 응답합니다.
  • 파티 A가 기다렸다가 다른 작업을 수행 할 수 있음
  • 메신저는 당사자 A의 원본 메시지를 당사자 B에게 보냅니다.
  • 당사자 B가 메시지를 처리
  • B 당사자는 처리 된 이미지의 주소와 해당 메시지를 A 당사자에게 라우팅하기위한 지시 사항이 포함 된 메시지를 Messenger에 보냅니다.
  • 메신저는 처리 된 이미지 주소를 포함하는 당사자 B로부터 메시지를 당사자 A에게 보냅니다.
  • 파티 A는 이제 처리 된 이미지에 대한 참조가 있으므로 작업이 완료된 것으로 간주합니다.
  • 나중에 A 당사자가 이미지를 필요로하는 경우 주소를 사용하여 이미지를 검색합니다 (아마 다른 상대방에게 메시지를 보내서).

여기서 문제가 보입니까? 두 경우 모두, 갑이 될 때까지 이미지 주소를 얻을 수없는 파티 B가 이미지를 처리합니다 . 그러나 파티 A는 이미지를 즉시 필요로하지 않으며, 모든 권리에 의해 처리가 아직 완료되면 더 이상 신경 쓰지 않아도됩니다!

AMQP 사례에서 B가 A에게 B 가 처리를 위해 이미지를 수락 했다고 알리고 A가 처리가 완료된 후 이미지의 위치를 ​​지정하도록함으로써이를 쉽게 해결할 수 있습니다 . 그러면 파티 B는 나중에 이미지 처리가 완료되었음을 알리는 메시지를 A에게 보낼 수 있습니다. 구조에 AMQP 메시지!

추측하지 말고 REST로 동일한 것을 달성 할 수 있습니다 . AMQP 예에서 "처리 된 이미지가 있습니다"메시지를 "이미지가 처리 중입니다. 나중에 가져올 수 있습니다"메시지로 변경했습니다. RESTful HTTP에서이를 수행하기 위해 202 Accepted코드를 Content-Location다시 사용 합니다.

  • 당사자 A는 다음과 같이 HTTP POST메시지를 당사자 B 에게 보냅니다.Content-Type: image/jpeg
  • 당사자 B는 202 Accepted처리가 완료되었는지 여부와 처리가 완료되면 이미지를 사용할 수있는 위치를 설명하는 일종의 "비동기 조작"컨텐츠를 포함 하는 응답을 즉시 보냅니다 . 응답에는 응답 본문이 무엇이든 나타내는 리소스에 대한 링크 인 Content-Location: <link>헤더 도 포함 202 Accepted됩니다. 이 경우 이는 비동기 작업에 대한 링크임을 의미합니다!
  • 파티 A는 이제 처리 된 이미지에 대한 참조가 있으므로 작업이 완료된 것으로 간주합니다.
  • 나중에 당사자 A가 처리 된 이미지를 필요로하는 경우, 먼저 처리가 완료되었는지 판별하기 위해 헤더에 링크 된 비동기 조작 자원 을 가져옵니다 Content-Location. 그렇다면 파티 A는 비동기 작업 자체의 링크를 사용하여 처리 된 이미지를 가져옵니다.

여기서 유일한 차이점은 AMQP 모델에서 파티 B가 이미지 처리가 완료되면 파티 A에 알린다는 것입니다. 그러나 REST 모델에서 당사자 A는 실제로 이미지가 필요하기 직전에 처리가 수행되는지 확인합니다. 이러한 접근 방식은 동일하게 확장 가능 합니다. 시스템이 커짐에 따라 비동기 AMQP와 비동기 REST 전략 모두에서 전송되는 메시지 수가 동일한 점근 적 복잡성으로 증가합니다. 유일한 차이점은 클라이언트가 서버 대신 추가 메시지를 보내는 것입니다.

그러나 REST 접근 방식에는 동적 검색 및 프로토콜 협상과 같은 몇 가지 트릭이 있습니다. 동기화 및 비동기 REST 상호 작용이 어떻게 시작되었는지 고려하십시오. 당사자 A는 당사자 B가 응답 한 특정 종류의 성공 메시지 만 다른 점을 제외하고는 동일한 요청 을 당사자 B 에게 보냈습니다 . 당사자 A가 이미지 처리가 동기식인지 비동기식인지 선택 하려면 어떻게해야 합니까? 당사자 B가 당사자 B가 비동기 처리를 할 수 있는지 여부를 모르는 경우 어떻게합니까?

글쎄, HTTP에는 실제로 이미 표준화 된 프로토콜이 있습니다! HTTP 기본 설정, 특히 respond-asyncRFC 7240 섹션 4.1 의 기본 설정이라고 합니다. 당사자 A가 비동기 응답을 원하는 경우 Prefer: respond-async초기 POST 요청이 있는 헤더를 포함합니다 . 당사자 B가이 요청을 준수하기로 결정하면이 요청 202 Accepted을 포함하는 응답을 다시 보냅니다 Preference-Applied: respond-async. 그렇지 않으면, 파티 B는 단순히 Prefer헤더 를 무시하고 201 Created평상시처럼 다시 보냅니다 .

이를 통해 당사자 A 는 서버와 협상 하여 대화중인 이미지 처리 구현에 동적으로 적응할 수 있습니다. 또한, 명시 적 링크를 사용한다는 것은 A 당사자가 B 이외의 다른 당사자에 대해 알 필요가 없음을 의미합니다. AMQP 메시지 브로커 없음, 이미지 주소를 실제로 이미지 데이터로 변환하는 방법을 알고있는 신비한 C 당사자 없음, 두 번째 B- 비동기 없음 동기식 요청과 비동기식 요청을 모두 수행해야하는 경우 등을 말합니다. 필요한 것, 원하는 것을 선택하고 상태 코드, 응답 내용 및 링크에 반응합니다. 추가Cache-Control헤더는 데이터의 로컬 사본을 보관할시기에 대한 명시적인 지침을 제공하며, 이제 서버는 클라이언트가 로컬 (또는 오프라인) 사본을 유지할 수있는 자원과 클라이언트와 협상 할 수 있습니다. 이것이 REST에서 느슨하게 결합 된 결함 허용 마이크로 서비스를 빌드하는 방법입니다.


1

순전히 이벤트 중심이어야하는지 여부는 특정 시나리오에 따라 다릅니다. 당신이 정말로 필요하다고 가정하면, 다음을 통해 문제를 해결할 수 있습니다.

다른 이벤트를 수신하고 페이로드에서 정보를 캡처하여 로컬의 읽기 전용 데이터 사본 저장 이렇게하면 해당 응용 프로그램에 적합한 형식으로 저장된 해당 데이터에 대한 빠른 읽기가 가능하지만 데이터가 서비스 전체에서 일관되게 유지됩니다.

GET /users/1이 접근 방식으로 모델링 하기 위해 UserCreatedand UserUpdated이벤트를 수신 하고 서비스에 사용자 데이터의 유용한 서브 세트를 저장할 수 있습니다. 그런 다음 해당 사용자 정보를 가져와야 할 경우 간단히 로컬 데이터 저장소를 쿼리 할 수 ​​있습니다.

잠시 동안 /users/끝점 을 노출하는 서비스가 어떤 종류의 이벤트도 게시하지 않는다고 가정 합니다. 이 경우, HTTP 요청에 대한 응답을 간단히 캐싱하여 유사한 작업을 수행 할 수 있으므로 일정 시간 내에 사용자 당 둘 이상의 HTTP 요청을 할 필요가 없습니다.


이해 했어요. 그러나이 시나리오에서 클라이언트에 대한 오류 처리 (및보고)는 어떻습니까?
Tony E. Stark

즉, UserCreated이벤트를 처리 할 때 발생하는 REST 클라이언트 오류 (예 : 중복 된 사용자 이름 또는 이메일 또는 데이터베이스 중단)를 어떻게 다시보고해야합니까?
Tony E. Stark

작업을 수행하는 위치에 따라 다릅니다. 사용자 시스템 내부에있는 경우 모든 유효성 검사를 수행하고 데이터 저장소에 쓴 다음 이벤트를 게시 할 수 있습니다. 그렇지 않으면, 나는 완벽에 표준 HTTP 요청을 수행 할 수 허용으로 볼 /users/새로운 개체로 요청이 성공했을 경우는 이벤트를 게시하기 위해 해당 시스템을 엔드 포인트를 허용, 및 응답
앤디 헌트

0

이벤트 소스 시스템에서는 일반적으로 상태를 나타내는 무언가, 데이터베이스 또는 일부 데이터의 집계 된 뷰가 변경 될 때 비동기 측면이 작동합니다. 예제를 사용하여 GET / api / users를 호출하면 시스템의 사용자 목록을 최신으로 나타내는 서비스의 응답을 간단히 반환 할 수 있습니다. 다른 시나리오에서, GET / api / users에 대한 요청으로 인해 사용자의 마지막 스냅 샷 이후에 서비스가 이벤트 스트림을 사용하여 다른 스냅 샷을 작성하고 결과를 리턴 할 수 있습니다. 이벤트 중심 시스템은 요청에서 응답으로 완전히 비동기식 일 필요는 없지만 서비스가 다른 서비스와 상호 작용해야하는 수준에있는 경향이 있습니다. 비동기식으로 GET 요청을 반환하는 것이 타당하지 않으므로 단순히 서비스의 응답을 반환 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.