엘라스틱서치(ES)를 IDE에서 띄어보자!
엘라스틱서치(이하 ES)를 회사에서 사용하고 공부하며 조금 더 심도있게 소스를 들여다 보고 싶다는 생각이 들었습니다.
이 생각이 확장되어 오픈소스를 분석하면서 실제로 동작이 맞는지 확인해보고자 로컬에서 ES를 띄워야겠다고 이어졌습니다.
(오픈소스 분석방법에도 나와있는 내용을 동감합니다.)
이 과정에서 ES를 로컬에서 효율적으로 띄우는 방법을 정리하여 포스팅 합니다.
Gradle 2.13 설치
ES 공식 Github 링크에 나와있는 것처럼 ES 빌드시에는 반드시 Gradle 2.13이 설치되어 있어야 한다.
이 포스팅에서는 Gradle에 대한 설명이나 설치방법은 생략한다.
단, 아래글 최소한의 도움을 주기 위해 설명하자면 어떤 경로에서든 아래의 명령어를 호출 했을 때 아래와 같이 2.13버전이 명시되면 정상적으로 Gradle을 설치한 것으로 볼 수 있다.
태그 확인 하기
ES는 릴리즈한 소스코드는 Tags로 관리하고 있고 Github에서 확인해보면 현재기준 최신버전인 v5.1.1 태그도 존재함을 알 수 있다.
이번 글에서는 이왕이면 최신버전인 v5.1.1을 사용할 계획이다.
Github에서 소스 clone 하기
ES 공식 repository에서 최신 소스를 clone 받는다.
1 2
$ git clone https://github.com/elastic/elasticsearch $ cd elasticsearch
로컬에서 브랜치 전환하기
로컬에서 아래의 명령어로 "v511" 브랜치를 생성하고 코드는 "v5.1.1"의 태그로 맞춘다. "git branch" 명령어를 통해 실제로 브랜치가 전환되었는지 확인 할 수 있다.
(브랜치명을 굳이 v511로 한 이유는 아래의 명령어에서 브랜치명과 태그명 자리를 분리하기 위해서이다.)
1 2
$ git checkout -b v511 v5.1.1 $ git branch
IDE에 맞게끔 Gradle 사전빌드 하기
ES는 국내에서 많이 쓰는 이클립스, 인텔리J에 맞게 IDE가 필요한 프로젝트 관련 파일들을 생성해주는 Gradle 명령어가 존재한다.
이부분을 이용하면 IDE에서 Gradle 프로젝트를 불러오고 빌드하는 과정의 트러블슈팅을 최소화 할 수 있다.
필자는 IntelliJ를 사용하므로 아래와 같이 입력하여 사전빌드를 수행한다.
1 2
$ gradle idea # 엘라스틱서치 소스 경로에서 실행 $ gradle eclipse # 이클립스 사용자는 위의 명령어가 아니라 이 명령어를 실행하면 됨
IDE에서 ES 프로젝트 불러오기
프로젝트 File -> Open으로 ES 소스경로의 build.gradle을 지정하여 OK버튼을 누른다.
Open as Project를 선택한다.
OK버튼을 누른다.
이미 인텔리J에서 필요한 파일이 존재한다고 나옵니다. Open Existing Project를 선택한다.
OK버튼을 누른다.
ES 버전 확인해보기
ES가 실제로 5.5.1버전으로 동작하는게 맞는지 확인하기 위해 Version.java를 열어 CURRENT 변수를 확인해 본다.
CURRENT 변수는 현재의 ES 버전을 정의하는 변수로써 5.1.1로 명시되어 있는것을 알 수 있다.
ES 실행하기
터미널 혹은 인텔리J의 메뉴를 통해 gradle로 ES를 실행시킬수 있다.
1 2
$ cd elasticsearch $ gradle run#start
하지만 해당 방법은 경험상 아래와 같은 아쉬운 점을 가지고 있다.
- Gradle Run#start를 수행하는 속도가 빠르지만은 않다. => 소스코드 수정/재시작 시 시간 소모가 많다.
- 콘솔 출력이 IDE 기준으로는 출력되지 않고 터미널 기준으로 출력시에는 문자열 검색이 불편하다.
- IDE를 통한 Break Point를 사용하고 싶어도 방법이 없다.
- IDE 내에서 수정/실행/로그검색이 All-In-One으로 이루어 지지 않는다.
- 색인 데이터가 저장되지 않고 재시작 시 마다 초기화 된다. (어떤 이에게는 장점이 될수도 있지만 이런 목적이라면 ES TC가 더 적합할 듯 하다.)
필자가 사용하는 ES 실행 방법
필자가 실행하는 방법은 위의 단점들을 보완한 방법이다.
결론부터 얘기하자면 ES 소스 + ES 배포판을 활용하여 IDE 실행환경을 구축하는 것이다.
부연설명을 하자면 ES 노드는 소스코드를 기반으로 띄우고 ES 실행 home을 배포판 경로로 지정하여 config, data 등의 정보는 배포판 경로의 것을 사용하는 것이다.
해당 방법은 아래와 같은 보완점을 가진다.
- Gradle 대비 더 빠른 구동속도 (IDE 컴파일 + 실행만 하기 때문, core module만 빌드하기 때문)
- Break Point 사용가능
- IDE 환경에서 코드 보기, 수정, 실행, 디버깅이 All-In-One으로 가능
- 실제 ES 데이터를 연동하여 구동 가능 => 재시작 시에도 데이터 유지
해당 방법으로 실행하는 STEP을 설명한다.
우선 ES 5.1.1버전을 다운로드 받아 필요한 설정파일을 바꾼다.
1 2 3 4 5
$ wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.1.1.tar.gz $ tar xzvf elasticsearch-5.1.1.tar.gz $ cd elasticsearch-5.1.1 $ cd config $ vi elasticsearch.yml
elasticsearch.yml 에서는 cluster.name을 popit으로 바꾼다.
1
cluster.name: popit
ES 소스의 구동 원리는 Elasticsearch.java의 static void main(String[] args)를 실행하는 것이다. 이때 필요한 옵션은 ES의 home path를 지정하는 것과 jvm security exception을 피하기 위해 log4j jmx기능을 끈다.
home path를 지정하게 되면 해당 home path의 config/elasticsearch.yml을 읽어 클러스터 이름이나 data의 경로등을 가져온다.
방금 만든 ES 실행 설정을 실행해보면 아래와 같이 IDE 내 콘솔로그에서 ES가 동작한다.
실제 ES가 정상적으로 구동되었는지 로그로 확인해도 되지만 알기쉽게 CURL을 호출해보면 우리가 만들었던 클러스터 이름 "popit" 으로 노드가 시작된것을 알 수 있다.
앞서 언급했듯이 로컬 개발환경과 ES 배포판은 config를 공유하기 때문에 데이터도 동일하게 사용 할 수 있다. 또한 ES를 재시작 하더라도 데이터가 초기화 되지 않는다.
필자의 경우 ES 토이 프로젝트로 어플리케이션을 만들어보고 이 데이터를 통해 다시 소스코드를 분석하니 소스를 좀 더 피부에 와닿게(?) 익히는데 도움이 되었다.
검증(소스 수정해서 찍어보기)
이제 할일은 ES 소스 분석에 시간을 투자하고 실제 실행 순서등을 따라가보고 궁금한 것을 콘솔에 찍어보는 일이다.
실제로 소스 변경 된것이 IDE에 찍히는지 검증, 예제를 보여주기 위해 가장 간단한 아래의 커맨드 시에 ES에 관련 소스 로그를 찍어보겠다.
1
$ curl localhost:9200
해당 Request를 처리하는 ES의 소소 부분은 RestMainAction으로써 여기의 prepareRequest()에서 Request를 처리한다. 여기에 logger로 "RestMainAction.prepareRequest()"를 찍어본다.
자세한 동작원리나 코드에 대한 설명은 차후 포스팅 예정이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
public class RestMainAction extends BaseRestHandler { @Inject public RestMainAction(Settings settings, RestController controller) { super(settings); controller.registerHandler(GET, "/", this); controller.registerHandler(HEAD, "/", this); } @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { logger.info("이렇게 찍으면 로그에 나옵니다."); // 추가된 코드 return channel -> client.execute(MainAction.INSTANCE, new MainRequest(), new RestBuilderListener<MainResponse>(channel) { @Override public RestResponse buildResponse(MainResponse mainResponse, XContentBuilder builder) throws Exception { return convertMainResponse(mainResponse, request, builder); } }); } // ... 생략 }
소스 수정 후 다시 ES를 재기동 하여 아래 명령어를 터미널에서 실행해본다.
1
curl localhost:9200
아래와 같이 "RestMainAction.prepareRequest()" 로그가 추가로 찍힌것을 확인 할 수 있다.