JDBC (Java Database Connectivity) 환경에서의 런타임 연결 로드 균형 조정

JDBC 런타임 연결 로드 균형 조정(Runtime Connection Load Balancing)이란?

JDBC 런타임 연결 로드 균형 조정(RCLB)은 오라클 Real Application Clusters (RAC) 환경에서 JDBC 클라이언트가 데이터베이스에 연결할 때, 연결 요청을 클러스터 내의 여러 노드에 분산시켜 시스템 자원을 효율적으로 활용하고 성능을 최적화하는 기술입니다.

본 가이드에서는 JDBC RCLB를 구성하고 활용하는 방법에 대해 자세히 설명하며, 실제 적용 가능한 예제 코드와 실행 결과를 통해 이해를 돕고자 합니다.

JDBC RCLB 구성 단계

JDBC RCLB를 활성화하려면 클라이언트 측과 서버 측 모두 구성해야 합니다.

1. 서버 측 구성

RAC 환경이 구성되어 있는지 확인합니다. 서버가 연결 이벤트 알림(FAN: Fast Application Notification)을 발행하도록 구성합니다. FAN은 클러스터 멤버십 변경, 서비스 상태 변경 등을 클라이언트에 알리는 메커니즘입니다.

2. 클라이언트 측 구성

JDBC 드라이버를 최신 버전으로 업데이트합니다. 11g Release 1 (11.1) 이후의 드라이버는 RCLB를 기본적으로 지원합니다. ojdbc7.jar 이상을 사용하는 것이 좋습니다.

연결 문자열에 다음 속성을 추가합니다:

  • LOAD_BALANCE=on: 연결 로드 균형 조정을 활성화합니다.
  • CONNECT_TIMEOUT=10: 연결 시도 시간 초과 값을 10초로 설정합니다 (선택 사항).
  • TRANSPORT_CONNECT_TIMEOUT=3: 연결 시도 실패 후 다음 시도까지의 대기 시간을 3초로 설정합니다 (선택 사항).
  • RETRY_COUNT=30: 연결 시도 실패 시 재시도 횟수를 30회로 설정합니다 (선택 사항).

    String url = "jdbc:oracle:thin:@(DESCRIPTION=
        (ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=racnode1)(PORT=1521))
                       (ADDRESS=(PROTOCOL=TCP)(HOST=racnode2)(PORT=1521)))
        (CONNECT_DATA=(SERVICE_NAME=myservice))
        (LOAD_BALANCE=on)(CONNECT_TIMEOUT=10)(TRANSPORT_CONNECT_TIMEOUT=3)(RETRY_COUNT=30))";
    

실전 예제 코드 및 실행 결과

다음 예제는 JDBC 연결을 생성하고 간단한 SQL 쿼리를 실행하는 Java 코드입니다. RCLB가 활성화되어 있으면, 연결 요청은 RAC 클러스터 내의 가용한 노드에 자동으로 분산됩니다.


    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.Statement;

    public class JDBCLoadBalanceExample {

        public static void main(String[] args) {
            String url = "jdbc:oracle:thin:@(DESCRIPTION=
                (ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=racnode1)(PORT=1521))
                               (ADDRESS=(PROTOCOL=TCP)(HOST=racnode2)(PORT=1521)))
                (CONNECT_DATA=(SERVICE_NAME=myservice))
                (LOAD_BALANCE=on)(CONNECT_TIMEOUT=10)(TRANSPORT_CONNECT_TIMEOUT=3)(RETRY_COUNT=30))";
            String user = "myuser";
            String password = "mypassword";

            try (Connection conn = DriverManager.getConnection(url, user, password)) {
                System.out.println("Connection successful!");

                Statement stmt = conn.createStatement();
                ResultSet rs = stmt.executeQuery("SELECT SYSDATE FROM DUAL");
                if (rs.next()) {
                    System.out.println("Current Date: " + rs.getString(1));
                }

                rs.close();
                stmt.close();
                conn.close();

            } catch (Exception e) {
                System.err.println("Connection failed: " + e.getMessage());
            }
        }
    }
    

