게이트웨이를 사용하여 여러 개별 요청을 단일 요청으로 집계합니다. 이 패턴은 클라이언트가 작업을 수행하기 위해 다른 백 엔드 시스템을 여러 차례 호출해야 하는 경우에 유용합니다.
컨텍스트 및 문제점
단일 작업을 수행하기 위해 클라이언트가 다양한 백 엔드 서비스를 여러 번 호출해야 할 수 있습니다. 여러 서비스를 사용하여 작업을 수행하는 애플리케이션은 각 요청마다 리소스를 확장해야 합니다. 새 기능 또는 서비스가 애플리케이션에 추가되면 추가 요청이 필요하며 리소스 요구 사항 및 네트워크 호출이 더욱 증가합니다. 클라이언트와 백 엔드 간의 이러한 대화는 애플리케이션의 성능과 규모에 부정적인 영향을 줄 수 있습니다. 여러 소규모 서비스로 빌드된 애플리케이션은 자연히 서비스 간 호출이 많으므로 마이크로 서비스 아키텍처에서는 이 문제가 보다 일반적입니다.
다음 다이어그램에서 클라이언트는 각 서비스(1,2,3)에 요청을 보냅니다. 각 서비스는 요청을 처리하고 응답을 애플리케이션으로 다시 보냅니다(4,5,6). 일반적으로 대기 시간이 긴 셀룰러 네트워크를 통해 이러한 방식으로 개별 요청을 사용하는 것은 비효율적이며 연결이 끊어지거나 요청이 불완전할 수 있습니다. 각 요청은 병렬로 수행될 수 있지만 애플리케이션은 각 요청에 대한 데이터를 보내고, 대기하고, 처리해야 하며, 모두 별도의 연결에서 실패할 가능성이 높아져야 합니다.
솔루션
게이트웨이를 사용하여 클라이언트와 서비스 간의 대화 시간을 줄입니다. 게이트웨이는 클라이언트 요청을 수신하고, 다양한 백 엔드 시스템에 요청을 디스패치한 다음, 결과를 집계하고 요청 클라이언트로 다시 보냅니다.
이 패턴은 애플리케이션이 백 엔드 서비스를 만드는 요청 수를 줄이고 대기 시간이 긴 네트워크를 통해 애플리케이션 성능을 향상시킬 수 있습니다.
다음 다이어그램에서는 애플리케이션이 게이트웨이에 요청을 보냅니다(1). 요청에는 추가 요청 패키지가 포함되어 있습니다. 게이트웨이는 이를 분해하여 각 요청을 관련 서비스로 전송 처리합니다(2). 각 서비스는 게이트웨이에 응답을 반환합니다(3). 게이트웨이는 각 서비스의 응답을 결합하고 애플리케이션에 응답을 보냅니다(4). 애플리케이션은 단일 요청을 수행하고 게이트웨이에서 단일 응답만 수신합니다.
문제 및 고려 사항
- 게이트웨이는 백 엔드 서비스 간에 서비스 결합을 도입해서는 안 됩니다.
- 대기 시간을 최대한 줄이려면 게이트웨이가 백 엔드 서비스 근처에 있어야 합니다.
- 게이트웨이 서비스는 단일 실패 지점을 도입할 수 있습니다. 게이트웨이가 애플리케이션의 가용성 요구 사항을 충족하도록 올바르게 설계되었는지 확인합니다.
- 게이트웨이에서 병목 현상이 발생할 수 있습니다. 게이트웨이가 부하를 처리하기에 적절한 성능을 갖추었으며 예상된 증가에 맞게 크기를 조정할 수 있는지 확인합니다.
- 게이트웨이 부하 테스트를 수행하여 서비스가 연속으로 실패하지 않도록 합니다.
- 격벽, 회로 분리, 재시도 및 시간 제한과 같은 기술을 사용하여 복원력 있는 디자인을 구현합니다.
- 하나 이상의 서비스 호출이 너무 오래 걸리는 경우 시간 초과를 허용하고 일부 데이터 집합을 반환하는 것이 허용될 수 있습니다. 애플리케이션에서 이 시나리오를 처리하는 방법을 고려합니다.
- 비동기 I/O를 사용하여 백 엔드의 지연이 애플리케이션에서 성능 문제를 야기하지 않도록 합니다.
- 상관 관계 ID를 사용한 자동 분산 추적을 구현하여 각 개별 호출을 추적합니다.
- 요청 메트릭 및 응답 크기를 모니터링합니다.
- 캐시된 데이터를 장애 조치(failover) 전략으로 반환하여 오류를 처리하는 것이 좋습니다.
- 게이트웨이에 집계를 빌드하는 대신 게이트웨이 뒤에 집계 서비스를 배치하는 것이 좋습니다. 요청 집계는 게이트웨이의 다른 서비스와 리소스 요구 사항이 다를 수 있으며 게이트웨이의 라우팅 및 오프로드 기능에 영향을 줄 수 있습니다.
이 패턴을 사용해야 하는 경우
다음 경우에 이 패턴을 사용합니다.
- 클라이언트는 작업을 수행하기 위해 여러 백 엔드 서비스와 통신해야 합니다.
- 클라이언트는 셀룰러 네트워크와 같이 대기 시간이 긴 네트워크를 사용할 수 있습니다.
이 패턴은 다음과 같은 경우에 적합하지 않을 수 있습니다.
- 여러 작업에서 클라이언트와 단일 서비스 간의 호출 수를 줄이려고 합니다. 이 시나리오에서는 서비스에 일괄 처리 작업을 추가하는 것이 나을 수 있습니다.
- 클라이언트 또는 애플리케이션은 백 엔드 서비스 근처에 있으며 대기 시간은 중요한 요소가 아닙니다.
워크로드 디자인
설계자는 게이트웨이 집계 패턴을 워크로드 디자인에 사용하여 Azure Well-Architected Framework 핵심 요소에서 다루는 목표와 원칙을 해결하는 방법을 평가해야 합니다. 예시:
핵심 요소 | 이 패턴으로 핵심 목표를 지원하는 방법 |
---|---|
안정성 디자인 결정은 워크로드가 오작동에 대한 복원력을 갖도록 하고 오류가 발생한 후 완전히 작동하는 상태로 복구 되도록 하는 데 도움이 됩니다. | 이 토폴로지에서는 무엇보다도 일시적인 오류 처리를 클라이언트의 분산 구현에서 중앙 집중식 구현으로 전환할 수 있습니다. - RE:07 일시적인 오류 |
보안 디자인 결정은 워크로드의 데이터 및 시스템의 기밀성, 무결성 및 가용성을 보장하는 데 도움이 됩니다. | 이 토폴로지는 종종 클라이언트가 시스템에 있는 터치 포인트 수를 줄여 공용 노출 영역 및 인증 지점을 줄입니다. 집계된 백 엔드는 클라이언트에서 완전히 네트워크 격리된 상태를 유지할 수 있습니다. - SE:04 구분 - SE:08 강화 |
운영 우수성은 표준화된 프로세스와 팀 응집력을 통해 워크로드 품질을 제공하는 데 도움이 됩니다. | 이 패턴을 사용하면 백 엔드 논리가 클라이언트와 독립적으로 발전할 수 있으므로 클라이언트 터치포인트를 변경하지 않고도 연결된 서비스 구현 또는 데이터 원본을 변경할 수 있습니다. - OE:04 도구 및 프로세스 |
성능 효율성은 크기 조정, 데이터, 코드의 최적화를 통해 워크로드가 수요를 효율적으로 충족하는 데 도움이 됩니다. | 이 디자인은 클라이언트가 여러 연결을 설정하는 디자인보다 대기 시간이 적을 수 있습니다. 집계 구현의 캐싱은 백 엔드 시스템에 대한 호출을 최소화합니다. - PE:03 서비스 선택 - PE:08 데이터 성능 |
디자인 결정과 마찬가지로 이 패턴을 통해 도입 가능한 다른 핵심 요소의 목표에 관한 절충을 고려합니다.
예시
다음 예제에서는 Lua를 사용하여 간단한 게이트웨이 집계 NGINX 서비스를 만드는 방법을 보여 줍니다.
worker_processes 4;
events {
worker_connections 1024;
}
http {
server {
listen 80;
location = /batch {
content_by_lua '
ngx.req.read_body()
-- read json body content
local cjson = require "cjson"
local batch = cjson.decode(ngx.req.get_body_data())["batch"]
-- create capture_multi table
local requests = {}
for i, item in ipairs(batch) do
table.insert(requests, {item.relative_url, { method = ngx.HTTP_GET}})
end
-- execute batch requests in parallel
local results = {}
local resps = { ngx.location.capture_multi(requests) }
for i, res in ipairs(resps) do
table.insert(results, {status = res.status, body = cjson.decode(res.body), header = res.header})
end
ngx.say(cjson.encode({results = results}))
';
}
location = /service1 {
default_type application/json;
echo '{"attr1":"val1"}';
}
location = /service2 {
default_type application/json;
echo '{"attr2":"val2"}';
}
}
}