(하둡) 자바 인터페이스

1. 하둡 URL로 데이터 읽기


하둡 파일 시스템에서 파일을 읽는 가장 쉬운 방법은 java.net.URL객체로 데이터를 읽는 스트림을 하나 여는 것이다.
자바가 하둡의 hdfs URL 스킴을 인식하기 위해서는 약간의 작업이 필요

이 작업은 FsUrlStreamHandlerFactory의 인스턴스와 함께 URL클래스의 setURLStreamHandlerFactory()메소드를 호출하여 수행된다.

이 메소드는 JVM하나당 한번씩만 호출할 수 있기 떄문에 일반적으로 정적 블록에서 실행된다.
이러한 한계는 프로그램의 일부 다른 부분 에서 URLStreamHandlerFactory를 설정하면 하둡URL로부터 데이터를 읽을 수 없게 됨을 의미한다.



2. 파일시스템 API로 데이터 읽기

앞에서 설명했듯이 애플리케이션에서 URLStreamHandlerFactory 설정이 불가능한 경우가 있다.
이떄는 파일에 대한 입력 스트림을 열기위해 FileSystem API를 사용해야한다.

하둡시스템의 파일은 하둡 Path객체로 표현된다.
여기서 Path는 hdfs:://localhost/user/tom/quangle.txt같은 하둡 파일 시스템 URL을 의미한다.

FileSystem은 일반적인 파일시스템 API로, 첫 단계는 접근할 파일시스템(여기서는HDFS)에 대한 인스턴스를 얻는 것이다.
FIleSystem인스턴스를 얻을 수 있는 정적 팩토리 메소드는 다음과같다.

public static FileSystem get(Configuration conf) throws IOException
public static FIleSystem get(URI uri, Configuration conf) throws IOException
public static FIleSystem get(URI uri, Configuration conf, String user) throws IOException

Configuration객체는 클라이언트나 서버의 환경 설정을 포함하고 있으며, 클래스 패스에 있는 etc/hadoop/core-site.xml과 같은 서정파일에서 관련 설정을 읽어들인다.

로컬 파일 시스템 인스턴스만 얻을 때는 getLocal()메소드를 사용하는 것이 가장 편리하다.

public static LocalFileSystem getLocal(Configuration conf) throws IOException

FileSystem 인스턴스를 얻으면  open()메소드를 호출하여 파일에 대한 입력 스트림을 열수 있다.

public FSDataInputStream open(Path f) throws IOException
public abstract FSDataInputStream open(Path f ,int bufferSize) throws IOException

첫번쨰 메소드는 4KB의 기본 버퍼 크기를 사용한다.

2-1. FSDataInputStream(읽기)


FileSystem의 open()메소드는 표준 java.io 클래스가 아닌 FSDataInputStream클래스를 반환한다.
이 클래스는 랜덤 접근을 지원하기 위해 java.io.DataInputStream을 특별히 변경한 것이며, 스트림의 어떤 부분이든 읽을 수 있다

public class FSDataInputStream extends DataInputStream implements Seekable, PositionedReadable {

}

Seekable 인터페이스는 파일에서 특정 위치로 이동하는 것을 허용하며, 파일의 시작점에서 현재 오프셋을 얻는 getPos()와 같은 쿼리 메소드를 제공한다.

public Interface Seekable {
 void seek(long pos) throws IOException;
 long getPos() throws IOException;
}

파일의 길이보다 더 큰 값을 seek() 메소드를 호출하면 IOException 을 일으킨다. 현재 위치에서 뒤로 스트림의 위치를 이동시키는 java.io.InputStream클래스의 skip()메소드와 달리 seek() 메소드는 파일에서 임의 위치나 절대 위치로 이동할 수 있다.

또한 FSDataInputStream 역시 주어진 오프셋에서 파일의 일부를 읽기위한 PositionedReadable인터페이스를 제공한다.

public interface PositionedReadable {

 public int read(long position, byte[] buffer, int offset, int length) throws IOException;
 public void readFully(long position, byte[] buffer, int offset, int length) throws IOException;
 public void readFully(long position, byte[] buffer) throws IOException;

}

read()메소드는 파일의 주어진 position에서 length만큼 바이트를 읽어서 buffer의 주어진 offset에 그내용을 복사한다. 반환값을 실제로 읽은 바이트 크기다.

이러한 모든 메소드는 파일의 현재 오프셋을 유지하고 스레드 안전을 지원한다(동시접속을 고려하여 FSDataInputStream을 설계하지 않았기 떄문에 다중 인스턴스를 생성하는 방법을 권장한다)
따라서 파일 전체를 읽는 중이더라도 메타데이터와 같은 파일의 다른 부분에 쉽게 접근 할 수 있다.

seek()메소드를 호출하는 것은 상대적으로 비용이 많이 드는 연산이므로 꼭 필요할 떄만 사용해야 한다.
애플리케이션이 다수의 seek()메소드를 수행하는 방식이 아닌 맵리듀스와 같은 스트리밍 데이터 기반의 접근 패턴을 사용하도록 구조화하라.

2-2. FSDataOutputStream(쓰기)

FileSystem 클래스의 create() 메소드는 FSDataOutputStream을 반환하는데, FSDataInputStream과 같이 파일에서 현재 위치를 얻기 위한 메소드를 지원한다.

public class FSDataOutputStream extends DataOutputStream implements Syncable {

}

FSDataInputStream과 달리 파일탐색 seek()기능을 제공하지 않는다.
HDFS는 열려있는 파일에는 순차쓰기를, 기존파일에는 추가연산만 지원하기 떄문이다.

다시말해, 파일의 끝 이외 다른 부분에 쓰는 것은 지원하지 않으므로, 쓰는 중에 탐색은 불가능하다.


3. 디렉토리


public boolean mkdirs(Path f) throws IOException

이 메소드는 java.io.File의 mkdirs()메소드처럼 존재하지 않은 모든 부모 디렉토리를 생성한다.


4. 파일시스템 질의





댓글

이 블로그의 인기 게시물

(18장) WebSocekt과 STOMP를 사용하여 메시징하기

(네트워크)폴링방식 vs 롱 폴링방식

(ElasticSearch) 결과에서 순서 정렬