위 코드에서 racnode1racnode2는 RAC 클러스터 내의 데이터베이스 노드 호스트 이름이며, myservice는 데이터베이스 서비스 이름입니다. myusermypassword는 데이터베이스 연결 사용자 이름과 비밀번호로 대체해야 합니다.

실행 결과 (성공적인 연결 시):

Connection successful!
Current Date: 2023-10-27
    

실행 결과 (연결 실패 시):

Connection failed: Network Adapter could not establish the connection
    

FAN 이벤트 활용

FAN 이벤트는 데이터베이스 장애 또는 가동 중단 시 클라이언트에게 알림을 제공하여 애플리케이션이 빠르게 대응할 수 있도록 합니다. FAN 이벤트를 활용하면, 애플리케이션은 더 이상 사용 불가능한 노드에 대한 연결 시도를 중단하고 가용한 노드로 즉시 전환할 수 있습니다.

FAN 이벤트 구독

FAN 이벤트를 구독하려면 oracle.jdbc.fan.FanManager 클래스를 사용합니다. 다음 예제는 FAN 이벤트를 구독하고 처리하는 방법을 보여줍니다.


    import java.sql.Connection;
    import java.sql.DriverManager;
    import oracle.jdbc.OracleConnection;
    import oracle.jdbc.fan.FanManager;

    public class FANExample {
        public static void main(String[] args) {
            String url = "jdbc:oracle:thin:@(DESCRIPTION=
                (ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=racnode1)(PORT=1521))
                               (ADDRESS=(PROTOCOL=TCP)(HOST=racnode2)(PORT=1521)))
                (CONNECT_DATA=(SERVICE_NAME=myservice))
                (LOAD_BALANCE=on)(CONNECT_TIMEOUT=10)(TRANSPORT_CONNECT_TIMEOUT=3)(RETRY_COUNT=30))";
            String user = "myuser";
            String password = "mypassword";

            try {
                Connection conn = DriverManager.getConnection(url, user, password);
                OracleConnection oracleConn = conn.unwrap(OracleConnection.class);

                FanManager fanManager = FanManager.getFanManager();
                fanManager.register(oracleConn, (e) -> {
                    System.out.println("FAN Event received: " + e.getType());
                    System.out.println("Event details: " + e.toString());
                });

                System.out.println("Successfully registered for FAN events.");

                conn.close();
            } catch (Exception e) {
                System.err.println("Error registering for FAN events: " + e.getMessage());
            }
        }
    }
    

위 코드에서 FanManager.register() 메서드를 사용하여 FAN 이벤트 리스너를 등록합니다. FAN 이벤트가 발생하면, 제공된 람다 표현식이 실행되어 이벤트 정보를 출력합니다.

RCLB 모니터링 및 문제 해결

JDBC RCLB가 제대로 작동하는지 확인하려면 다음과 같은 방법을 사용할 수 있습니다.

  • 연결 풀 통계 확인: 애플리케이션 서버 또는 연결 풀 관리 도구를 사용하여 연결 풀의 상태를 모니터링합니다. 가용한 연결 수가 적절히 유지되고 있는지 확인합니다.
  • JDBC 드라이버 로그 확인: JDBC 드라이버의 로그 레벨을 높여 연결 시도, FAN 이벤트 처리 등의 정보를 기록하도록 설정합니다. 로그를 분석하여 연결 실패 또는 오류 발생 여부를 확인합니다.
  • 서버 측 로그 확인: 데이터베이스 서버 로그를 확인하여 클라이언트 연결 요청, FAN 이벤트 생성 등을 모니터링합니다.

주의 사항

  • 로드 밸런싱이 잘 되기 위해서는 RAC DB에 여러 인스턴스가 떠있어야 한다.
  • FAST_FAILOVER 설정은 사용하지 않는 것이 좋다 (deprecated).

결론

JDBC RCLB는 오라클 RAC 환경에서 애플리케이션의 가용성과 성능을 향상시키는 데 필수적인 기술입니다. 본 가이드에서 제공하는 정보와 예제 코드를 활용하여, JDBC RCLB를 성공적으로 구성하고 최적화된 데이터베이스 환경을 구축하시기 바랍니다.

위로 스크롤