2015-08-26


- 장강명 -"한국이 싫어서"

 : 9


자기 개발서이자, 성공 유학기 같은 소설,
신문기자 출신의 작가라서 그런지 남자 작가 임에도 불구하고 여성의 화자를 
취재 만으로 잘 써냈다.

큰 스토리 라인을 가지지 않고 짧은 양만큼 빨리 읽을수 있으며,
느끼는 바 또한 크지만...

한국 문학계가 좋아 한다는 문학성은 별로 찾을수 없었다.
아님 내가 모르는건지~.

그래도 재미있게 잘 읽었고,
현재의 나를 돌아 볼수 있는 계기가 되었다.



2015-08-20

JAVA Thread 와 unable to create new native thread



상황

리눅스에서 java로 만든 multi thread 프로그램을 동작 시키고 있는데, java.lang.OutOfMemoryError: unable to create new native thread 가 발생.
JVM 이 죽는다.


Java Thread  종류

1. 데몬 스레드(Daemon Thread)
데몬 스레드는 다른 비데몬 스레드가 없다면 동작을 중지한다.
가비지 컬렉션 같은 것들이다.

2. 비데몬 스레드(Non-daemon Thread)
보통 class에서 실행하는 main은 비데몬 스레드이다.
main같은 비데몬 스레드가 일반적으로 Stack 을 보면 thread in VM 으로 표현되고
VM Thread 라고 한다.
비슷하게 일반 로직이 아닌 JVM 의 native 기능을 사용하는 thread를 Thread In Native 라고 하며 Native Thread 라고 한다.
일반적으로 socket, rmi관련 thread를 들수 있다.


원인

크게 두가지 원인으로 나눌수 있다.
1. 리눅스에서 MAX thread 개수를 넘어서 Thread를 생성 하려 할때.
2. OS 에서 Thread 생성에 필요한 메모리를 실제로 할당해주지 못할때.

위 두가지 상황 모드 정상인 상황은 아니다.

Linux MAX thread 수 확인 법
하여간에  일반적으로 java thread는 linux의 ps 명령등으로 확인이 불가능하다.
즉 개별 프로세스로 보이지도 않고 커널 쓰레드도 아니다.
확인 하려면 시스템 설정을 조회해야 한다.




조회방법
cat /proc/sys/kernel/threads-max
설정 방법 echo 1000 > /proc/sys/kernel/threads-max

* 실제로 1000 개하면 몇만개 이상 되어야 한다.


프로세스당 Thread 수 확인법

조회방법
ps -eLo pid,cmd,nlwp

결과
PID CMD                         NLWP
    1 /sbin/init                     1
    2 [kthreadd]                     1
    3 [migration/0]                  1
58651 /usr/java/jdk1.8.0_05/bin/j  144

여기 결과값 NLWP가 number of light weight process의 약자로 java thread 의 수이다.
커널 쓰레드도 1로 표시된다.
위는 jdk의 프로그램이 144개의 쓰레드를 생성 했다는 의미이다.


java 에서성 할수 있는 프로세스 확인

public class test
{
   public static void main(String[] args)
    {
        int cnt = 0;
        while(true){
            cnt++;
                System.out.println("cnt:" + cnt);
            new Thread(new Runnable(){
                public void run() {
                    try {
                        Thread.sleep(10000000);
                    } catch(InterruptedException e) { e.printStackTrace();}    
                }
            }).start();
        }
    }
}


위 프로그램 을 실제 동작 시키면  플래폼에 따라 생성 개수의 차이가 발생한다.
32bit JVM 의 경우 약 9000개 64jvm의 경우 약 34000개 정도 까지 무난히 생성된다.

이는 JVM 프로세스가 관리하는 스택 저장 공간의 사이즈와 연결되는데
java 실행시 -Xss 옵션으로 스택의 사이즈를 지정하면 된다.
(-Xss128k) 옵션을 너무 작게 주면 최소 값 얼마 이상 주라고나오는데 32bit는 100k 64bit는 160k 이다. 기본값은 128k 라고 한다.


따라서 리눅스에서 max thread 생성 개수가 남아 있더라도 ,
stack 에 의해서 thread 의 생성에 java는 제한을 가지게 된다.



해결
java.lang.OutOfMemoryError: unable to create new native thread가 발생하면
위에 쭉 언급한 바와 같이 실제 메모리 문제라기 보다는 쓰레드의 생성 개수 제한 떄문이 가능서이 조금더 높다.


