zeppelin (제플린) 설치 및 튜토리얼

이미지가 안나오는 관계로 http://blog.wonwoo.ml/wordPress/1401 여기로 오면 보입니다. 워드프레스 빨랑 버려야지. 요즘들어 엄청 느려졌네.

개인적으로 제플린을 사용해 볼까 해서 일단 설치를 해봤다. 물론 정말로 사용할지(?) 하지 않을지(?)는 모르겠으나 설사 지금은 사용 하지 않는다 하더라도 나중에 혹시 사용하게 될지도 모르니 일단 해보자.

요즘 우리나라 오픈소스들이 많이 등장했다. 특히 우리가 잘 알고 있는 아파치 재단에도 많은 프로젝트가 top level로 올라가 있다. 예를들어 apache mina, apache tajo ,apache hama 등이 있고 오늘 간단하게나마 알아볼 zeppelin도 그 중 한개의 프로젝트이다. 제플린은 top level 프로젝트로 올라간지는 얼마 되지 않았다. 내기억이 맞다면 올해(2016년)에 올라간 걸로 기억한다. mina는 뭐 워낙 유명한분이 만드셔서.. mina보다는 netty로 더 유명한가? tojo 경우에는 고려대학교 컴퓨터학과 연구실에서 시작된 프로젝트이다. hama는 잘…모르겠다.. 자세한건 인터넷으로..
아무튼 뜬금없이 우리나가 오픈소스를 살펴봤다. 우리나라에도 대단한분들이 아주 많다.

제플린은 Apache Spark을 기반으로 한 시각화 툴이다. UI에서 코딩도 할 수 있고 sql도 날리면서 데이터를 시각화해서 보여주는 그런 프로젝트이다. 말로는 감이 잘 오지 않을 수도 있으니 설치부터 해보자.

mac 기준이지만 window도 지원한다고 하니 많이는 상관없을 듯하다.
https://zeppelin.apache.org/download.html 제플린 다운로드 페이지다. 필자의 경우에는 Binary package with all interpreters 을 다운받았다. 물론 github가서 빌드해도 상관 없으나 필자는 그냥 다운 받기로 했다. 용량이 꽤 크다. 다운받은 파일을 압축을 풀자.

그리고 제플린 root 폴더로 가서 bin/zeppelin-daemon.sh start 실행 시키자. 기본 포트는 8080인데 8080은 우리가 was 서버로 잘 활용하니 바꾸고 싶다면 conf/zeppelin-site.xml.templatezeppelin-site.xml 복사하고 아래 부분을 수정해주면 된다.

 //...
<property>
  <name>zeppelin.server.port</name>
  <value>8080</value>
  <description>Server port.</description>
</property>
//...

필자는 일단 그냥 개인 컴퓨터에서 하기에 8080포트로 사용했다. 그럼 UI를 살펴보자.
http://localhost:8080 으로 접속하면 아래와 같이 괜찮은 화면이 나올 것이다.

zp1

화면도 나쁘지 않다. 우리는 처음이니까 Create new note 버튼을 눌러서 note를 만들자. 만약 다른사람이 작업한게 있다면 import 해도 된다. 또한 공유도 된다고 들었는데.. 그래서 막 실시간으로 반영되고 그랬던 걸로 기억한다. 아무튼 우리는 Create new note 버튼을 눌러서 note 명을 자유롭게 지정해주자.

zp2

첫 화면은 위와 같다. 휑하다. 뭘해야 될지도 모르겠다면 우리에게 튜토리얼이 있다.
https://zeppelin.apache.org/docs/0.6.2/quickstart/tutorial.html 여기에 가면 튜토리얼이 있으니 참고하길 바란다. 물론 필자도 이거 보고 따라서 할 거다.
위의 페이지에 가면 bank.zip 이라는 압축파일을 다운로드 받을 수 있으니 일단 다운받자.
그리고 제플린 화면에서 아래와 같이 입력하자.

val bankText = sc.textFile("/Users/wonwoo/Downloads/bank/bank-full.csv")

case class Bank(age:Integer, job:String, marital : String, education : String, balance : Integer)

// split each line, filter out header (starts with "age"), and map it into Bank case class
val bank = bankText.map(s=>s.split(";")).filter(s=>s(0)!="\"age\"").map(
    s=>Bank(s(0).toInt, 
            s(1).replaceAll("\"", ""),
            s(2).replaceAll("\"", ""),
            s(3).replaceAll("\"", ""),
            s(5).replaceAll("\"", "").toInt
        )
)

