'Know/Java'에 해당되는 글 27건

  1. 2014.01.22 Netty ChannelGroup
  2. 2013.06.11 Selenium을 이용한 UI 테스트
  3. 2013.02.22 JDBC 동작 원리
  4. 2013.02.13 Java Troubleshooting Tool - VisualVM
  5. 2012.02.24 m2 eclipse 버전업시에 에러 ignore
  6. 2011.01.12 Eclipse ERD Plugin
  7. 2010.10.07 Maven local Repository에 custom jar 추가하기
  8. 2009.08.14 Hash
  9. 2009.04.22 ant native2ascii
  10. 2008.10.14 MINA - Logging Configuration

Netty ChannelGroup

Know/Java 2014.01.22 14:12


http://netty.io/5.0/api/index.html


A thread-safe Set that contains open Channels and provides various bulk operations on them. Using ChannelGroup, you can categorize Channels into a meaningful group (e.g. on a per-service or per-state basis.) A closed Channel is automatically removed from the collection, so that you don't need to worry about the life cycle of the added Channel. A Channel can belong to more than one ChannelGroup.


ChannelGroup은 쓰레드 세이프하며 Channel을 Set에 관리하며 다양한 오퍼레이션을 제공한다.

ChannelGroup을 사용하면 의미있는 그룹들로 Channel들을 분류할수 있으며 끊긴 Channel들은 자동으로 Collection에서 삭제된다. 하여 추가된 Channel들의 라이프사이클에 관하여 걱정하지 않아도 된다.

하나의 채널은 여러개의 Channel 그룹에 속할수 있다.

'Know > Java' 카테고리의 다른 글

Netty ChannelGroup  (0) 2014.01.22
Selenium을 이용한 UI 테스트  (0) 2013.06.11
JDBC 동작 원리  (0) 2013.02.22
Java Troubleshooting Tool - VisualVM  (0) 2013.02.13
m2 eclipse 버전업시에 에러 ignore  (0) 2012.02.24
Eclipse ERD Plugin  (0) 2011.01.12
Trackbacks 0 : Comments 0

Selenium을 이용한 UI 테스트

Know/Java 2013.06.11 17:29


Selenium을 이용한 UI 테스트


1. Selenium 개요

1.1 Selenium이란

  • Selenium은 웹 어플리케이션을 위한 테스팅 프레임워크로 자동화 테스트를 위한 여러가지 강력한 기능을 지원해준다.
  • 다양한 브라우저들을 지원하며, 다양한 테스트 작성 언어(Java, Ruby, Groovy, Python, PHP, and Perl.)를 지원한다.
  • 현재 WebDriver라는 웹 자동화 툴과 통합하는 작업이 진행되고 있다. (2.0ax 버전)
  • 홈페이지 : http://seleniumhq.org/http://code.google.com/p/selenium/

1.2 Selenium Components