1. ulimit -a  명령으로 프로세스당 메모리 사용제한 양을 확인 하고 조치 한다.
2. 리눅스의 max thread 수를 늘린다.
3. java thread stack size 크기를 줄인다.
4. 실제 물리 메모리를 늘린다.
5. 사실은 제일 먼저 엄한 Thread를 생성하고 있지는 않은지  확인 한다.

등으로 조치한다.

참고
heap 메모리의 부족과는 상관없다.
이 에러는 java 메모리의 Stack 메모리 부분에서 발생한다.


Linux Thread Architecture

Linux Thread



.




Linux Thread란

Linux에서  일반적으로  <pthread.h> 를 구현한 프로그램을 의미하며, process와 달리 fork()를 통해 생성하지 않는다. 또한, Thread들간 주소 영역을 공유하기 때문에 Thread들간 통신 구현이 간단하며, Context Switching이 발생하지 않아 부담이 적다.
그리고 Process를 통해 구현되며, 하나의 Process에 종속적이다.
State가 없고. 실행과 종료만이 있다.
LWP(Light Weight Process) 라고도 한다.

Linux Thread 종류

  1. User Level Thread

  • Thread Scheduling 이  Process 내부에서 처리 되는 Thread.
  • OS 의 Scheduling 에 개별 쓰레드를 등록할 필요가 없다.
  • Pthread 생성시 “PTHREAD_SCOPE_SYSTEM” 인자를 가지는 Thread.
  • Kernel 2.4 이전에는 복수의 user thread가 1개의 kernel Thread에서 동작.
  • Kernel Procedure  및 OS Scheduling 의 영향을 받지 않아 kernel level thread 보다 백배이상 빠르다.
  • 하나의 Process로 인식해 ,개별 Thread를 확인 할수 없다.(OS는 모른다)
  • 개별 Thread는 non blocking 구현이 필요하다. block되면 process전체가 멈추게 된다.
  • user mode에서 동작한다.
  1. Kernel Level Thread

  • OS 상의 Scheduling 을 통해 동작하는 Thread.(OS의 scheduling 에 접근하기 위해서는 Kernel 의 time signal을 받아야 하기 때문이라고 한다.)
  • OS 상에서 확인이 가능하다.

  • ps -ef 조회시 대괄호 “[]”에 둘러 싸여 있거나, PPID가 2인 녀석이 kernel thread이다.

root      2989     2  0 04:26 ?        00:00:00 [drbd1_worker]
root      3012     2  0 04:26 ?        00:00:00 [drbd1_receiver]

  • Signal 처리를 구현해야 한다.
  • Full thread control block (TCB) 이 필요하다.
  • Kernle mode에서 동작한다.

Thread Process 종류

  1. Single Thread Process

  1. Multi Thread Process

User- Kernal Thread Maping

  1. N:1 Threading Model (User-level Threading)


  • Kernel Thread를 지원하지 않는 시스템에서 사용.

  1. 1:1 Threading Model (Kernel-level Threading)


  • Windows 98/NT/2000/XP, OS/2, Linux이 해당됨.
  • 결국 모든 Thead 동작이 Kernel Thread로 구현 동작된다.
  • 모든 Thread가 OS에 의해 Scheduling된다.
  1. M:N Threading Model (Hybrid Threading)


  • 효율적인 kernel thread 구성 및 유지 가능
  • 1:1, N:1 매핑의 장점을 조합.
  • 유연하지만, 구현이 복잡함.
  • Solaris v9 후속, IRIX, HP-UX

2015-08-09

파리채의 진화


사건 사고가 많은 세상이지만, 상상하던 모든 것들이 하나씩 이루어 지고 있다.
크게는 스마트폰 부터 작게는 파리채 까지 세상은 발전하고 있다.

그런 의미에서 아무도 돌아 보지 않을듯한 영역에서의 의외의 발견은 놀라웠다.
늘어나는 파리채라니..






2015-08-05

DRBD stacked resource 구성

DRBD stacked resource 구성
ver: DRBD 8.3.13




리눅스에서 drbd 설치 바로가기

구성도

총3개의 호스트를 기반으로 stacked 복제 리소스를 구성한 그림이다.
DRBD8 버전은 3노드와 4노드의 복제 방식을 명확하게 제안 하고 있다.
밑의 구성도는 그중에 3노드 구성에 대한 그림이다.


추가:
drbd9 버전 부터는 4노드 이상의 복수 노드에 대해서 stacked 리소스의 구성 없이 N:N 구성으로 복제 리소스를 구성 할 수 있다.