// convert to DataFrame and create temporal table
bank.toDF().registerTempTable("bank")

스칼라를 모른다면 그냥 저런게 있다고 알자. 필자도 스칼라를 아주 잘알지는 못한다. 예전에 공부좀 했었는데 다 까먹. 아무튼 이런식으로 코딩할 수 도 있다. sc.textFile 안에는 아까 다운받은 zip 파일 압축을 푼후에 경로를 입력해주자. 거기에는 어떤 형식으로 된 text 문자열이 들어 있다.
경로를 입력하고 난 뒤 우측에 있는 run버튼을 누르자.

zp3

처음에는 시간이 조금 걸린다. 필자 컴터가 구려서 그런가? 아무튼 완료가 되었다면 아래와 같은 화면이 나온다.

zp4

나머지는 데이터를 가공하는 작업이고 마지막에 있는 bank.toDF().registerTempTable("bank") 이 코드는 temp 테이블을 만드는 작업을 한거다. 일반적으로 우리가 아는 db의 table이라고 생각하면된다.

우리가 한 작업 아래에 보면 다시 입력할 수 있게 필드가 생긴다. 이제부터는 테이블을 만들었으니 sql을 날려보자.

%sql 
select 
  age, count(1) 
from 
  bank 
where 
  age < 30 
group by 
  age 
order by 
  age

우리가 흔히 쓰던 쿼리문이다. 위와 같이 입력후에 다시 run버튼을 눌러보자.
zp5

그럼 위와 같이 테이블이 먼저 보일 것이다. 이것만 있으면 재미 없다. 바로 아래에 있는 차트 버튼들을 눌러보자.
그럼 아래와 같은 이쁜 차트들이 보일 것이다.

zp6

zp7

zp8

실제로 요즘 대학교 경영학에서는 기초 쿼리문을 알려준다는 이야기가 있다. (물론 어디서 들었던거다.) 맨 처음에 했던 코딩 작업은 개발자들이 해주고 나머지 기초 쿼리문은 데이터를 다루는 사람이 직접 원하는 쿼리문을 날려서 값들을 확인한다고 한다. 물론 쉽지 않은건 개발자들이 해주는 것도 나쁘지 않다.

위의 작업은 단순하고 정적인 작업들이다. 만약 위의 쿼리에서 나이가 20살 보다 작은 사람만 찾고 싶을 떄에는 쿼리문을 고쳐야 된다. 하지만 우리는 그럴필요 없다. 아래와 같이 해보자.

%sql 
select 
  age, count(1) 
from 
  bank 
where 
  age < ${maxAge=30} 
group by 
  age 
order by 
  age

위와 같이 입력해서 실행 한다면 뜬금없이 input box가 생겨난다. 거기에서 우리가 원하는 입력 값을 입력후에 실행 하면 된다.

%sql 
select
 age, count(1) 
from 
  bank 
where 
  marital="${marital=single,single|divorced|married}" 
group by 
  age 
order by 
  age

위의 예제도 입력하여 실행 시켜 보자. 그러면 select box가 생겨난다. 셀렉트 박스도 이것저것 선택하여 바꿔보자. 이건 실시간으로 바뀌네?
이런식으로 원하는 데이터를 마음껏 커스터마이징해서 시각화 할 수 있다. 아주 괜찮은 아이다.
조금만더 살펴보자.

이번에는 동적으로 field를 선택해보자. 아래와 같이 입력하면 체크박스가 나온다.

%sql
select  
  ${checkbox:fields=age|job|marital|education|balance,age|job|marital|education|balance} 
from 
  bank
limit 
  100

원하는 체크 박스를 클릭 후에 run을 해보자. 그럼 체크된 필드만 목록에 보인다. 체크박스도 이것저것 체크해서 살펴보자. 사용자가 계속 쿼리문을 바꿔가며 할 필요 없이 그때 그때 원하는 데이터만 볼 수 있으니 참 좋다.

zp9

이외에도 다양한 언어를 지원한다. 예를 들어 앵귤러도 지원한다.

%angular
<div class="row" style="padding:20px; width:500px">
    <h3>일자</h3>
    <div class="input-group input-group-ch">
        <span class="input-group-addon" id="sizing-addon1">Start date</span>
        <input class="form-control" type="text" id="startDatepicker" ng-model="startDate"></input>
        <span class="input-group-addon" id="sizing-addon1">End date</span>
        <input class="form-control" type="text" id="endDatepicker" ng-model="endDate"></input>
    </div>
