쉼터

'공부/opensource'에 해당되는 글 3건

  1. 2009.09.01 httpclient 사용시 CLOSE_WAIT, TIME_WAIT 문제 해결방안 (2)
  2. 2008.03.17 hbase 설치 (2)
  3. 2008.03.03 hadoop 설치
HTTP 통신할때 주로 httpclient를 이용해서 처리를 한다.

기본적인 httpclient 사용 방법은 다음과 같다.

더보기

여기서 주의할 점은
method.releaseConnection();
이렇게 connection을 끊어줘야한다.

근데 간혹 CLOSE_WAIT, TIME_WAIT이 누적되어서 FD가 빠지지 않는 경우가 있다.
(ESTABLISHED, CLOSE_WAIT, TIME_WAIT이 뭔지 모른다면 TCP 3-Way handshake부터 공부하면 된다.)
대충쓸때는 상관없지만 문제는 지속적으로 연결할때 CLOSE_WAIT, TIME_WAIT이 없어지지않고 계속해서 쌓이게될때가 있다.

일단 CLOSE_WAIT이 계속 누적해서 안빠진다면 httpclient를 잘못쓴 경우가 많다.
연결할때마다 계속해서 httpclient를 new해서 생성을 하면서 어느수준이상으로 연결을 시도할때 CLOSE_WAIT이 누적되어 안빠지게된다.
왜냐하면 httpclient는 default가 HTTP/1.1 방식이다.
어느정도 keepalive를 유지하기때문에
서버에서는 connectionTimeout이 지나면 연결을 종료시키지만
서버에서 연결종료된 상황을 클라이언트에서 서버로 다시 물어보기전에는 알 수가 없다.
그래서 완전히 종료가 안되고 CLOSE_WAIT 상태가 된다.
근데 이 상황에서 매번 httpclient를 생성하게되면 제대로 연결을 종료안되고
클라이언트 쪽에는 CLOSE_WAIT이 쌓이게된다.

해결책은 여러방법이 있다.
1. 클라이언트쪽에서 HTTP/1.0으로 연결하면된다.

method.getParams().setParameter(HttpMethodParams.PROTOCOL_VERSION, HttpVersion.HTTP_1_0);

1.0으로 연결을 한다는거는 keepalive를 유지안하고 매번 연결하고 끊고한다는거다.
이렇게 하면 CLOSE_WAIT이 누적은 안된다.
하지만 CLOSE_WAIT대신에 TIME_WAIT이 누적된다.
그리고 매번 연결을 끊고 연결하기때문에 throughput이 제대로 안나온다.

2. httpclient를 제한적으로 사용하는 방법이다.
httpclient를 wrapping하는 하나의 클래스를 만든다.
그리고 그 클래스를 싱글톤패턴을 이용해서 필요한곳에서 사용한다.
근데 문제는 스레드환경에서 한번에 여러군데 접속하고 싶을때는 문제가 발생한다.
그럴때는 MultiThreadedHttpConnectionManager를 이용하면된다.

MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
HttpClient client = new HttpClient(connectionManager);

이렇게만 해주면 알아서 pooling을 해준다.
MultiThreadedHttpConnectionManager에는 몇가지 옵션이 있는데
필요에 따라서 적절히 조절해주면된다.

이렇게 하면 CLOSE_WAIT 상태가 계속해서 누적되어 쌓이지 않는다.

3. IdleConnectionTimeoutThread를 이용해서 해결 할 수도 있다.

MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
IdleConnectionTimeoutThread idleConnectionTimeoutThread = new IdleConnectionTimeoutThread();
idleConnectionTimeoutThread.addConnectionManager(connectionManager);
HttpClient client = new HttpClient(connectionManager);
idleConnectionTimeoutThread.start();

이렇게 별도의 스레드를 생성해서 idle상태를 주기적으로 지워준다.

IdleConnectionTimeoutThread를 이용하지않고
connectionManager.closeIdleConnections(1000*10);
이걸 이용해서 주기적으로 지워줄 수 있다.

근데 3번째 방법은 CLOSE_WAIT를 해결하는 방법이라기보단
CLOSE_WAIT가 발생할때 더 이상 안늘어나게하는 사후처리 방법이다.

웬만하면 2번째처럼 통신할 수 있는 채널에 제약을 걸어서 많이 생성못하도록하는게 제일 좋은거 같다.