환경 설정

기본 환경 구성 파일이다.
import 방식이 아닌 전체 drbd.conf 파일을 저장한다. 또한, 3노드를 구성하는 모든 호스트에 동일한 설정 파일이 존재해야 한다.


global {
    usage-count no;
    disable-ip-verification;
}
common {
    startup {
            wfc-timeout 1;
    }
}
resource r0 {
    protocol     B;
    on hostA {
                               address 10.10.10.1:7788;         ----------------> 1
            disk /dev/sdb1;
            flexible-meta-disk internal;
            device  /dev/drbd0;
    }
    on hostB{
                               address 10.10.10.2:7788;
            disk /dev/sdb1;
            flexible-meta-disk internal;
            device  /dev/drbd0;
    }
}               
resource r0_1 {
              protocol A;
              meta-disk internal;
              stacked-on-top-of r0 {
                               device /dev/drbd10;           ----------------> 2
                               address 10.10.10.1:7789;
              }
              on hostC {
                               device   /dev/drbd10;
                               disk      /dev/sdb1;
                               address 10.10.10.3:7789;
                               meta-disk internal;        ----------------> 3
                               }
              }
}


  1. 호스트 A와 B 사이의 구성은 일반 복제 리소스 구성과 완전히 동일하다.
    하지만 제 3 노드인 호스트 C 는 호스트 A에서 복제 된다 ( 호스트 A가 primary라고 가정한다). 따라서 stacked 리소스 r0_1은 address가 호스트 A의 주소와 같다.
    별개의 네트워크 라인/포트를 가진다. 즉 완전히 별개의 라인으로 취급된다.


추가:
실제 구성에서는 호스트 B가 primary 가 될경우 10.10.10.1이라는 주소가 없기 때문에 데이터를 보낼 수  없다.
다라서 Stacked된 대상 리소스 ( 여기서는 r0) 의 리소스는 완전히 분리되어야 하며
호스트 A와 호스트 B에서 동시에 사용할수 있는 가상 IP(VIP) 여야 한다.


  1. 위에서 언급 한 것과 같이 호스트 A-B와 호스트 A-C가 완전히 별개의 라인이기 때문에 drbd에서 취급 하는 가상 디바이스 인덱스도 분리되어야 한다.
  2. Stacked구조의 target 리소스는 Internal 메타 데이터를 사용해야만 한다.
    그래야만 하나의 볼륨에 메타 데이터 정보를 포함 시킬수 있다.



생성 명령

호스트 A,B,C에 drbd.conf를 작성 후, service를 재 시작 한다.


  1.  먼저 호스트 A 에서 메타 데이터 생성

    drbdadm create-md r0
  2. 호스트 B에서 메타 데이터 생성

    drbdadm create-md r0
  3. 호스트 A에서 리소스 활성화 및 Stacked 리소스 메타 데이터 생성

    drbdadm up r0
    drbdadm -- --overwrite-data-of-peer primary r0
    >> 이 과정에서 동기화 진행
    drbdadm create-md --stacked r0-U
  4. 호스트 C에서 메타 데이터 생성

    drbdadm create-md r0-U
    service drbd start 혹은 drbdadm adjust r0 혹은 필요 없다.
  5. 호스트 A에서 stacked 리소스 활성화

    drbdadm up --stacked r0-U
    drbdadm primary --stacked r0-U
    drbdadm --stacked -- --overwrite-data-of-peer primary r0-U
    >> 이 과정에서 동기화 진행
    mount /dev/drbd10 /mountpoint


추가:
일반 복제 리소스 r0와 stacked리소스 r0_1 에 대해 두번 풀싱크를 별도로 해줘야 한다.
또한 Stacked 리소스가 primary가 되기 위해서는 r0리소스가 primary여야 한다.


사용


  1. 먼저 일반 리소스 r0를 primary 로 승격 시킨다.

    drbdadm primary r0
  2. stacked 리소스 r0_1을 활성화 한다.

    drbdadm up --stacked r0_1
  3. stacked 리소스 r0_1을 primary 로 승격 시킨다.

    drbdadm primary --stacked r0_1
  4. 볼륨 I/O를 하기 위해서 Stacked r0_1 리소스의 가상 장치를 os에 마운트 한다.

    mount /dev/drbd10 /mnt
    >> 이 과정 전에 primary 상태에서 format이 필요할  수 있다..
         
  5. 사용이 끝나면 반대의 순서로 drbd 리소스를 비 활성화 한다.