1.2.1 Selenium IDE
  • Selenium Test Case를 만들고 실행하기 위한 통합 개발 환경
  • 파이어폭스 확장 플러그인으로 제공되며, Selenium Test Case를 쉽게 작성할 수 있도록 도와준다
  • 레코딩이 쉽고, 재생을 지원한다.
  • 브라우저 내의 사용자의 행동을 저장하여 다양한 언어(C#, Java, Perl, PHP, Python, Ruby 등)로 변환 가능 하다.
  • 참고 : http://seleniumhq.org/projects/ide/
1.2.2 Selenium Core
  • Selenium의 Core 라이브러리
1.2.3 Selenium RC(Remote Control)
  • http 를 통해 command 를 받는 Java 로 작성된 서버
  • Selenium API로 작성한 테스트 코드를 실행시켜 주는 역할을 한다.
  • 테스트용 PC 에 설치를 한 후 원격지에서 unit 테스트 framework로 웹어플리케이션의 자동화 테스트를 가능하게 한다.
  • 참고 : http://seleniumhq.org/projects/remote-control/
1.2.4 Selenium GRID
  • Selenium GRID를 이용해 테스트 코드를 여러대의 Selenium RC에서 동시에 실행 할 수 있다.
  • 테스트 수행속도를 향상시키기 위해 분산해서 처리하거나 여러가지 환경에서 테스트가 필요할 때 사용한다.
  • 서로다른 브라우저 환경에서 일관성있는 테스트가 가능하다.
  • 참고 : http://selenium-grid.seleniumhq.org/how_it_works.html

2. Selenium IDE의 사용

2.1 Selenium IDE 설치

2.1.1 다운로드 및 설치
2.1.2 설치 확인
  • "Fire Fox > 도구" 메뉴 에서 설치 확인
2.1.3 Selenium IDE Toolbar
  • 1. Speed Control : 테스트 케이스의 속도 재생 속도 조절
  • 2, Run All : Test Suite를 재생
  • 3. Run : Test Case를 재생
  • 4. Pause/Resume : 테스트 케이스의 정지와 리스타트
  • 5. Step : 클릭 시 한번에 한 라인씩 수행
  • 6. TestRunner Mode : 브라우저 내에서 테스트 실행 및 결과를 HTML Table 형식으로 볼 수 있음 (Firefox 3.6에서 잘 안 됨)
  • 8. Record : 유저 브라우저의 액션을 레코딩 시작/정지 버튼

2.2 Selenium IDE 테스팅 예제

  • Selenium IDE에서 Recording 후 저장된 테스트코드를 수행하면 된다.
2.2.1 Recording
  • ① Firefox를 열어서 도구 => Selenium IDE를 선택해서 IDE를 활성화 시킨다
  • ② Test하기 원하는 사이트로 이동 한다. 또는 Base URL 입럭
  • ③ 빨강색 Record버튼을 누른다.
  • ④ Firefox창에서 원하는 액션을 수행하면 해당내용이 자동으로 저장된다.
  • ⑤ 원하는 테스트가 끝났으면 다시 빨강색 Record버튼을 눌러서 종료시킨다.
2.2.2 저장된 테스트코드 수행
  • ① 테스트 수행속도를 설정한다.
  • ② Play 버튼을 눌러서 테스트를 수행한다.
2.2.3 테스트를 자바코드로 전환
  • Selenium IDE에서 테스트 작성 후 IDE 메뉴에서 Options => Format 으로 원하는 언어를 선택하면 된다.
  • 아래는 JUnit4 기반의 테스트 코드 예제이다.
  • 테스트 코드의 "Untitled" 와 "change-this-to-the-site-you-are-testing"를 수정하면 된다.
    package com.example.tests;
    
    import com.thoughtworks.selenium.*;
    import java.util.regex.Pattern;
    
    public class Untitled extends SeleneseTestCase {
    	public void setUp() throws Exception {
    		setUp("http://change-this-to-the-site-you-are-testing/", "*chrome");
    	}
    	public void testUntitled() throws Exception {
    		selenium.open("/home/index.nhn");
    		selenium.type("query", "리쌍");
    		selenium.click("//input[@type='image']");
    		selenium.waitForPageToLoad("30000");
    		verifyTrue(selenium.isTextPresent("개리"));
    	}
    }
2.2.4 간단 데모

3. Selenium RC의 사용

3.1 다운로드 및 설치

3.1 Selenium RC 예제

3.1.1 Selenium RC 서버 Start
  • java -jar selenium-remote-control-1.0.3\selenium-server-1.0.3\selenium-server.jar
3.1.2 JUnit 테스트
  • 아래는 Selenium IDE로 저장한 자바코드를 Selenium RC를 이용해 테스트하는 예제이다.
    import com.thoughtworks.selenium.SeleneseTestCase;
    
    public class SimpleRCTest extends SeleneseTestCase {
        public void setUp() throws Exception {
            setUp("http://dev.music.naver.com/", "*firefox");
        }
    
        public void testSearch() throws Exception {
            selenium.open("/home/index.nhn");
            selenium.type("query", "리쌍");
            selenium.click("//input[@type='image']");
            selenium.waitForPageToLoad("30000");
            verifyTrue(selenium.isTextPresent("개리"));
        }
    }
  • Selenium관련 maven 빌드 설정
    -- repository 설정
    <repositories>
        <repository>
            <id>selenium-repository</id>
            <url>http://selenium.googlecode.com/svn/repository/</url> 
        </repository>
    </repositories>
    
    -- dependency 설정
    -- 아래서  WebDriver 간단설명 예정으로 WebDriver 포함 버전으로 설정했음.
    <dependencies>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium</artifactId>
            <version>2.0a4</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
3.1.3 간단 데모

4. WebDriver를 이용한 UI 테스트

4.1 WebDriver 개요

4.1.1 WebDriver란?
  • 단순한 API들로 구성된 개발자 중심의 웹 UI 테스트 자동화 도구 이다.
  • 다양한 브라우저(FireFox, Internet Explorer, Safari, Chrome...)에서 일관성 있는 테스트를 할 수 있다.
  • Selenium 1.0에서 지원하지 못하던 테스트 기능 문제를 개선하였다.
  • multiple frames, multiple browser windows, popups, and alerts, Page navigation, Drag-and-drop, AJAX-based UI elements등 테스트 가능하다
  • 현재 Selenium과 통합되어 2.0a 버전이 개발되고 있다.
4.1.2 WebDriver 장점
  • Driver 변경만으로 다양한 환경에서 테스트 수행이 가능 하다.
  • 표준 API 지원을 통해 개발자 UI 테스트에 최적화 되어 있다.
  • Real browser 외에도 HtmlUnitDriver 지원을 통한 빠른 테스트 피드백이 가능 하다.
  • 현재 Selenium과 연계를 통해 장단점 상호 보완 중이다.
4.1.3 WebDriver 단점
  • 개발자 중심의 UI 테스트 도구인 관계로 초기 학습 시간 및 비용에 대한 부담이 발생한다.
  • 시나리오에 기인한 테스트케이스의 작성이 까다롭고 불명확할 수 있다.

4.2 WebDriver 예제

4.2.1 간단 예제
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;

public class Example  {
    public static void main(String[] args) {
        // Create a new instance of the html unit driver
        // Notice that the remainder of the code relies on the interface,
        // not the implementation.
        WebDriver driver = new HtmlUnitDriver();

        // And now use this to visit Google
        driver.get("http://www.google.com");

        // Find the text input element by its name
        WebElement element = driver.findElement(By.name("q"));

        // Enter something to search for
        element.sendKeys("Cheese!");

        // Now submit the form. WebDriver will find the form for us from the element
        element.submit();

        // Check the title of the page
        System.out.println("Page title is: " + driver.getTitle());
    }
}

문서정보


'Know > Java' 카테고리의 다른 글

Netty ChannelGroup  (0) 2014.01.22
Selenium을 이용한 UI 테스트  (0) 2013.06.11
JDBC 동작 원리  (0) 2013.02.22
Java Troubleshooting Tool - VisualVM  (0) 2013.02.13
m2 eclipse 버전업시에 에러 ignore  (0) 2012.02.24
Eclipse ERD Plugin  (0) 2011.01.12
Trackbacks 0 : Comments 0

JDBC 동작 원리

Know/Java 2013.02.22 09:31

 

Mysql Statement Cancellation tiemr 관련 에러를 찾아보다가 찾게 된글

 

JDBC 동작 원리에 대해 자세히 설명이 되어있다.

 

한번쯤 읽어보면 도움이 될듯한 글

 

원본글 http://helloworld.naver.com/helloworld/1321

 

 

NHN Business Platform 웹플랫폼개발랩 강운덕

성능 문제나 장애가 발생할 때 중요하게 살펴보는 부분(tier)은 WAS(Web Application Server)와 DBMS입니다. 대부분의 경우에 WAS를 담당하는 조직과 DBMS를 담당하는 조직이 달라, 각자 담당 분야를 중심으로 상황을 파악하려 합니다. 이때 상대적으로 관심을 못 받는 사각지대가 생기는데, 바로 WAS와 DBMS 사이입니다. Java 애플리케이션을 기준으로 말하면 DBCP와 JDBC입니다. 이 글에서는 JDBC의 타임아웃 설정을 중심으로 장애에 대응하는 방법을 설명하겠습니다.

  • 어느 날 DDoS 공격, 그 뒤로 먹통이 된 WAS

    다음과 같은 사고가 일어났다고 가정해 보자.

    DDoS 공격으로 서비스 전체가 정상적으로 동작하지 않았다. L4가 정상으로 동작하지 않아 네트워크가 단절되었고, 이로 인해 WAS도 동작 불능 상태에 빠졌다. 이후 보안팀에서는 DDoS 공격을 전부 차단했고, 네트워크도 정상으로 복구되었다. 그러나 WAS는 여전히 동작 불능 상태이다.

    서비스팀에서는 WAS의 ThreadDump를 통해 JDBC의 API 호출 중에 WAS가 정지해 있음을 확인했다. 10분이 지나고 20분이 지나도 WAS는 여전히 정지 상태(WAITING)였고, 서비스는 정상으로 동작하지 않았다. 그런데 30분이 지날 무렵 갑자기 Exception을 발생시키면서 서비스가 복구되었다.

    QueryTimeout 값도 3초로 설정되어 있는데 왜 30분씩이나 WAS가 정지 상태에 있었으며, 30분이 지나니 왜 정상적으로 WAS가 동작했던 것일까?

    정답은 JDBC의 타임아웃 과정을 이해하면 알 수 있다.

  • 왜 JDBC 드라이버에 대해서 알아야 하는가?

    JDBC는 DBMS에 접근하기 위한 표준 API이다. Sun은 4가지 타입의 드라이브를 정의하는데, NHN에서 주로 사용하는 것은 Type4 형식이다. JDBC Type4 드라이버는 Java로만 작성되어 있으며(pure java), Java 애플리케이션에서 소켓을 이용해 DBMS와 통신한다.

    122111_0935_JDBCInterna1.png

    그림 1 JDBC Type4 드라이버의 DBMS 통신 구조

    Type4 드라이버는 소켓을 통해 바이트 스트림(byte stream)을 처리하기 때문에 HttpClient 같은 네트워크 라이브러리와 근본적으로 동작이 같다. 즉, 많은 CPU자원을 소모하고, ResponseTime의 손해가 있으며, 다른 네트워크 라이브러리가 가지고 있는 장애 포인트를 동일하게 가지고 있다. HttpClient를 사용한 경험이 있다면 타임아웃 값을 제대로 설정하지 않아 장애(hang)가 발생한 상황을 겪어 보았을 것이다. Type4 드라이버 역시 SocketTimeout 값을 제대로 설정하지 않으면 동일한 장애가 발생할 수 있다.

    JDBC 드라이버의 SocketTimeout 값을 어떻게 설정하면 좋을지, 그리고 무엇을 고려해야 히는지 알아보자.

  • WAS와 DBMS의 통신 시 타임아웃 계층

    그림 2는 WAS와 DBMS와 통신 시 타임아웃 계층을 단순화한 것이다.

    122111_0935_JDBCInterna2.png

    그림 2 타임아웃 계층

    상위 레벨의 타임아웃은 하위 레벨의 타임아웃에 의존성을 가지고 있다. 하위 레벨의 타임아웃이 정상으로 동작해야 상위 레벨의 타임아웃도 정상으로 동작한다. 예를 들어, JDBC Driver SocketTimeout이 정상으로 동작하지 않으면, 그보다 상위 레벨의 타임아웃인 StatementTimeout과 TransactionTimeout도 정상으로 동작하지 않는다.

    "StatementTimeout을 설정했는데도 네트워크 장애가 발생했을 때, StatementTimeout이 동작하지 않아 애플리케이션이 장애 상황에서 회복되지 않았어요"란 문의를 많이 받았다. StatementTimeout은 네트워크 연결 장애에 대한 타임아웃을 담당하는 것이 아니다. StatementTimeout은 Statement 한 개의 수행 시간을 제한하는 기능만 담당한다. 네트워크 장애에 대비하는 타임아웃은 JDBC Driver SoecketTimeout이 처리해야 한다.

    JDBC Driver SocketTimeout은 OS의 SocketTimeout 설정에 영향을 받는다. JDBC Driver SocketTimeout을 설정하지 않아도 네트워크 장애 발생 이후 30분이 지나면 JDBC Connection Hang이 복구되는 것은 OS의 SocketTimeout 설정때문이다.

    그림 2에서 DBCP Connection Pool이 타임아웃 계층과 분리되어 왼쪽에 있는 것을 볼 수 있다. DBCP는 Connection을 생성하고 관리하는 일을 하며, 타임아웃 처리에는 관여하지 않는다. DBCP 내부에서 Connection을 생성하거나 Connection 유효성을 확인하려 Validation Query를 보낼 때에는 SocketTimeout이 영향을 주지만 애플리케이션에 직접적인 영향을 주지는 않는다.

    단, 애플리케이션 로직에서 DBCP에 getConnection() 메서드를 호출할 때 Connection을 애플리케이션이 얻을 때까지의 타임아웃을 지정할 수 있다. 하지만 이것은 JDBC의 ConnectTimeout과는 무관하다.

    122111_0935_JDBCInterna3.png

    그림 3 각 레벨 별 타임아웃

  • TransactionTimeout이란?

    TransactionTimeout은 프레임워크(Spring, EJB Container)나 애플리케이션 레벨에서 유효한 타임아웃이다.

    TransactionTimeout은 생소한 개념일 수 있다. 간단히 설명하면 "StatementTimeout x N(Statement 수행 수) + α(가비지 컬렉션 및 기타)"라고 할 수 있다. 전체 Statement 수행 시간을 허용할 수 있는 최대 시간 이내로 제한하려 할 때 TransactionTimeout을 사용한다.

    가령 Statement 한 개를 수행할 때 0.1초가 필요하다면, 몇 개 안 되는 Statement를 수행할 때에는 문제가 없다. 그러나 Statement 10만 개를 수행할 때에는 일만 초(약 7시간)가 필요하다. TransactionTimeout은 이런 경우에 사용할 수 있다.

    실 구현체로 EJB CMT(Container Managed Transaction)가 가장 대표적인 예이다. EJB CMT는 제작사마다 구현 방식과 동작 과정이 다르다. NHN에서는 EJB Container를 사용하지 않으므로, 가장 익숙한 예는 Spring의 TransactionTimeout이 될 수 있겠다. Spring에서는 다음과 같이 XML을 이용하여 설정하거나, Java 코드에서 @Transactional을 이용하여 타임아웃을 설정할 수 있다.

    1
    2
    3
    <tx:attributes>
    <tx:method name="…" timeout="3">
    </tx:method></tx:attributes>

    Spring에서 제공하는 TransactionTimeout은 매우 단순하다. 해당 Transaction의 시작 시간과 경과 시간을 기록하면서, 특정 이벤트 발생 시 경과 시간을 확인하여 타임아웃 이상일 경우 예외(Exception)를 발생하도록 하고 있다.

    Spring에는 Transaction Synchronization방식이라고 하여 Connection을 ThreadLocal에저장해 두고 사용한다. ThreadLocal에 Connection 저장 시 Transaction의 시작 시간과 타임아웃 시간을 같이 기록하고, Proxy Connection을 사용하여 Statement를 생성하는 작업을 시도할 경우 경과 시간을 체크하여 예외를 발생시키도록 구현되어있다.

    EJB CMT 구현 방식 또한 크게 다르지 않다. 만약 TransactionTimeout이 매우 중요하고 사용하는 컨테이너나 프레임워크에서 이런 기능을 제공하지 않는다면 직접 구현해서 사용해도 별 무리가 없을 정도로 매우 단순한 구조이다. TransactionTimeout에 대한 표준 API는 없다.

    수행 시간이 200ms인 Statement가 5개 이하이고 기타 부수적인 비즈니스 로직 처리 시간이나 프레임워크 동작 시간이 100ms일 경우, TrasactionTimeout시간은 1100ms((200 x 5)+100) 이상으로 설정해야 한다.

  • StatementTimeout 이란?

    Statement 하나가 얼마나 오래 수행되어도 괜찮은지에 대한 한계 값이다. JDBC API인 Statement에 타임아웃 값을 설정하며, 이 값을 바탕으로 JDBC 드라이버가 StatementTimeout을 처리한다. JDBC API인 java.sql.Statement.setQueryTimeout(int timeout) 메서드로 설정한다.

    요즘 개발 환경에서는 개발자가 직접 StatementTimeout을 Java 코드로 설정하는 경우는 드물며, 프레임워크를 이용하여 해결하는 경우가 많다. iBatis를 예로 들어 설명하자면 "sql-map-config.xml" 파일의 sqlMapConfig/settings에 @defaultStatementTimeout 값으로 기본값을 설정할 수 있다. 또한 "sql-map.xml" 파일의 statement, select, insert, update 구문마다 @timeout 값으로 개별적으로 설정할 수 있다.

    StatementTimeout 시간은 애플리케이션 특성에 따라 지정하기 때문에 이에 대한 설정 권장 값은 없다.

  • JDBC 드라이버의 StatementTimeout 동작 방식

    StatementTimeout의 동작방식은 DBMS나 드라이버별로 다르다.

    Oracle과 Microsoft SQL Server의 동작 방식이 서로 비슷하고, MySQL과 CUBRID의 동작 방식이 서로 비슷하다.

  • Oracle JDBC Statement의 QueryTimeout

    122111_0935_JDBCInterna4.png

    그림 4 Oracle JDBC Statement의 QueryTimeout 동작 과정

    Oracle JDBC Statement의 QueryTimeout은 다음과 같은 과정으로 동작한다.

  • Connection.createStatement() 메서드를 호출하여 Statement를 생성한다.
  • Statement.executeQuery() 메서드를 호출한다.
  • Statement는 자신의 Connection을 사용하여 Oracle DBMS로 쿼리를 전송한다.
  • Statement는 타임아웃 처리를 위해 OracleTimeoutPollingThread(classloader별로 1개 존재)에 Statement를 등록한다.
  • 타임아웃이 발생한다.
  • OracleTimeoutPollingThread는 OracleStatement.cancel() 메서드를 호출한다.
  • Connection을 통해 취소(cancel) 메시지를 전송하여 수행중인 쿼리를 취소한다
  • jTDS(Microsoft SQL Server) Statement의 QueryTimeout

    122111_0935_JDBCInterna5.png

    그림 5 jTDS(Micsofot SQL Server) Statement의 QueryTimeout의 동작 과정

    jTDS(Microsoft SQL Server) Statement의 QueryTimeout은 다음과 같은 과정으로 동작한다.

  • Connection.createStatement() 메서드를 호출하여 Statement를 생성한다.
  • Statement.executeQuery() 메서드를 호출한다.
  • Statement는 내부 Connection을 사용하여 Microsoft SQL DBMS로 쿼리를 전송한다.
  • Statement는 타임아웃 처리를 위해 TimerThread에 Statement를 등록한다.
  • 타임아웃이 발생한다.
  • TimerThread는 JtdsStatement 객체 내부의 TdsCore.cancel() 메서드를 호출한다.
  • ConnectionJDBC을 통해 취소 메시지를 전송하여 수행중인 쿼리를 취소한다.
  • MySQL JDBC Statement의 QueryTimeout(5.0.8 버전)

    122111_0935_JDBCInterna6.png

    그림 6 MySQL JDBC Statement의 QueryTimeout의 동작 과정(5.0.8 버전)

    MySQL JDBC Statement(5.0.8 버전)의 QueryTimeout은 다음과 같은 과정으로 동작한다.

  • Connection.createStatement() 메서드를 호출하여 Statement를 생성한다.
  • Statement.executeQuery() 메서드를 호출한다.
  • Statement는 내부 Connection을 사용하여 MySQL DBMS로 쿼리를 전송한다.
  • Statement는 타임아웃 처리를 위해 새로운 타임아웃 처리용 스레드를 생성한다. 5.1.x 버전에서는 Connection에 한 개의 스레드가 할당되는 것으로 변경되었다.
  • 스레드에 타임아웃 처리를 등록한다.
  • 타임아웃이 발생한다.
  • 타임아웃 처리 스레드가 Statement와 동일한 설정의 Connection을 생성한다.
  • 생성된 Connection을 사용하여 취소 쿼리(KILL QUERY "connectionId")를 전송한다.
  • CUBRID JDBC Statement의 QueryTimeout

    122111_0935_JDBCInterna7.png

    그림 7 CUBRID JDBC Statement의 QueryTimeout의 동작 과정

    CUBRID JDBC Statement의 QueryTimeout은 다음과 같은 과정으로 동작한다.

  • Connection.createStatement() 메서드를 호출하여 Statement를 생성한다.
  • Statement.executeQuery() 메서드를 호출한다.
  • Statement는 내부 Connection을 사용하여 CUBRID DBMS로 쿼리를 전송한다.
  • Statement는 타임아웃 처리를 위해 새로운 타임아웃용 스레드를 생성한다.
  • 스레드에 타임아웃 처리를 등록한다.
  • 타임아웃이 발생한다.
  • 타임아웃 처리 스레드가 Statement와 동일한 설정의 Connection을 생성한다.
  • 생성된 Connection을 사용하여 취소 메시지를 전송한다.
  • JDBC 드라이버의 SocketTimeout 이란?

    JDBC Driver Type4는 소켓을 사용하여 DBMS에 연결하는 방식이고, 애플리케이션과 DBMS 사이의 ConnectTimeout 처리는 DBMS에서 하지 않는다.

    JDBC 드라이버의 SocketTimeout 값은 DBMS가 비정상으로 종료되었거나 네트워크 장애(기기 장애 등)가 발생했을 때 필요한 값이다. TCP/IP의 구조상 소켓에는 네트워크의 장애를 감지할 수 있는 방법이 없다. 그렇기 때문에 애플리케이션은 DBMS와의 연결 끊김을 알 수 없다. 이럴 때 SocketTimeout이 설정되어 있지 않다면 애플리케이션은 DBMS로부터의 결과를 무한정 기다릴 수도 있다(이러한 Connection을 Dead Connection이라고 부르기도 한다).

    이러한 상태를 방지하기 위해 소켓에 타임아웃을 설정해야 한다. SocketTimeout은 JDBC 드라이버에서 설정할 수 있다. SocketTimeout을 설정하면 네트워크 장애 발생 시 무한 대기 상황을 방지하여 장애 시간을 단축할 수 있다.

    단, SocketTimeout 값을 Statement의 수행 시간 제한을 위해 사용하는 것은 바람직하지 않다. 그러므로 SocketTimeout 값은 StatementTimeout 값보다는 크게 설정해야 한다. SocketTimeout값이 StatementTimeout보다 작으면, SocketTimeout이 먼저 동작하므로 StatementTimeout 값은 의미가 없게 되어 동작하지 않는다.

    SocketTimeout에는 아래 두 가지 옵션이 있고, 드라이버별로 설정 방법이 다르다.

    • Socket Connect 시 타임아웃(connectTimeout): Socket.connect(SocketAddress endpoint, int timeout) 메서드를 위한 제한 시간
    • Socket Read/Write의 타임아웃(socketTimeout): Socket.setSoTimeout(int timeout) 메서드를 위한 제한 시간

    CUBRID, MySQL, jTDS (Microsoft SQL Server), Oracle JDBC 소스를 모두 확인해 본 결과 네 개의 드라이버에서는 위의 두 가지 API를 사용함을 확인할 수 있었다. JDBC 드라이버별 SocketTimeout의 설정 방법은 아래와 같다. connectTimeout와 socketTimeout의 기본 값인 0은 타임아웃을 발생하지 않도록 하는 것이다.

    표 1 SocektTimeout 설정 방법

    JDBC 드라이버

    connectTimeout

    기본값

    단위

    적용 방법

    socketTimeout

    기본값

    단위

    MySQL Driver

    connectTimeout

    0

    ms

    DriverURL에 옵션 명시

    • 형식

    jdbc:mysql://[host:port],[host:port].../[database]

    [?propertyName1][=propertyValue1][&propertyName2][=propertyValue2]...

    jdbc:mysql://xxx.xx.xxx.xxx:3306/database?connectTimeout=60000&socketTimeout=60000

    socketTimeout

    0

    ms

    jTDS(MS-SQL Server) Driver

    loginTimeout

    0

    sec

    DriverURL에 옵션명시

    • 형식

    jdbc:jtds:<server_type>://<server>[:<port>][/<database>][;<property>=<value>[;...]]

    jdbc:jtds:sqlserver://server:port/database;loginTimeout=60;socketTimeout=60

    socketTimeout

    0

    sec

    Oracle Thin Driver

    oracle.net.CONNECT_TIMEOUT

    0

    ms

    DriverURL로 설정할 수 없고, OracleDatasource.setConnectionProperties() API를 통해 Properties 객체로 전달해야 한다.

    DBCP사용 시 다음 API를 사용한다.

    • BasicDatasource.setConnectionProperties()
    • BasicDatasource.addConnectionProperties()

    oracle.jdbc.ReadTimeout

    0

    ms

    Cubrid Thin Driver

    별도 설정 없음

    5,000

    ms

    DriverURL로 설정할 수 없으며, 5초 후 타임아웃이 발생한다.

    • URL에 althost 옵션 지정으로 타입아웃 시 지정된 호스트로 연결 가능
    • C API로는 URL에 login_time 옵션을 ms단위로 명시 가능

    별도 설정 없음

    5,000

    ms

    DriverURL로 설정할 수 없으며, 5초 후 타임아웃이 발생한다.

    • URL에 althost 옵션 지정으로 timeout 시 지정된 호스트로 연결 가능

    DBCP의 별도 API를 직접 사용하지 않고, Properties로 설정하는 방법도 있다. Properties 설정 시 키는 "connectionProperties", 값은 "[propertyName=property;]*" 형식의 문자열을 전달한다. 다음 예는 iBatis에서 XML을 통한 Properties 설정을 예로 들었다.

    1
    2
    3
    4
    5
    6
    <transactionmanager type="JDBC">
    <datasource type="com.nhncorp.lucy.db.DbcpDSFactory">
    ....
    <property name="connectionProperties" value="oracle.net.CONNECT_TIMEOUT=6000;oracle.jdbc.ReadTimeout=6000">
    </property></datasource>
    </transactionmanager>
  • OS 레벨 SocketTimeout 설정

    SocketTimeout이나 ConnectTimeout을 설정하지 않으면 네트워크 장애가 발생해도 애플리케이션이 대부분 이를 감지할 수 없다. 따라서 연결이 되거나 데이터를 읽을 수 있을 때까지 애플리케이션이 무한정 기다리게 된다. 그러나 서비스에서 발생한 실재 장애 상황에서는 30분 후에 애플리케이션(WAS)이 재연결을 시도하여 문제가 해결되는 경우가 많다. OS에서도 SocketTimeout 시간을 설정할 수 있기 때문이다.

    이 기사의 처음에 예로 든 리눅스 서버에서는 SocketTimeout을 30분으로 설정해 두고 있었다. 해당 설정 값을 통해 OS 레벨에서 네트워크 연결 끊김을 확인하는 것이다. 문제가 발생한 리눅스 서버의 KeepAlive 체크 수행 주기가 30분이므로 SocketTimeout 설정을 0으로 해도 네트워크 장애로 인한 DBMS 연결 장애 지속 시간이 30분을 넘지 않는 것이다. Linux 서버에서 KeepAlive 체크 수행 주기는 tcp_keepalive_time로 조정할 수 있다.

    네트워크 장애로 인해 애플리케이션이 대기 상태로 빠지는 경우는 대부분 애플리케이션이 Socket.read() 메서드를 호출하고 있을 때이다. 그러나 네트워크 구성이나 장애 유형에 따라 매우 드물게 Socket.write() 메서드를 실행하는 도중 대기 상태에 빠지는 경우가 있다.

    애플리케이션에서 Socket.write() 메서드를 호출하면 OS 커널 버퍼에 데이터를 기록한 후 바로 제어권을 애플리케이션에 반환한다. 즉 커널 버퍼에 값을 제대로만 기록하면 Socket.write() 메서드 실행은 언제나 성공한다. 그러나 특수한 네트워크 장애로 OS 커널 버퍼가 가득차면 Socket.write() 메서드도 대기 상황에 빠질 수 있다. 이 경우 OS는 일정 시간 동안 패킷 재전송을 시도하다고 한계 값에 도달하면 에러를 발생시킨다. 이 기사에서 예로 든 서버에서는 해당 값이 대략 15분으로 설정되어 있었다. 이 값은 Linux 서버의 tcp_retries2로 조절할 수 있다.

  • 마치며

    JDBC 내부의 동작 설명은 이것으로 마무리한다. 올바른 타임아웃 설정으로 장애를 줄이는 데 도움이 되었으면 하는 바람이다. 추가적인 문의나 JDBC에 관련한 좋은 정보가 있다면 개발자센터 블로그나 이 기사의 댓글로 글을 남겨 주기를 부탁한다.

    마지막으로 자주 문의가 들어온 내용을 정리해 보았다.

    • Q Statement.setQueryTimeout() 메서드로 QueryTimeout을 설정했는데도 네트워크 장애 발생 시 기대하는 대로 동작하지 않습니다.
      A QueryTimeout은 정상적으로 소켓 연결을 맺고 있을 때에만 유효합니다. 그렇기 때문에 네트워크 장애의 예외 상황을 처리할 수 없습니다. 네트워크 장애 상황을 대비하려면 JDBC 드라이버에 있는 SocketTimeout을 설정해야 합니다.
    • Q TransactionTimeout, StatementTimeout, JDBC 드라이버 SocketTimeout은 DBCP 설정 값과 어떤 관계가 있나요?
      A DBCP에서 Connection을 JDBC로부터 얻어올 때 DBCP의 waitTimeout 값만큼 대기할 수 있습니다. 그 외의 DBCP 설정 값은 DBCP 단독으로 동작합니다.
    • Q JDBC SocketTimeout을 설정하면 DBCP에서 유휴 상태(idle)로 오래 유지된 Connection이 닫히지 않나요?
      A 아니요, 닫히지 않습니다. Socket 옵션은 실제 데이터를 쓰거나 읽을 때 적용되기 때문에, DBCP 안에서 유휴 상태인 Connecton에 영향을 끼치지 않습니다. DBCP 내부에서 부족한 Connection 생성, 오래된 유휴 Connection 제거, Validation Check 시 영향을 줄 수 있지만 네트워크에 문제가 발생하지 않는 한 특이 사항은 일어나지 않습니다.
    • Q SocketTimeout시간은 얼마나 길게 설정해야 하나요?
      A 본문에서 말한 것처럼 StatementTimeout보다는 충분히 크게 잡아야 하며, 권장 값은 없습니다. JDBC 드라이버의 SocketTimeout 값이 영향을 주는 시점은 네트워크 장애가 발생한 이후입니다. 해당 값을 정밀하게 설정한다고 해서 장애가 발생하지 않는 것이 아니며, 경우에 따라(네트워크 장애가 곧 복구되었을 경우) 장애 시간을 줄일 수 있을 뿐입니다.

    'Know > Java' 카테고리의 다른 글

    Netty ChannelGroup  (0) 2014.01.22
    Selenium을 이용한 UI 테스트  (0) 2013.06.11
    JDBC 동작 원리  (0) 2013.02.22
    Java Troubleshooting Tool - VisualVM  (0) 2013.02.13
    m2 eclipse 버전업시에 에러 ignore  (0) 2012.02.24
    Eclipse ERD Plugin  (0) 2011.01.12
    Trackbacks 0 : Comments 0

    Java Troubleshooting Tool - VisualVM

    Know/Java 2013.02.13 17:42

     

    java thread 정보를 분석할 수 있는 visual tool.

     

    다운로드는 아래!

     

     

    http://visualvm.java.net/download.html

    'Know > Java' 카테고리의 다른 글

    Selenium을 이용한 UI 테스트  (0) 2013.06.11
    JDBC 동작 원리  (0) 2013.02.22
    Java Troubleshooting Tool - VisualVM  (0) 2013.02.13
    m2 eclipse 버전업시에 에러 ignore  (0) 2012.02.24
    Eclipse ERD Plugin  (0) 2011.01.12
    Maven local Repository에 custom jar 추가하기  (0) 2010.10.07
    Trackbacks 0 : Comments 0

    m2 eclipse 버전업시에 에러 ignore

    Know/Java 2012.02.24 22:37

    아래의 내용을 <build> 태그 사이에 입력

    <pluginManagement>
    <plugins>
        <!-- Ignore/Execute plugin execution -->
        <plugin>
            <groupId>org.eclipse.m2e</groupId>
            <artifactId>lifecycle-mapping</artifactId>
            <version>1.0.0</version>
            <configuration>
                <lifecycleMappingMetadata>
                    <pluginExecutions>
                        <!-- copy-dependency plugin -->
                        <pluginExecution>
                            <pluginExecutionFilter>
                                <groupId>org.apache.maven.plugins</groupId>
                                <artifactId>maven-dependency-plugin</artifactId>
                                <versionRange>[1.0.0,)</versionRange>
                                <goals>
                                    <goal>copy-dependencies</goal>
                                </goals>
                            </pluginExecutionFilter>
                            <action>
                                <ignore />
                            </action>
                        </pluginExecution>
                    </pluginExecutions>
                </lifecycleMappingMetadata>
            </configuration>
        </plugin>
       </plugins></pluginManagement>




    maven-resources-plugin prior to 2.4 is not supported by m2e. Use maven-resources-plugin version 2.4 or later.

    에러시 아래와 같이 처리

      <plugin> 
       
    <groupId>org.apache.maven.plugins</groupId> 
       
    <artifactId>maven-resources-plugin</artifactId> 
         
    <version>2.4</version> 
       
    <executions> 
         
    <!-- had a process goal here that i removed because it was not compatible --> 
       
    </executions> 
     
    </plugin> 


    'Know > Java' 카테고리의 다른 글

    JDBC 동작 원리  (0) 2013.02.22
    Java Troubleshooting Tool - VisualVM  (0) 2013.02.13
    m2 eclipse 버전업시에 에러 ignore  (0) 2012.02.24
    Eclipse ERD Plugin  (0) 2011.01.12
    Maven local Repository에 custom jar 추가하기  (0) 2010.10.07
    Hash  (0) 2009.08.14
    Trackbacks 0 : Comments 0

    Eclipse ERD Plugin

    Know/Java 2011.01.12 11:14

    ERD 무료 TOOL을 찾아보던 중, Eclipse 플러그인이 존재하는 것을 알았다.

    http://download.eclipse.org/tools/gef/updates

    'Know > Java' 카테고리의 다른 글

    Java Troubleshooting Tool - VisualVM  (0) 2013.02.13
    m2 eclipse 버전업시에 에러 ignore  (0) 2012.02.24
    Eclipse ERD Plugin  (0) 2011.01.12
    Maven local Repository에 custom jar 추가하기  (0) 2010.10.07
    Hash  (0) 2009.08.14
    ant native2ascii  (0) 2009.04.22
    Trackbacks 0 : Comments 0

    Maven local Repository에 custom jar 추가하기

    Know/Java 2010.10.07 14:36

    Maven 사용시 customize 한 jar를 사용할 경우 local repository에 추가하는 방법이다

    사용법

    mvn install:install-file -Dfile=추가할 jar파일 경로 -DgroupId=groupid -DartifactId=artifactid -Dversion=version  -Dpackaging=jar


     



    'Know > Java' 카테고리의 다른 글

    m2 eclipse 버전업시에 에러 ignore  (0) 2012.02.24
    Eclipse ERD Plugin  (0) 2011.01.12
    Maven local Repository에 custom jar 추가하기  (0) 2010.10.07
    Hash  (0) 2009.08.14
    ant native2ascii  (0) 2009.04.22
    MINA - Logging Configuration  (0) 2008.10.14
    Trackbacks 0 : Comments 0

    Hash

    Know/Java 2009.08.14 11:18

    출처: http://internet512.chonbuk.ac.kr/datastructure/hash/hash1.htm


    Hashing은 하나의 문자열을 원래의 것을 상징하는 더 짧은 길이의 값이나 키로 변환하는 것이다. 짧은 해시 키를 사용하여 항목을 찾으면 원래의 값을 이용하여 찾는 것보다 더 빠르기 때문에, 해싱은 데이터베이스 내의 항목들을 색인하고 검색하는데 사용된다.

    또한 해싱에 의해 정렬된 이름들 각각은 데이터베이스 내에서 개인들 데이터의 키가 될 수 있다. 데이터베이스 검색 수법은 일치하는 것이 먼저 발견될 때까지 각 이름들을 글자단위로 확인하기 시작해야만 한다. 그러나, 만약 이름들 각각이 해시된다면, 각 이름별로 4자리의 고유한 키를 생성하는 것이 가능해진다. 예를 들면 다음과 같다.

    Abernathy, Sara
    Epperdingle, Roscoe
    Moore, Wilfred
    Smith, David
    (그리고 더 많은 수의 데이터가 알파벳 순으로 정렬되어 있다).

       7864 Abernathy, Sara
       9802 Epperdingle, Roscoe
       1990 Moore, Wilfred
       8822 Smith, David
              (기타 등등)

    어떤 이름을 찾는 작업은 먼저 해시 값을 계산하고, 그 다음에 그 값을 사용하여 일치여부를 비교하는 작업으로 구성된다. 일반적으로 이렇게 하는 것은, 각 문자가 26개의 경우를 갖는 예측할 수 없는 값의 길이에서 찾는 것보다, 각각이 오직 9개의 경우를 갖는 네 자리 수에서 일치하는 것을 찾는 것이 더 빠르다


    해싱 알고리즘을 해시 함수라고 부른다. 해싱 함수(hashing function) h(k)는 어떤 키 k에 대한 테이블 주소(table address)를 계산하기 위한 방법으로, 주어진 키 값으로부터 레코드가 저장되어 있는 주소를 산출해 낼 수 있는 수식을 말한다.

    해싱은 빠른 속도의 데이터 검색 외에도, 전자서명을 암호화하고 복호화하는 데에도 사용된다. 전자서명은 해시 함수를 이용하여 변환된 다음, 해시 값(이를 요약 메시지라고 부른다)과 전자서명이 별도로 전송된다. 수신자는 송신자가 사용한 해시함수와 같은 것을 사용하여, 서명으로부터 요약 메시지를 뽑아내어 그것을 이미 수신한 요약 메시지와 비교한다. 그 비교 결과는 같아야만 전자서명이 유효한 것이다.

    해시 함수는 원래의 값이나 키를 색인하는데 사용되며, 그 값이 관련된 데이터가 검색될 때마다 다시 사용된다. 그러나, 해싱은 항상 한 쪽 방향으로만 연산된다. 따라서, 해시된 값을 분석함으로써 해시 함수를 추출해내는 역방향 공학은 필요가 없다. 사실, 이상적인 해시함수는 그러한 분석에 의해 추론할 수 없어야 한다. 또한, 우수한 해시 함수는 서로 다른 두 개의 입력에 대해, 동일한 해시 값을 생산해서는 안된다. 만약 그렇게 되면, 충돌이 생긴다. 충돌 위험성이 매우 적은 해시 함수라야 훌륭한 해시 함수로 평가된다.

    데이터베이스 저장이나 검색에 잘 적용되는 해시 함수는 오히려 암호화나 에러검출 목적으로는 잘 듣지 않을 수도 있다. 암호화에 사용되는 잘 알려진 해시 함수들이 몇 개 있다. 이러한 것들에는 전자서명을 요약 메시지라고 불리는 더 짧은 값으로 바꾸는 데 사용되는 요약 메시지 해시 함수 MD2, MD4, MD5 등과, 더 큰 요약 메시지 (60 비트)를 만드는 표준 알고리즘인 SHA (Secure Hash Algorithm) 등이 포함된다.

    'Know > Java' 카테고리의 다른 글

    Eclipse ERD Plugin  (0) 2011.01.12
    Maven local Repository에 custom jar 추가하기  (0) 2010.10.07
    Hash  (0) 2009.08.14
    ant native2ascii  (0) 2009.04.22
    MINA - Logging Configuration  (0) 2008.10.14
    [Eclipse] Absent Line Number Information  (0) 2007.07.23
    Trackbacks 0 : Comments 0

    ant native2ascii

    Know/Java 2009.04.22 16:57
    ANT의 native2ascii 를 이용하여 여러개의 파일을 UTF-8로 변경하기


    <?xml version="1.0" encoding="UTF-8"?>
    <project name="native2ascii" default="convert" basedir=".">
    <target name="init" >
    <property name="javasrc.dir" value="D:\src" />
    <property name="javabld.dir" value=".\java" />
    </target>
    <target name="clear">
    <delete>
    <fileset dir="${javabld.dir}" includes="**/*.java"/>
    </delete>
    </target>
    <target name="convert" depends="init,clear">
    <native2ascii encoding="UTF-8" reverse="true" src="${javasrc.dir}" dest="${javabld.dir}" includes="**/*.java"/>
    </target>
    </project>

    'Know > Java' 카테고리의 다른 글

    Maven local Repository에 custom jar 추가하기  (0) 2010.10.07
    Hash  (0) 2009.08.14
    ant native2ascii  (0) 2009.04.22
    MINA - Logging Configuration  (0) 2008.10.14
    [Eclipse] Absent Line Number Information  (0) 2007.07.23
    api 문서 링크  (0) 2006.07.20
    Trackbacks 0 : Comments 0

    MINA - Logging Configuration

    Know/Java 2008.10.14 13:45
    생각보다 간단하다. -_-;;


    MINA를 사용한 어플리케이션의 로깅방법은 아래와 같다.

    로깅에 필요한 jar들을 classpath에 추가한 후,
    src의 ROOT에 아래와 같은 내용으로 log4j.properties 파일로 놓아둔다.

    # Set root logger level to DEBUG and its only appender to A1.
    log4j.rootLogger=DEBUG, A1

    # A1 is set to be a ConsoleAppender.
    log4j.appender.A1=org.apache.log4j.ConsoleAppender

    # A1 uses PatternLayout.
    log4j.appender.A1.layout=org.apache.log4j.PatternLayout
    log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c{1} %x - %m%n


    자세한 내용은 아래의 링크로.

    http://mina.apache.org/logging-configuration.html#LoggingConfiguration-log4jexample

    'Know > Java' 카테고리의 다른 글

    Hash  (0) 2009.08.14
    ant native2ascii  (0) 2009.04.22
    MINA - Logging Configuration  (0) 2008.10.14
    [Eclipse] Absent Line Number Information  (0) 2007.07.23
    api 문서 링크  (0) 2006.07.20
    DataSource를 이용한 ConnectionPool 설정  (0) 2006.05.16
    Trackbacks 0 : Comments 0