그리고 TIME_WAIT 상태가 누적되는거는 연결이 종료되는데 시간이 걸리기때문에
어쩔 수 없이 발생을 하게된다.
그래서 웬만하면 HTTP/1.1로 통신을 해야한다.
서버도 HTTP/1.1로 받을 수 있도록하고
클라이언트도 HTTP/1.1로 보내면서 keepalvie를 유지해서
나름 서로간에 전용통로를 만들어줘서 연결이 종료안되게 만들면된다.

여기서 중요한것은 MultiThreadedHttpConnectionManager 여기에
maxTotalConnections 이 값을 상황에 맞게 유지시키는거다.
내가 연결해야하는 connection수가 maxTotalConnections수를 넘어가게된다면
어쩔수 없이 기존 연결된 소켓을 끊고 새롭게 연결해야하기때문에
keepalive 상태를 유지못한다.

즉, TIME_WAIT이 안일어나게 하기 위해서는 연결 종료를 안하고
계속 그 통로를 통해서 통신을 하는건데
maxTotalConnections수를 적절히 조절해서 연결이 안끊기게
keepalive 상태를 유지하게하면된다.

자세한 사항은 httpclient wiki에 나와있다.
Posted by pchun Trackback 0 Comment 2

hbase 설치

2008.03.17 21:51 : 공부/opensource
hbase는 Google의 Bigtable의 clone 프로젝트로 진행중에 있고
hadoop의 subproject로 진행중이다.

즉, hbase를 사용할려면 hadoop(0.16.0이상)을 다운 받으면된다.

$HADOOP_HOME/contrib/hbase 에 있다.

일단 $HBASE_HOME/conf/hbase-site.xml을 편집한다.

<configuration>
    <property>
        <name>hbase.master</name>
        <value>localhost:60000</value>
        <description>The host and port that the HBase master runs at.</description>
    </property>
  
<property>
        <name>hbase.rootdir</name>
        <value>hdfs://localhost:9000/hbase</value>
        <description>The directory shared by region servers.</description>
    </property>
</configuration>

일단 hbase.master, hbase.rootdir는 기본적으로 설정해줘야한다.

$HBASE_HOME/conf/regionservers 이 파일하고 $HADOOP_HOME/conf/slaves와 동일하게 해준다.

$HBASE_HOME/bin/start-hbase.sh(hbase 시작)
$HBASE_HOME/bin/stop-hbase.sh(hbase 종료)

항상 hadoop을 먼저 띄우고 hbase를 시작해야하고 hbase를 닫고 hadoop을 닫아줘야한다.

http://localhost:60010
정상적으로 hbase가 실행이 된다면 위 페이지가 나올것이다.

참조사이트(http://hadoop.apache.org/hbase/docs/current/api/overview-summary.html#overview_description)
Posted by pchun Trackback 0 Comment 2

hadoop 설치

2008.03.03 23:18 : 공부/opensource
- ssh 설치
ssh를 이용해서 remote hadoop daemons을 관리하기 때문에 필수로 설치되어야한다.

- hadoop 다운로드
http://hadoop.apache.org/core/releases.html

- 압축을 풀고 나서 conf/hadoop-env.sh 파일에 JAVA_HOME 설정

- bin/hadoop 한번 실행

- conf/hadoop-site.xml 편집
<configuration>
  <property>
    <name>fs.default.name</name>
    <value>localhost:9000</value>
  </property>
  <property>
    <name>mapred.job.tracker</name>
    <value>localhost:9001</value>
  </property>
</configuration>

- ssh-keygen 실행(localhost도 ssh를 이용하기때문에 설정해야함)
ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa
cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys


- DFS 포맷
bin/hadoop namenode -format


- example(그냥 싱글노드에서 동작)

bin/start-all.sh (hadoop daemon 실행)
bin/hadoop dfs -put conf input (conf 디렉토리에 있는 파일을 DFS에 input이라는 이름으로 copy)
bin/hadoop jar hadoop-*-examples.jar grep input output 'dfs[a-z.]+' (DFS input에 있는 파일 중에 'dfs[a-z.]+'에 매칭되는 문자열을 output에 저장)
bin/hadoop dfs -get output output  (DFS output에 있는 내용을 output 디렉토리에 저장)
cat outout/* (결과값 확인)
bin/stop-all.sh (hadoop daemon 중지)


참조 사이트(http://hadoop.apache.org/core/docs/current/quickstart.html)
Posted by pchun Trackback 0 Comment 0