로드밸런싱 관리
개요
본 문서에서는 OpenSQL v3.0의 OpenProxy 모듈에서 제공하는 PostgreSQL 서버 로드 밸런싱 및 쿼리 라우팅 기능에 대한 전반적인 설명과 구성 방법에 대하여 기술한다.
기능
Read-Only Load Balancing
PostgreSQL의 Streaming Replication 구성에서 Primary가 아닌 Replica 인스턴스는 Read-Only 쿼리만을 처리할 수 있다. OpenProxy는 구성에 따라 Read-Only 쿼리를 Replica 인스턴스들 중 하나로 보내어 처리하고 결과를 반환하는 로드밸런싱 기능을 제공한다.
OpenProxy에서는 기본적으로 Pool (OpenProxy에 접속 시 Database 이름으로 구분되는 PostgreSQL 서버군) 단위로 로드밸런싱 옵션을 관리하며 Pool마다 다른 설정을 부여할 수 있다.
구성
Query Parser 활성화
Read-Only 쿼리를 식별해 Replica 인스턴스로 보내기 위해서는 openproxy.toml
구성에서 아래 옵션을 활성화해야 한다.
query_parser_enabled
: Query Parsing 기능을 활성화한다. Read / Write Splitting 외에도 Plugin 기능 활용을 위해서는 해당 옵션을 활성화해야 한다.query_parser_read_write_splitting
: Parsing한 쿼리를 기반으로 Replica로 보낼 수 있는 (Read-Only) 쿼리인지 Primary에서만 처리할 수 있는 쿼리인지 판단하는 Infer 기능을 활성화한다.
[pools.my_pool]
pool_mode = "transaction"
query_parser_enabled = true
query_parser_read_write_splitting = true
Pool의 PostgreSQL 구성에 따라 위 옵션으로 동작하는 OpenProxy는 사용자 쿼리를 파싱하여 Replica
Role을 가진 서버로 사용자 요청을 보내 처리한다.
Simple Query 프로토콜로
SELECT
쿼리를 처리하거나 Extended 프로토콜로 명시적인 Transaction Block 없이SELECT
만 파싱하여 처리하는 경우는 Replica로 라우팅할 수 있다.명시적인 Transaction 내에서 1개 혹은 여러 개의 Statement를 처리하는 경우는 Primary로 라우팅한다.
이 외에 Primary 노드도 Read-Only 쿼리를 보내는 대상에 포함하고자 하는 경우는 아래와 같이
primary_reads_enabled
옵션을 활성화한다.
[pools.my_pool]
pool_mode = "transaction"
query_parser_enabled = true
query_parser_read_write_splitting = true
primary_reads_enabled = true
session
풀링 모드 (하나의 클라이언트가 하나의 PostgreSQL 서버 연결에서 처리되는 방식) 에서도 해당 옵션은 동작하지만 클라이언트의 첫 쿼리를 infer()
한 결과로 얻은 PostgreSQL 서버 연결이 클라이언트 세션 종료시까지 유지되므로, SELECT
쿼리를 먼저 처리하고 이후 Primary에서만 처리되어야 하는 쿼리를 보내는 경우 에러가 발생할 수 있다.
Query 파싱 및 로드밸런싱 기능을 사용하고자 하는 경우에는
transaction
풀링 모드 (하나의 트랜잭션이 하나의 PostgreSQL 서버 연결에서 처리되는 방식) 를 사용하는 것을 권장한다.
Load Balancing 설정
Pool 단위로 Read-Only 쿼리를 처리할 Replica를 선택하는 방식을 설정할 수 있다.
random
방식은 PostgreSQL 서버 중 랜덤하게 하나의 서버를 선택하여 요청을 라우팅하는 방식이다.loc
방식은 현재 활성화된 Connection 수가 가장 적은 PostgreSQL 서버로 요청을 라우팅하는 방식이다.
[pools.my_pool]
load_balancing_mode = "random" ## "random", "loc"
Prepared Statement Cache 설정
Prepared Statement는 PostgreSQL Extended Protocol에서 쿼리를 실행하는 방식의 하나로, 사용자 지정 쿼리를 전처리한 (Pre-compiled) 쿼리 실행 Plan 형태로 DBMS 서버에 오브젝트 형태로 저장하여 사용하는 방식이다.
PostgreSQL에서는 클라이언트 세션 단위로 Prepared Statement 생성 및 처리를 지원한다.
OpenProxy의 session
풀링 모드에서는 하나의 Client가 종료시까지 하나의 PostgreSQL 서버 연결에서만 처리되므로 별도의 작업이 필요 없으나, transaction
풀링 모드에서는 하나의 Client가 Transaction 단위로 여러 개의 PostgreSQL 서버 연결에서 처리가 될 수 있으므로 Prepared Statement 처리 시 문제가 발생할 수 있다.
이를 위해 OpenProxy는
transaction
풀링 모드로 동작 시 글로벌한 Prepared Statement 캐시 기능을 제공한다.Client들이 선언한 모든 Prepared Statement는 캐시에 저장되고, Client가 Prepared Statement를 실행하려는 경우 해당 Prepared Statement를 캐시에서 가져와 현재 PostgreSQL 서버 세션에 선언되었는지 확인하고, 선언되어 있지 않은 경우 실행에 앞서 선언한다.
해당 글로벌 Cache를 활성화하기 위해서는 Pool의
prepared_statements_cache_size
값을 지정해주어야 한다. 기본값은0
으로 글로벌 Cache를 비활성화하는 설정이다.글로벌 Cache가 비활성화된 경우, Client 내에서 Unnamed (클라이언트가 이름을 지정하지 않은) Prepared Statement의 처리만을 지원한다. 즉 Client가 2개 이상의 Prepared Statement를 바인딩하고 실행하려는 경우 에러가 발생한다.
해당 글로벌 Cache는 LRU 방식으로 유지되며, 값이 너무 작은 경우 Prepared Statement를 많이 선언하는 클라이언트 요청 처리 시 문제가 발생할 수 있다.
[pools.my_pool]
pool_mode = "transaction"
prepared_statements_cache_size = 1000
주의사항
지원되지 않는 기능
transaction
풀링 모드에서 Query Parser를 활성화하는 경우 아래 SQL 명령어들의 처리가 제한된다.
PREPARE
, EXECUTE
이름을 가진 (Named) Prepared Statement를 사용자가 명시적으로 SQL 레벨에서 생성하고 실행을 지시하는 명령어이다.
transaction
풀링 모드에서는 각 Transaction이 서로 다른 서버 Connection에서 실행될 수 있으므로 정상적으로 동작하지 않는다.session
풀링 모드에서는 Client와 Server 사이의 Connection이 세션이 유지되는 동안 동일하므로 사용할 수 있다.
사용자 지정 함수의 실행
CREATE FUNCTION
구문을 이용해 사용자 지정 함수를 Database에 생성하는 경우, 해당 함수가 Primary 노드에서만 실행되어야 하는 DDL 혹은 DML 구문을 포함한다면SELECT
쿼리를 이용한 해당 함수의 실행이 OpenProxy 구성 설정에 따라 Replica 노드로 라우팅되어 에러가 발생할 수 있다.특정 구문의 실행을 명시적 Transaction Block
BEGIN … COMMIT
으로 감싸 Primary 노드로만 라우팅하는 방향으로 우회할 수 있다.
Last updated