MINA에서 버퍼 제어하기 - IoBuffer
IoBuffer
IoBuffer는 MINA 어플리케이션에서 사용되는 Byte Buffer를 말하는데 NIO의 ByteBuffer
- fill, get/putString 그리고 get/putAsciiInt() 와 같은 유용한 getter/setter 메소드를 제공하지 않는다.
- ByteBuffer 의 허용크기가 가변길이 데이터를 저장하기에 충분하지 않다
IoBuffer는 앞서 말했지만 MINA에서 NIO ByteBuffer를 대체하는 클래스입니다. 그 이유는 버퍼의 확장을 쉽게 하기 위해서인데요.
좀더 자세히 말하자면 MINA 에서 IO를 최소화하기 위해 데이터를 한번만 읽어 모든 처리를 하자는 취지에서 만들어진 것 같습니다.
한마디로 소켓으로부터 받은 데이터를 버퍼에 담아 한번에 처리하겠다는 것인데요 .
문제는 고정길이가 아닌 가변길이의 데이타가 전송되는 경우 버퍼크기를 초과하는 데이터를 처리하기가 쉽지 않다는 것이었습니다.
그래서 버퍼의 확장이 쉽도록 구현된 대체 클래스인 셈이죠. 하지만 메모리 관리방법을 JVM내 객체가 저장되는 공간인 Heap 영역이 아닌 일반메모리상에서 직접 접근할 수 있는 버퍼영역인 Direct Buffer를 사용하는 경우에 문제가 발생하게 됩니다.
즉 Buffer의 데이터에 다른 프로그램으로 직접 접근할 수 있다는 보안상의 결함을 가지고 있다는 것이죠.
따라서 MINA3 버젼부터는 변경할 예정이라고 하네요.(원문 참조, Direct Buffer가 아닌 Heap 버퍼 사용을 권장함)
MINA에서 IoBuffer를 사용하는 방법
IoBuffer 는 추상클래스입니다, 따라서 직접 인스턴스화 할 수는 없습니다. IoBuffer를 할당하기 위해서 우리는 두개의 allocate() 메소드 중 하나를 사용해야 합니다.
- public static IoBuffer allocate(int capacity, boolean direct)
- public static IoBuffer allocate(int capacity)
위에서 처럼 allocate() 메소드는 하나 또는 두개의 인자를 가집니다. :
- capacity – 버퍼 크기
- direct – 버퍼 유형. direct buffer를 얻기 위해서는 true, heap buffer는 false
기본적으로 버퍼의 할당은 SimpleBufferAllocator
- IoBuffer.setUseDirectBuffer(false);
- IoBuffer buf = IoBuffer.allocate(1024);
즉 기본값으로 Heap버퍼를 사용하는 것으로 설정한 후 새로운 Heap 버퍼로 반환하는 것입니다. 이 방법을 사용하기 전에 주의할 점은 기본 버퍼유형을 설정해야 한다는 것입니다. 그래야만 Heap 버퍼를 사용하게 됩니다.(앞서 말한 이유로...)
- SimpleBufferAllocator(기본값) - 매번 새로운 버퍼를 생성한다
- CachedBufferAllocator - 확장시 재사용가능한 버퍼영역을 캐싱한다.
예제
먼저 자동으로 버퍼를 확장하는 방법에 대한 예제 입니다. IoBuffer는 autoExpand라는 프로퍼티를 이용하여 버퍼크기와 한계치를 자동으로 확장할수 있습니다.
IoBuffer buffer = IoBuffer.allocate(8);
buffer.setAutoExpand(true);
buffer.putString("12345678",encoder);
//버퍼에 추가
buffer.put((byte)10);
버퍼를 증가시키는 것은 어렵지 않습니다. 마치 StringBuffer 를 통해서 문자열을 추가하듯이 버퍼에 put메소드를 사용하면 자동적으로 증가가 됩니다.
지속적으로 버퍼가 증가만 된다면 문제겠죠. 메모리자원을 보존하기 위해 추가할당된 byte 들을 삭제하도록 요청할 필요가 있습니다. 이러한 요구에 따라 autoShrink 프로퍼티를 지원하고 있는데요. autoExpand 와는 반대의 개념으로 compact() 메소드가 호출되면 버퍼의 크기를 절반 또는 현재 할당된 영역의 4분지1이하의 크기로 줄일 수 있습니다. 다음은 버퍼 크기를 수동으로 줄이는 예제입니다.
IoBuffer buffer = IoBuffer.allocate(8);buffer.setAutoExpand(true);
buffer.put((byte)1);
System.out.println("기본 버퍼 크기 = "+buffer.capacity());
buffer.shrink();
System.out.println(" shrink 이후 기본 버퍼 크기 = "+buffer.capacity());
buffer.capacity(32);
System.out.println("버퍼 크기를 32로 증가시킨 결과 = "+buffer.capacity());
buffer.shrink();
System.out.println("shrink 이후 버퍼 크기 = "+buffer.capacity());
결과
기본 버퍼 크기 = 16 // 버퍼 크기가 16인 버퍼 생성. 즉 버퍼의 최소용량을 16으로 설정
shrink 후 기본버퍼 크기 = 16 // shrink() 호출 . 하지만 최소영역 이하로 줄일수 없습니다. 16
버퍼크기를 32로 증가시킨 결과 = 32 // 버퍼의 최대크기를 32로 늘임. 버퍼용량 32
shrink 이후 버퍼크기 =16 // shrink() 호출. 기본최소용량인 16으로 버퍼크기를 줄임
버퍼크기를 수동으로 줄이고자할때 shrink()를 사용하고 있지만 버퍼의 크기를 줄이기 위해 이 예제에서처럼 명시적으로 요청할 필요는 없습니다.
앞서 말한바와 같이 autoShrink 프로퍼티를 설정하면 자동적으로 메모리자원을 확보하기 위해 추가된 버퍼를 삭제할 수 있습니다.
이 글은 http://mina.apache.org/iobuffer.html 를 참고하여 작성되었구요.
좀더 상세하게 설명되어 있는 번역문은 pdf파일로 첨부하였습니다만. 언제나 그렇듯이 번역상태는 ....-_-a
'개발 이야기 > MINA' 카테고리의 다른 글
[MINA] Logging Configuration (0) | 2009.11.30 |
---|---|
MINA 기반의 어플리케이션 구조 (0) | 2009.05.28 |
MINA 2.0 에코서버 만들기 (0) | 2009.05.21 |