Storm 훑어보기

16

Click here to load reader

description

팀 내 발표자료 Storm 훑어보기

Transcript of Storm 훑어보기

Page 1: Storm 훑어보기

스톰Storm 훑어보기최범균 2014-01-17

Page 2: Storm 훑어보기

스톰Storm

● 데이터의 스트림을 처리하는 시스템○ 실시간 데이터 처리 목적○ 예 - 주식 실시간 트레이딩, 기계 데이터 분석

● 주요 특징○ 프로세싱 병렬 실행

■ 클러스터에서 연산 수행○ 안정성

■ 데이터의 처리를 보장○ 내고장성(fault-tolerant)

■ 프로세스 재시작으로 작업 재할당

Page 3: Storm 훑어보기

토폴로지/클러스터

● 토폴로지(topology)○ 데이터 처리 프로그램 단위○ 데이터의 흐름을 정의○ 데이터 변환을 구현○ 물리적으로 jar 파일 형태로 클러스터에 전송

● 스톰 클러스터(cluster)○ 토폴로지를 실행○ 다수의 JVM에서 토폴로지의 각 작업을 병렬 실행

Page 4: Storm 훑어보기

스톰 토폴로지

토폴로지(topology):데이터 스트림 처리를 위한 작업 단위

스파우트(Spout):스트림 데이터를볼트에 전달.외부 메시징 시스템 등에서 데이터 가져옴

볼트(Bolt):데이터를 처리해서 다른 볼트에 전달하거나 외부에 저장

이미지 출처: http://storm-project.net/

Page 5: Storm 훑어보기

스트림의 데이터: 튜플

튜플튜플튜플

튜플은 [이름:값, 이름:값, 이름:값, …] 형식의 데이터

볼트는 튜플을 입력으로 받아 연산 수행 후,새로운 튜플을 생성해서 다른 볼트에 전달 또는연산 결과를 별도 처리(DB 저장 등)

Page 6: Storm 훑어보기

스톰 클러스트

● 토폴로지를 실행

Zookeeper 클러스터

Nimbus(master) Supervisor Supervisor Supervisor

님버스(Nimbus):토폴로지의 각 태스크를 Worker에 할당하고, 모니터링

수퍼바이저(Supervisor):토폴로지의 태스크를 실행하기 위해 worker 프로세스 생성

주키퍼(Zookeeper):토폴로지의 실행 상태 보관

토폴로지:jar 파일

Page 7: Storm 훑어보기

개발자가 해야 할 일

● 스톰 클러스터 구축● 코드 구현

○ 스파우트 구현○ 볼트 구현○ 토폴로지 구성

-- 토폴로지 구성 예TopologyBuilder builder = new TopologyBuilder();builder.setSpout("word-reader", new WordReader());builder.setBolt("word-normalizer", new WordNormalizer()).shuffleGrouping("word-reader");builder.setBolt("word-counter", new WordCounter()).shuffleGrouping("word-reader");

word-reader word-normalizer word-counter

Page 8: Storm 훑어보기

병렬 실행

● 워커worker 프로세스○ 클러스터에서 생성되는 JVM 프로세스, 토폴로지 단위로 설정 가능

● executor○ 스파우트/볼트를 실행하는 쓰레드, worker가 생성○ 스파우트/볼트 단위로 개수 지정, 지정하지 않으면 1개 사용

● 태스크task○ 스파우트/볼트 당 생성할 작업(인스턴스) 개수○ 지정하지 않으면 executor 당 1개

builder.setBolt("word-normalizer", new WordNormalizer(), 4) // 4개의 쓰레드 .setNumTasks(8) // 8개의 작업 생성 .shuffleGrouping("word-reader");

conf.setNumWorkers(2); // worker 프로세스 2개

* 1개 worker에서 2개 쓰레드 실행 / 1개 쓰레드가 2개의 태스크를 실행* 즉, 각 worker에서 4개의 태스크 실행

Page 9: Storm 훑어보기

스트림 그룹핑

● 태스크가 2개 이상일 때 각 태스크에 튜플을 분배하는 기준 필요

word-normalizer 볼트

1번 태스크

2번 태스크

word-reader 스파우트

튜플튜플

1번 태스크로 전달?

Page 10: Storm 훑어보기

스트림 그룹핑 종류그룹핑 설명

Shuffle(None도 동일)

각 튜플을 랜덤하게 볼트 태스크로 보낸다. 각 태스크에 보내지는 튜플은 균등한다.

Field 튜플의 지정한 필드 값을 이용해서 볼트 태스크를 선택한다. 동일 필드 값을 가진 튜플은 같은 볼트 태스크로 전달된다.

All 동일 튜플이 모든 볼트 태스크에 전달된다.