</div>

<script>
$("#startDatepicker").datepicker({
    dateFormat: 'yy-mm-dd'
});

$("#endDatepicker").datepicker({
    dateFormat: 'yy-mm-dd'
});
</script>

z10

위와 같이 html로 코딩해도 화면에 잘 적용 된다. 데이터를 많이 다루는 회사한테는 아주 좋은 툴이 될 것 같다.
만약 spark을 사용하고 있다는 무조건 써야하는 툴로 자리 잡은듯 하다. 아주 좋고 잘 만든 툴이다. 한국분들이 만드셔서 더 정이 가는 것 같다.

이것으로 간단하게 제플린에 대해서 살펴봤다.

kafka 설치

kafka를 설치 해보자
카프카란 LinkedIn에서 개발된 메시지큐 시스템이다. 기존 메시지 시스템과 우수한 성능을 보이고 있다고 한다. 여기 에서 다운로드 받을 수 있다.

producer_consumer

위의 그림은 카프카의 구성요소와 동작 방식으로 발행과 구독 모델기반으로 되어져 있다.
카픈카는 topic 기준으로 메시지를 관리하며 Producer는 topic의 메시지를 생성 후 메시지를 broker에 전달한다. 전달받은 메시지를 분류별로 큐에 쌓으면 구독하는 consumer들이 메시지를 가져가는 구조로 되어있다.

다운 받은 카프카 파일을 압출을 푼후에 실행 시켜보자.

bin/zookeeper-server-start.sh config/zookeeper.properties

...

[2016-05-22 13:30:16,738] INFO Server environment:java.compiler=<NA> (org.apache.zookeeper.server.ZooKeeperServer)
[2016-05-22 13:30:16,738] INFO Server environment:os.name=Mac OS X (org.apache.zookeeper.server.ZooKeeperServer)
[2016-05-22 13:30:16,738] INFO Server environment:os.arch=x86_64 (org.apache.zookeeper.server.ZooKeeperServer)
[2016-05-22 13:30:16,738] INFO Server environment:os.version=10.11.4 (org.apache.zookeeper.server.ZooKeeperServer)
[2016-05-22 13:30:16,738] INFO Server environment:user.name=wonwoo (org.apache.zookeeper.server.ZooKeeperServer)
[2016-05-22 13:30:16,738] INFO Server environment:user.home=/Users/wonwoo (org.apache.zookeeper.server.ZooKeeperServer)
[2016-05-22 13:30:16,738] INFO Server environment:user.dir=/Users/wonwoo/Documents/kafka_2.11-0.9.0.1 (org.apache.zookeeper.server.ZooKeeperServer)
[2016-05-22 13:30:16,747] INFO tickTime set to 3000 (org.apache.zookeeper.server.ZooKeeperServer)
[2016-05-22 13:30:16,747] INFO minSessionTimeout set to -1 (org.apache.zookeeper.server.ZooKeeperServer)
[2016-05-22 13:30:16,747] INFO maxSessionTimeout set to -1 (org.apache.zookeeper.server.ZooKeeperServer)
[2016-05-22 13:30:16,775] INFO binding to port 0.0.0.0/0.0.0.0:2181 (org.apache.zookeeper.server.NIOServerCnxnFactory)

카프카를 실행 시키기 위해 주기퍼가 필요 하므로 주키퍼를 먼저 실행 해야 된다. 그럼 위와 같은 로그가 출력 될 것이다.
그런다음에 메시지 저장소인 카프카를 실행시켜보자.

bin/kafka-server-start.sh config/server.properties

...

[2016-05-22 13:33:02,693] INFO [ThrottledRequestReaper-Produce], Starting  (kafka.server.ClientQuotaManager$ThrottledRequestReaper)
[2016-05-22 13:33:02,696] INFO [ThrottledRequestReaper-Fetch], Starting  (kafka.server.ClientQuotaManager$ThrottledRequestReaper)
[2016-05-22 13:33:02,730] INFO Will not load MX4J, mx4j-tools.jar is not in the classpath (kafka.utils.Mx4jLoader$)
[2016-05-22 13:33:02,778] INFO Creating /brokers/ids/0 (is it secure? false) (kafka.utils.ZKCheckedEphemeral)
[2016-05-22 13:33:02,786] INFO Result of znode creation is: OK (kafka.utils.ZKCheckedEphemeral)
[2016-05-22 13:33:02,788] INFO Registered broker 0 at path /brokers/ids/0 with addresses: PLAINTEXT -> EndPoint(192.168.0.6,9092,PLAINTEXT) (kafka.utils.ZkUtils)
[2016-05-22 13:33:02,803] INFO New leader is 0 (kafka.server.ZookeeperLeaderElector$LeaderChangeListener)
[2016-05-22 13:33:02,822] INFO Kafka version : 0.9.0.1 (org.apache.kafka.common.utils.AppInfoParser)
[2016-05-22 13:33:02,822] INFO Kafka commitId : 23c69d62a0cabf06 (org.apache.kafka.common.utils.AppInfoParser)
[2016-05-22 13:33:02,823] INFO [Kafka Server 0], started (kafka.server.KafkaServer)

