JDBC와 Failover
JDBC와 Failover#
이 절은 Altibase JDBC 애플리케이션에서 Failover 기능을 사용하는 방법을 설명한다.
Failover란#
Failover란 데이터베이스 서버에 장애가 발생하여 연결이 끊어졌을 때, 애플리케이션이 즉시 다른 서버로 연결을 생성하여 기존에 수행하던 작업을 계속하는 기능을 말한다.
Failover는 아래 두 가지 방식으로 동작할 수 있다.
CTF(Connection Time Failover)#
데이터베이스로의 접속 시도를 실패한 경우, 다른 서버로 접속을 재시도하는 동작 방식이다. CTF는 Connection 객체의 connect 메소드를 호출할 때 발생할 수 있다.
STF(Session Time Failover)#
SQL문을 수행하여 서버로부터 결과를 받기 전에 연결 오류가 발생한 경우, 다른 서버로 접속하여 사용자가 지정한 작업을 계속하는 동작 방식이다. STF는 connect를 제외한 서버와 통신을 하는 모든 메소드 수행 시에 발생할 수 있다.
Failover에 대한 자세한 내용은 Replication Manual의 "Failover"장을 참고하도록 한다.
사용 방법#
여기에서는 JDBC 애플리케이션에서 CTF 및 STF 기능을 사용하는 방법을 설명한다.
CTF#
Properties 객체에 아래의 속성을 추가해서 CTF 기능을 사용할 수 있다.
Properties sProps = new Properties();
sProps.put("alternateservers", "database1:20300, database2:20300");
sProps.put("connectionretrycount", "5");
sProps.put("connectionretrydelay", "2");
sProps.put("sessionfailover", "off");
각각의 속성에 대한 자세한 설명은 1장의 "연결 속성" 절을 참고하라.
STF#
CTF 기능을 설정하는 속성에 추가로 "SessionFailover=on"을 설정해서 STF 기능을 사용할 수 있다.
데이터베이스 서버로 접속을 시도하는 것을 제외한 통신 상황에서, 클라이언트가 서버의 장애를 감지하면 먼저 CTF 과정을 수행하여 접속을 복원한다. 그 다음, 클라이언트는 사용자가 등록한 콜백 함수를 수행한 후에, 사용자가 Failover 발생을 인지할 수 있도록 Failover Success Exception을 발생시킨다. 이 때 모든 서버로 Failover가 실패하면 드라이버는 원래 발생했던 Exception을 던진다.
아래는 사용자가 작성해야 할 Failover 콜백 함수를 위한 인터페이스이다.
public interface AltibaseFailoverCallback
{
public final static class Event
{
public static final int BEGIN = 0;
public static final int COMPLETED = 1;
public static final int ABORT = 2;
}
public final static class Result
{
public static final int GO = 3;
public static final int QUIT = 4;
}
int failoverCallback(Connection aConnection,
Object aAppContext,
int aFailoverEvent);
};
다음은 사용자가 Failover 콜백 함수를 등록하고 해제하는 과정을 보여주는 코드 예제이다.
public class UserDefinedFailoverCallback implements AltibaseFailoverCallback
{
...
public int failoverCallback(Connection aConnection,
Object aAppContext,
int aFailoverEvent)
{
// User Defined Code
// Result.GO나 Result.QUIT 중 한 가지 값을 반환해야 함.
}
...
}
위의 AltibaseFailoverCallback 인터페이스에 포함된 Event 상수는 사용자가 작성한 Failover 콜백 함수가 JDBC 드라이버에 의해 호출될 때, 콜백 함수의 세 번째 인자인 aFailoverEvent로 전달된다. 각 Event 상수의 의미는 다음과 같다.
-
Event.BEGIN: Session Failover가 시작됨
-
Event.COMPLETED: Session Failover가 성공하였음
-
Event.ABORT: Session Failover가 실패하였음
AltibaseFailoverCallback 인터페이스에 포함된 Result 상수는 사용자가 작성하는 콜백 함수에서 반환할 수 있는 값들이다. 콜백 함수에서 Result 상수 이외의 값을 반환하면 Failover가 정상적으로 동작하지 않는다.
-
Result.GO 콜백 함수에서 이 상수값이 반환되면, JDBC 드라이버는 STF의 다음 과정을 계속해서 진행한다.
-
Result.QUIT 콜백 함수에서 이 상수값이 반환되면, JDBC 드라이버는 STF 과정을 종료한다.
다음은 사용자가 작성하는 Failover 콜백 함수의 두 번째 인자로 사용할 수 있는 객체의 코드 예제이다.
public class UserDefinedAppContext
{
// User Defined Code
}
사용자가 구현한 애플리케이션의 정보를 STF 과정에서 사용할 필요가 있는 경우, Failover 콜백 함수를 등록하면서 콜백 함수에 전달될 객체를 지정할 수 있다. 콜백 함수를 등록하는 registerFailoverCallback 메소드의 두 번째 인자로 이 객체를 지정하면, 실제로 콜백 함수가 호출될 때 이 객체가 전달된다. 다음은 이런 과정을 코드로 나타낸 예제이다.
// 사용자 정의 콜백 함수 객체 생성
UserDefinedFailoverCallback sCallback = new UserDefinedFailoverCallback();
// 사용자 정의 애플리케이션 정보 객체 생성
UserDefinedAppContext sAppContext = new UserDefinedAppContext();
...
Connection sCon = DriverManager.getConnection(sURL, sProp);
// 사용자 정의 애플리케이션 객체와 함께 콜백 함수 등록
((AltibaseConnection)sCon).registerFailoverCallback(sCallback, sAppContext);
...
// 콜백 함수 해제
((AltibaseConnection)sCon).deregisterFailoverCallback();
코드 예제#
STF를 위한 콜백 함수를 구현하는 코드 예제이다.
아래의 예제는 여러 가지 경우를 무시한 단순 코드이므로, 사용자 애플리케이션에서 그대로 사용할 수 없음을 주의해야 한다.
public class MyFailoverCallback implements AltibaseFailoverCallback
{
public int failoverCallback(Connection aConnection, Object aAppContext,int aFailoverEvent)
{
Statement sStmt = null;
ResultSet sRes = null;
switch (aFailoverEvent)
{
// 사용자 어플리케이션의 로직상 Failover 시작 전에 필요한 작업을 진행할 수 있다.
case Event.BEGIN:
System.out.println("Failover Started .... ");
break;
// 사용자 어플리케이션의 로직상 Failover 완료 후에 필요한 작업을 진행할 수 있다.
case Event.COMPLETED:
try
{
sStmt = aConnection.createStatement();
}
catch( SQLException ex1 )
{
try
{
sStmt.close();
}
catch( SQLException ex3 )
{
}
return Result.QUIT;
}
try
{
sRes = sStmt.executeQuery("select 1 from dual");
while(sRes.next())
{
if(sRes.getInt(1) == 1 )
{
break;
}
}
}
catch ( SQLException ex2 )
{
try
{
sStmt.close();
}
catch( SQLException ex3 )
{
}
// Failover 과정을 종료한다.
return Result.QUIT;
}
break;
}
// Failover 과정을 계속한다.
return Result.GO;
}
}
다음은 STF 성공 여부를 확인하는 코드 예제이다. STF가 성공했는지 실패했는지를 판단하는 방법은 SQLException의 ErrorCode가 Validation.FAILOVER_SUCCESS와 일치하는지 확인하는 것이다. while loop 내에 Failover 검증 코드를 삽입한 이유는 Failover가 성공하더라도 이전에 수행중이던 작업은 다시 수행해야 하기 때문이다.
// 반드시 수행하려던 작업을 재수행할 수 있도록 구현해야 한다.
// 이 경우에는 while loop를 사용하였다.
while (true)
{
try
{
sStmt = sConn.createStatement();
sRes = sStmt.executeQuery("SELECT C1 FROM T1");
while (sRes.next())
{
System.out.println("VALUE : " + sRes.getString(1));
}
}
catch (SQLException e)
{
// Failover 성공 여부 확인
if (e.getErrorCode() == AltibaseFailoverCallback.FailoverValidation.FAILOVER_SUCCESS)
{
// Failover가 성공했으므로 Exception을 무시하고 계속 진행한다.
continue;
}
System.out.println("EXCEPTION : " + e.getMessage());
}
break;
}