Direct 튜플을 생성하는 쪽에서 직접 볼트 태스크를 지정한다.

Global n개의 태스크 중, 작은 ID를 가진 태스크로 튜플을 전달한다.

* Global Grouping 사용 이유에 대한 힌트:https://groups.google.com/forum/#!msg/storm-user/JalFsPvksxw/l4RnjM7qI0wJ

-- 코드 샘플builder.setBolt("word-normalizer", new WordNormalizer(), 4).shuffleGrouping("word-reader");builder.setBolt("word-counter", new WordCounter(), 2).fieldGrouping("word-reader", new Field(“word”));

Page 11: Storm 훑어보기

스파우트와 볼트 구현 방식public class WordReader extends BaseRichSpout { // 튜플을 스트림으로 보낼 때 사용 private SpoutOutputCollector collector;

@Override public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) { this.collector = collector; // 메시지 큐 연결 등의 처리 }

@Override public void nextTuple() { … // 데이터를 읽어와 알맞은 튜플 생성 collector.emit(new Values(line), line); }

@Override public void declareOutputFields( OutputFieldsDeclarer declarer) { // 생성할 튜플의 필드 정의 declarer.declare(new Fields("line")); }

@Override public void close() { …연결 종료 등 처리 }}

public class WordNormalizer extends BaseRichBolt { private OutputCollector collector;

@Override public void prepare(Map conf, TopologyContext context, OutputCollector collector) { this.collector = collector; …. // 데이터 처리 위한 준비 }

@Override public void execute(Tuple input) { String sentence = input.getString(0); String[] words = sentence.split(" "); for (String word : words) { word = word.trim().toLowerCase(); // 다른 볼트에 전달할 튜플 생성 collector.emit(new Values(word)); } collector.ack(input); }

@Override public void declareOutputFields( OutputFieldsDeclarer declarer) { // 볼트가 튜플 생성할 경우, 필드 정의 declarer.declare(new Fields("word")); }}

Page 12: Storm 훑어보기

메시지(튜플) 처리 여부 확인 public class WordReader extends BaseRichSpout {

@Override public void nextTuple() { … collector.emit(new Values(line), msgId); }

@Override public void ack(Object msgId) { // 처리가 된 튜플의 아이디 수신 }

@Override public void fail(Object msgId) { // 처리에 실패한 튜플의 아이디 수신 // 실패 메시지에 대한 알맞은 재처리 필요 }

}

public class WordNormalizer extends BaseRichBolt {

@Override public void execute(Tuple input) { try { String sentence = input.getString(0); String[] words = sentence.split(" "); for (String word : words) { word = word.trim(); if (!word.isEmpty()) { word = word.toLowerCase(); collector.emit(new Values(word)); } } collector.ack(input); // 메시지 처리 됨을 알림 } catch(Exception e) { collector.fail(input); // 메시지 처리 실패 알림 } }

* 스파우트는 ack()와 fail()을 통해 발생시킨 메시지가 처리되었는지 알 수 있음* 스파우트가 fail 메시지를 받는 경우: - 수신 볼트에서 fail() 호출하거나 메시지를 제한된 시간 안에 처리하지 못한 경우* 튜플의 처리 여부 상태를 메모리로 관리하므로 , 반드시 수신 볼트에서 ack와 fail을 해야 함

Page 13: Storm 훑어보기

최초의 메시지가 여러 튜플을 거치면?

word-reader word-normalizer word-counter

collector.emit(new Values(word));collector.ack(input);

collector.fail(input);ack

fail 응답이 원본 스파우트에 전달되지 않음

ack로 인식

Page 14: Storm 훑어보기

Anchoring

● 메시지를 연결해서 전체에서 처리되었는지 확인하기 위한 방법

word-reader word-normalizer word-counter

-- 스트림에서 받은 input을 연결collector.emit(input, new Values(word));collector.ack(input);

collector.ack(input);ack

ack

연결된 모든 튜플에 대해ack를 받을 때 비로서 ack 처리

Page 15: Storm 훑어보기

Fault tolerance

● 워커 프로세스 죽을 때○ 수퍼바이저가 워커 프로세스 재 구동

● 님버스/수퍼바이저가 죽을 때○ 얼른 재시작하면, 태스크 재시작

● 님버스가 실행 중인 노드가 죽을 때○ 얼른 다른 장비 구해서 님버스 실행

■ 수퍼바이저는 기능 제공 ● 수퍼바이저가 실행 중인 노드가 죽을 때

○ 님버스가 노드에서 실행 중인 태스크를 다른 노드에 할당

Page 16: Storm 훑어보기

기타

● 스톰 클러스터 설치● Trient● 다중 언어 지원● 주키퍼● 스톰 + Esper● Kestrel (메시지 큐)