위와 같이 로그가 출력 되었다면 성공적으로 실행되었다.
카프카는 topic 기준으로 메시지를 처리 하기 때문에 topic을 생성해 주어야 한다.

bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test
Created topic "test".

위는 topic을 생성해주는 커멘드 명령어이다. 우리는 공식문서에 나와있듯이 topic의 이름을 test라 지정하였다.
그리고 현재 만들어진 topic을 볼 수 있는 명령어이다.

bin/kafka-topics.sh --list --zookeeper localhost:2181
test

그런다음에 producer를 실행 시켜보자

bin/kafka-console-producer.sh --broker-list localhost:9092 --topic test

방금 만든 test라는 topic으로 발행하는 커멘드 명령어이다.
명령어를 실행 시킨다음에 메시지를 입력해보자.

This is Message
This is another message

발행을 했으면 구독하는 consumer가 있어야 한다.

bin/kafka-console-consumer.sh --zookeeper localhost:2181 --topic test --from-beginning
This is Message
This is another message

위와 같이 test라는 topic을 구독하여 보자.
그럼 이전에 test라는 topic으로 발행 했던 메시지들이 출력이 된다.

그럼 다른 메시지를 발행해보자.

My name is wonwoo lee

메시지를 입력후에 consumer에 있는 커멘드창을 보면 위에 입력했던 메시지가 출력이 될 것이다. 만약 출력이 안되었다면 topic이 제대로 되어있는지 다시 확인해보자.

일단 기본적으로 kafka에 대해서 알아봤고 설치 후 간단한 명령어를 통해 발행 및 구독을 해보았다.
카프카의 공식 홈페이지에 보면 아주 쉽게 설명 되어 있으니 공식 홈페이지를 참고에서 해보는 것이 나을 듯하다.

spark 설치 및 간단하게 보자

spark을 설치 해보자
간단하게 설치하고 실행만 시켜보자.
mac 기준으로 설치를 진행하겠다. 깔기만 하면 되긴 하는데..설치할 것도 없다.
spark

위와 같은 설정으로 다운받자.
원하는 곳에 압축을 푼후 ${SPARK_HOME}/bin 으로 가서 아래와 같이 실행 시키자!

./spark-shell

spark1

그럼 위와 같이 실행 될 것이다.
이 spark-shell을 실행 시키면 sparkContext가 생성 된다. 로그를 보면 확인 할 수 있다.

Spark context available as sc.

이렇게 말이다.

그리고 webUI도 함께 올라간다.
http://localhost:4040 으로 접속 해보자!

일단 설치가 완료 되었다.
이번 시간에는 간단하게만 알아보자

scala> val textFile = sc.textFile("/Users/wonwoo/Documents/spark-1.6.1-bin-hadoop2.6/README.md")
textFile: org.apache.spark.rdd.RDD[String] = /Users/wonwoo/Documents/spark-1.6.1-bin-hadoop2.6/README.md MapPartitionsRDD[19] at textFile at <console>:27

아까 말했듯이 sc는 shell을 실행 시킬때 자동으로 올라간다.

scala> textFile.count()
res15: Long = 95

파일의 RDD의 개수이다. 지금버전의 README.md는 95줄이 있다.

scala> textFile.first()
res18: String = # Apache Spark

첫번째 RDD를 가져온다.
마지막으로 원하는 단어를 찾아보자.

scala> textFile.filter(line => line.contains("Spark")).count()
res19: Long = 17

그리고 나서 spark WEB UI에 접속해보자.
그러면 우리가 했던 작업들을 상세하게 볼 수 있다.
우리는 간단하게 스팍에 대해서 알아봤다.
다음 시간에는 좀더 재밌는 거를 해보자!