일반적인 사용 시나리오
애플리케이션 확장성
서버리스 및 이벤트 기반 애플리케이션의 연결 처리
API 및 AWS Lambda에서 지원하는 웹 서비스와 같은 서버리스 및 이벤트 기반 애플리케이션은 종종 수명이 짧은 많은 클라이언트 요청을 지원해야 합니다. 이 사용 패턴으로 인해 애플리케이션 측에서 연결 풀링을 구현할 가능성 없이 데이터베이스 측에서 연결 이탈이 발생할 수 있습니다. 동시 연결 수만으로 인해 데이터베이스 성능이 저하되거나 데이터베이스가 연결 제한을 초과하여 클라이언트 측 오류가 발생할 수 있습니다.
이러한 시나리오에서 RDS Proxy는 다음과 같은 이점을 제공할 수 있습니다.
-
데이터베이스에서 프록시로의 연결 설정 비용을 절감하고 연결 풀링 및 멀티플렉싱을 제공하여 많은 수의 클라이언트 연결을 훨씬 적은 수의 백엔드 데이터베이스 연결로 변환합니다. 이렇게 하면 연결 오버헤드와 데이터베이스 경합을 줄이는 데 도움이 됩니다. 특히 연결 설정 및 유지 관리 비용이 비교적 높은 PostgreSQL과 같은 데이터베이스 엔진에서 그렇습니다.
-
연결 급증을 보다 정상적으로 처리할 수 있습니다. 예를 들어 데이터베이스가 연결 제한을 초과하면 클라이언트에 즉시 오류를 반환합니다. RDS Proxy가 풀에서 연결을 빌려야 하지만 풀이 이미 용량에 있는 경우 프록시는 연결을 사용할 수 있을 때까지 기다릴 수 있습니다. 이 기능은 하드 오류를 쿼리 지연 시간의 약간의 증가로 전환하여 클라이언트 경험을 개선할 수 있습니다.
-
구성 가능한 연결 풀 크기를 사용하면 RDS Proxy를 스로틀링 또는 로드 셰딩 메커니즘으로 사용할 수도 있습니다. 연결 수가 지정한 제한을 초과하면 RDS Proxy는 구성 가능한 제한 시간 내에 연결을 사용할 수 있을 때까지 기다립니다. 이는 데이터베이스가 여러 워크로드를 제공하고 특정 워크로드가 데이터베이스에 생성할 수 있는 부담을 제한하려는 경우에 유용할 수 있습니다.
컨테이너 기반 분산 애플리케이션의 연결 처리
컨테이너 기반 분산 애플리케이션 아키텍처에는 각각 애플리케이션 코드 사본을 실행하는 수백 또는 수천 개의 컨테이너가 있을 수 있습니다. 개별 컨테이너가 연결 풀링이 가능하더라도 이러한 풀은 컨테이너별로 다르므로 매우 작습니다. 컨테이너 수에 각 컨테이너 미니 풀의 크기를 곱하면 Amazon RDS 또는 Aurora 데이터베이스의 연결 제한을 초과할 수 있습니다.
이 상황에서는 RDS Proxy가 연결 풀링(연결 재사용) 및 멀티플렉싱(백엔드 연결 하나를 사용하여 여러 클라이언트 서비스)을 수행하는 기능이 가장 중요합니다. 각 컨테이너 내에서 연결 풀링을 사용하여 애플리케이션 스레드와 RDS Proxy 간의 이탈을 줄일 수 있지만 프록시는 백엔드 데이터베이스 연결 수를 관리 가능한 수준으로 줄이는 데 도움이 될 수 있습니다.
읽기 복제본 사용률 개선
읽기 전용 트래픽을 지원하려면 읽기 중심 데이터베이스에 여러 개의 읽기 복제본이 필요할 수 있습니다. 애플리케이션은 자체 로직을 사용하여 연결할 복제본을 선택하거나, 더 일반적으로 Aurora 클러스터 리더 엔드포인트와 같은 DNS 기반 라운드 로빈 메커니즘을 사용할 수 있습니다. 그러나 DNS 기반 접근 방식을 사용하면 DNS 캐싱으로 인해 복제본 사용률이 일정하지 않을 수 있습니다. 예를 들어 클라이언트는 자신을 특정 복제본으로 ‘고정’하거나, 클러스터에 추가되는 새 복제본을 인식하지 못하거나, 더 이상 존재하지 않는 복제본에 연결을 시도할 수 있습니다.
RDS Proxy 읽기 전용 엔드포인트를 사용하는 경우 프록시는 ‘최소 미해결 연결’ 로직을 사용하여 사용 가능한 모든 복제본 간에 클라이언트 연결을 라우팅합니다. RDS Proxy는 CPU 사용률과 같은 데이터베이스 지표를 기반으로 트래픽을 로드 밸런싱하지 않지만 데이터베이스의 연결 제한을 기준으로 각 복제본의 클라이언트 연결 수를 균등화하려고 시도합니다. 예를 들어 500, 500 및 1000(각각) max_connections 설정으로 실행 중인 Aurora 복제본이 3개 있는 경우 프록시는 세 번째 복제본에 대한 연결 수의 약 두 배를 다른 두 개에 전송하려고 시도합니다.
RDS Proxy 리더 엔드포인트를 Aurora 클러스터와 함께 사용하거나 Amazon RDS Multi-AZ DB 클러스터 배포를 읽기 가능한 대기 2개와 함께 사용할 수 있습니다. 프록시 리더 엔드포인트는 읽기 복제본이 있는 Amazon RDS DB 인스턴스 배포에는 지원되지 않습니다.
연결 효율성 개선
클라이언트 애플리케이션과 데이터베이스 간에 프록시를 도입할 때 일반적으로 프록시를 통한 추가 네트워크 홉의 지연 시간 비용도 고려하면서 연결 처리 효율성을 높이는 것이 목표입니다. 데이터베이스에 대해 직접 열렸을 모든 연결이 이제 프록시에 대해 열리기 때문에 추가 중간 계층은 연결 효율성을 개선하는 데 직관적이지 않은 것처럼 보일 수 있습니다. 프로토콜 핸드셰이크 단계는 두 경우 모두 동일하므로 연결 핸드셰이크에 리소스를 계속 사용하는 경우 효율성 개선의 출처가 명확하지 않을 수 있습니다.
프록시가 연결을 설정하기 위해 반드시 더 저렴한 것은 아닙니다. 대신 핸드셰이크 처리 부담의 대부분을 데이터베이스 계층에서 프록시 계층으로 이동합니다. 데이터베이스 리소스에 대한 비용을 지불하면 보조 오버헤드가 아닌 데이터베이스 작업에 해당 리소스를 소비할 수 있습니다. 이는 암호화된 연결을 사용할 때 특히 중요합니다. 기존 연결을 통해 암호화된 데이터를 전송하는 오버헤드는 중요하지 않지만 암호화된 연결을 설정하는 초기 오버헤드는 상당합니다. 초당 수백 또는 수천 개의 연결을 통해 이탈하는 환경에서는 이러한 추가 노력이 빠르게 누적될 수 있습니다. (상대적으로 비용이 많이 드는) 데이터베이스 리소스에 CPU 시간을 소비하지 않고 대신 (비교적으로 저렴한) 프록시 계층으로 오프로드할 수 있습니다.
추가 네트워크 홉에서 발생하는 지연 시간과 관련하여 중요한 정도는 애플리케이션이 얼마나 ‘변동’하고 데이터베이스의 각 ‘대화’당 실행되는 문 수에 따라 달라집니다. RDS Proxy에서는 일반적으로 짧은 한 자릿수 밀리초 내에 지연 시간이 추가된 것을 관찰하지만 애플리케이션에 가시적인 영향을 미치지는 않습니다. 예제:
-
쿼리 실행 시간이 수십 또는 수백 밀리초(또는 그 이상)인 워크로드는 총 쿼리 시간의 작은 부분이므로 프록시 오버헤드를 알아차릴 가능성이 낮습니다.
-
한 자릿수 밀리초 또는 밀리초 미만의 쿼리를 실행하는 애플리케이션은 쿼리 오버헤드(쿼리당 추가 네트워크 홉 1개)가 쿼리 실행 시간과 비교하여 상당하기 때문에 차이를 확인할 수 있습니다. 클라이언트 세션에 몇 개의 쿼리만 포함된 경우에도 누적 오버헤드가 여전히 작으면 문제가 되지 않을 수 있습니다.
상황에 추가된 지연 시간이 눈에 띄고 바람직하지 않은 경우 프록시 사용의 다른 이점(풀링, 멀티플렉싱, 장애 조치 처리)과 비교해야 합니다.
높은 가용성
Amazon RDS 및 Aurora에서 실행되는 다중 AZ 데이터베이스(Aurora DSQL 제외)는 장애 조치 메커니즘을 사용하여 기본 데이터베이스 인스턴스에 문제가 발생할 경우 가용성을 복원합니다. 장애 조치는 기본 인스턴스의 컴퓨팅 조정과 같은 운영 워크플로의 일부로도 사용됩니다. 장애 조치에는 기본(읽기/쓰기 가능) 데이터베이스 엔드포인트를 이전 기본 인스턴스에서 새로 승격된 인스턴스로 이동하는 DNS 변경이 포함됩니다. 클라이언트가 지연 없이 기본를 따를 수 있도록 클라이언트 애플리케이션에서 이 DNS 변경을 관찰하고 인식해야 합니다.
일부 애플리케이션은 운영 체제 또는 애플리케이션 수준에서 DNS 캐싱의 결과로 DNS 변경 사항을 적시에 인식하는 데 어려움을 겪을 수 있습니다. 애플리케이션 수준에서 DNS 캐싱 문제를 해결하는 것이 모범 사례이지만 애플리케이션 복잡성이나 변경 사항 도입 비용으로 인해 항상 실현 가능한 것은 아닙니다.
이 시나리오에서 RDS Proxy는 DNS 관련 장애 조치 지연을 방지하는 효과적인 방법입니다. RDS Proxy에서 제공하는 읽기/쓰기 엔드포인트와 선택적 읽기 전용 엔드포인트는 데이터베이스 인스턴스가 역할을 교환할 때 해당 엔드포인트 뒤의 IP 주소가 변경되지 않는다는 점에서 ‘안정적’입니다. RDS Proxy는 백엔드 데이터베이스의 토폴로지를 지속적으로 추적하고 클라이언트에서 인스턴스 역할 변경을 추상화합니다.
DNS에 의존하지 않고 데이터베이스 토폴로지를 직접 감지할 수 있는 고급 드라이버를 사용하는 등 DNS 캐싱 문제를 처리하는 다른 방법이 있습니다. 그러나 애플리케이션 수준에서 코드 변경 및 새 드라이버를 도입하는 대신 데이터베이스 앞에 단일 프록시를 배포하는 것이 더 쉬울 수 있습니다.
읽기 가용성
RDS Proxy는 데이터베이스 장애 조치 중에 클라이언트 경험을 개선하는 것 외에도 읽기 복제본 문제가 발생할 경우 애플리케이션 가용성을 지원합니다. 이 작업은 두 가지 방법으로 수행됩니다.
-
읽기 복제본을 사용할 수 없게 되지만 클러스터에 사용 가능한 다른 복제본이 있는 경우 프록시는 사용 가능한 복제본으로 새 연결을 라우팅할 수 있습니다. 클라이언트는 DNS 전파 지연이나 DNS 캐싱에 대해 걱정할 필요가 없습니다.
-
멀티플렉싱된 기존 클라이언트 연결의 경우 프록시는 해당 연결에서 사용 가능한 다른 복제본으로 후속 쿼리를 보낼 수 있습니다. 이 상황에서 클라이언트는 백엔드 복제본에 문제가 발생했다는 것을 인식하지 못할 수도 있습니다. 이 기술을 사용할 때 RDS Proxy는 복제 지연 측면에서 새 복제본이 이전 복제본보다 뒤처지지 않도록 합니다. 이렇게 하면 클라이언트가 전송한 후속 쿼리에는 오래된 것으로 간주될 수 있는 데이터가 표시되지 않습니다.
하나의 대상에 여러 프록시 사용
Amazon RDS 인스턴스 또는 Aurora 클러스터와 같은 데이터베이스 대상당 하나의 RDS Proxy를 사용하는 것이 가장 좋습니다. 이는 대부분의 시나리오에서 잘 작동하고, 구성을 단순하게 유지하며, 클라이언트 경험을 더 예측 가능하게 만듭니다. 이에 비해 여러 프록시를 사용하려면 예기치 않은 동작을 방지하기 위해 모든 프록시에서 구성을 신중하게 정렬해야 합니다. 예를 들어 모든 프록시 풀의 결합된 크기가 단일 데이터베이스 대상의 연결 제한을 초과하지 않도록 해야 합니다.
특정 상황에서 여러 프록시를 사용하는 아이디어를 계속 탐색할 수 있습니다. 다음 섹션에서는 가장 일반적인 시나리오를 설명하고 단일 프록시와 다중 프록시 접근 방식의 장단점을 간략하게 설명합니다.
프록시 가용성
RDS Proxy 인프라는 설계상 고가용성을 제공하며 여러 가용 영역(AZ)에 배포됩니다. 프록시 용량은 지속적인 상태 모니터링을 통해 여러 노드에 분산되며, 프로비저닝된 인스턴스 크기 또는 데이터베이스의 Serverless v2 최대 ACU 설정에 따라 자동으로 조정됩니다. 프록시의 분산 다중 AZ 설계로 인해 고가용성을 위해 Amazon RDS 또는 Aurora 클러스터 앞에 여러 프록시를 실행할 필요가 없습니다.
실제로 단일 데이터베이스 대상 앞에 여러 프록시를 사용하면 이제 애플리케이션 스택이 프록시에 내장된 강력한 메커니즘에 의존하는 대신 문제를 감지하고 이에 대응할 책임이 있습니다. 따라서 고가용성 이유로 여러 프록시를 사용하는 것은 해결할 수 있는 것보다 더 많은 문제가 발생할 수 있으므로 권장하지 않습니다.
여러 클라이언트 풀 처리
각 프록시는 하나의 읽기/쓰기 엔드포인트와 추가 읽기/쓰기 또는 읽기 전용 엔드포인트(선택 사항)를 제공합니다. 단일 프록시를 사용하여 여러 클라이언트 그룹 또는 여러 워크로드를 처리하는 경우 해당 워크로드가 잠재적으로 방해가 될 수 있습니다. 예를 들어, 한 워크로드는 다른 워크로드를 처리하기에 충분한 여유 연결이 남아 있지 않은 지점까지 연결 풀을 독점할 수 있습니다. 별도의 프록시를 사용하여 워크로드를 격리하는 것은 매력적인 솔루션일 수 있지만 다른 옵션을 먼저 고려할 수 있습니다.
-
데이터베이스 자체는 여러 프록시를 실행하는 것보다 더 간단한 대안을 제공할 수 있습니다. 예를 들어 특정 사용자가 풀을 독점하여 문제가 발생한 경우 데이터베이스의 권한 시스템을 사용하여 해당 사용자가 열 수 있는 동시 연결 수를 제한할 수 있습니다.
-
마찬가지로 데이터베이스 수준 쿼리 제한 시간 및 유휴 제한 시간은 분리된 연결 또는 런어웨이 쿼리 문제를 해결할 수 있습니다.
-
동시 연결 수가 아닌 쿼리 또는 트랜잭션 기간 또는 쿼리당 리소스 소비로 인해 문제가 발생하는 경우 프록시가 쿼리 또는 트랜잭션 가중치에 제한을 부과하지 않으므로 추가 프록시를 사용하는 것이 도움이 되지 않습니다. 소스에서 문제를 해결할 수 없는 경우 데이터베이스의 이벤트 스케줄러를 사용하여 문제가 있는 클라이언트를 별도의 프록시로 이동하는 대신 임의의 조건에 따라 클라이언트 활동을 감지하고 종료하는 코드를 실행할 수 있습니다.
동일한 대상 앞에 여러 프록시를 사용하기로 결정한 경우 모든 연결 풀의 총 크기가 대상 데이터베이스의 기능을 초과하지 않는지 확인합니다. 예를 들어 모든 프록시의 MaxConnectionsPercent 합계는 100보다 작아야 합니다. 그렇지 않으면 프록시가 데이터베이스가 처리하도록 구성된 것보다 더 많은 연결을 열려고 시도할 수 있습니다.
각 프록시는 별도로 청구되며 청구 요금은 워크로드 활동이 아닌 기본 데이터베이스 리소스의 크기에 따라 달라집니다. 여러 프록시를 실행하는 비용과 대체 솔루션이 있는 경우 구현하는 비용을 고려합니다.
읽기 및 쓰기 풀을 독립적으로 제어
각 프록시는 하나의 읽기/쓰기 엔드포인트와 추가 읽기/쓰기 또는 읽기 전용 엔드포인트(선택 사항)를 제공하지만 제한 및 제한 시간은 각 프록시 엔드포인트가 아닌 전체 프록시 대상에 대해 구성됩니다.
예를 들어 여러 읽기 복제본과 프록시의 리더 엔드포인트를 사용하여 대량의 읽기 전용 쿼리를 처리하는 Aurora 클러스터가 있을 수 있지만 단일 라이터에 대한 리소스 부담을 줄이기 위해 읽기/쓰기 연결 수를 제한하고 싶을 수 있습니다. MaxConnectionsPercent 설정은 전체 프록시 대상(클러스터)에 대해 정의되므로 읽기 전용 엔드포인트의 제한에도 영향을 주지 않고 읽기/쓰기 엔드포인트에 대한 연결 수를 제한할 수 없습니다.
이 문제에 접근하는 방법에는 여러 가지가 있습니다.
클러스터에서 추가 읽기 복제본을 시작하고 프록시 MaxConnectionsPercent 설정을 비례적으로 줄일 수 있습니다. 이렇게 하면 라이터에 허용되는 최대 연결 수를 줄이면서 읽기 전용 연결 풀의 총 크기가 유지됩니다. 그러나 클러스터 비용도 증가하며 복제본이 많을수록 덜 효과적입니다.
인스턴스 수준 파라미터 그룹을 사용하여 라이터와 별도로 읽기 복제본에 대한 데이터베이스 연결 제한(예: Aurora MySQL 또는 PostgreSQL의 max_connections)을 구성할 수 있습니다. 그러나 장애 조치 중에 복제본을 라이터 역할로 승격할 수 있으므로 초기 파라미터 구분이 영구적이지 않으므로 비대칭 파라미터 구성을 사용하지 않아야 합니다. 장애 조치 중에 승격을 위해 선택한 복제본에 영향을 미치도록 인스턴스 수준 장애 조치 우선 순위 설정을 변경하고 이를 소프트 장애 조치 제외 메커니즘으로 사용하여 비대칭 구성을 보다 예측 가능하게 만들 수 있습니다. 그러나 장애 조치 우선순위는 힌트로만 사용되며 장애 조치 동작을 확실하게 보장하지는 않습니다. 따라서 비대칭 설정이 있는 다중 인스턴스 구성은 지속적인 모니터링이 필요하고 장애 조치가 원치 않는 인스턴스에 도달하면 예기치 않은 동작을 생성할 수 있으므로 권장되지 않습니다.
이 시나리오에서는 여러 프록시를 사용하는 것이 읽기 및 쓰기 풀을 별도로 관리하는 가장 깔끔한 방법일 수 있습니다. 단일 데이터베이스 대상에 대해 두 개의 프록시를 생성한 다음 첫 번째 프록시의 라이터 엔드포인트와 두 번째 프록시의 읽기 전용 엔드포인트를 사용하도록 애플리케이션을 구성할 수 있습니다. 한 프록시는 쓰기 워크로드만 처리하고, 다른 프록시는 읽기 워크로드만 처리하며, MaxConnectionsPercent(및 기타 설정)는 각 프록시에 대해 독립적으로 구성할 수 있습니다. 이 솔루션에는 두 번째 프록시를 실행하는 데 드는 추가 비용이 포함되지만 이전 대안보다 더 간단하고 예측 가능합니다.