Scala, Spring-Boot, JPA를 활용한 웹 애플리케이션 개발 과정에 대해 다룬다. Spring-Boot와 JPA 조합만으로도 생산성 있는 웹 애플리케이션 개발이 가능하다. 이 조합만으로도 충분히 의미가 있지만 여기에 Scala라는 약간은 불편한 듯 보이는 언어를 도입함으로써 얻을 수 있는 즐거움을 공유한다. Spring-Boot + JPA 조합에 Scala를 적용하면서의 좌충우돌 경험담을 전한다.
Scala, Spring-Boot, JPA를 활용한 웹 애플리케이션 개발 과정에 대해 다룬다. Spring-Boot와 JPA 조합만으로도 생산성 있는 웹 애플리케이션 개발이 가능하다. 이 조합만으로도 충분히 의미가 있지만 여기에 Scala라는 약간은 불편한 듯 보이는 언어를 도입함으로써 얻을 수 있는 즐거움을 공유한다. Spring-Boot + JPA 조합에 Scala를 적용하면서의 좌충우돌 경험담을 전한다.
Spark 의 핵심은 무엇인가? RDD! (RDD paper review)Yongho Ha
요즘 Hadoop 보다 더 뜨고 있는 Spark.
그 Spark의 핵심을 이해하기 위해서는 핵심 자료구조인 Resilient Distributed Datasets (RDD)를 이해하는 것이 필요합니다.
RDD가 어떻게 동작하는지, 원 논문을 리뷰하며 살펴보도록 합시다.
http://www.cs.berkeley.edu/~matei/papers/2012/sigmod_shark_demo.pdf
Apache Storm 0.9 basic training - VerisignMichael Noll
Apache Storm 0.9 basic training (130 slides) covering:
1. Introducing Storm: history, Storm adoption in the industry, why Storm
2. Storm core concepts: topology, data model, spouts and bolts, groupings, parallelism
3. Operating Storm: architecture, hardware specs, deploying, monitoring
4. Developing Storm apps: Hello World, creating a bolt, creating a topology, running a topology, integrating Storm and Kafka, testing, data serialization in Storm, example apps, performance and scalability tuning
5. Playing with Storm using Wirbelsturm
Audience: developers, operations, architects
Created by Michael G. Noll, Data Architect, Verisign, https://www.verisigninc.com/
Verisign is a global leader in domain names and internet security.
Tools mentioned:
- Wirbelsturm (https://github.com/miguno/wirbelsturm)
- kafka-storm-starter (https://github.com/miguno/kafka-storm-starter)
Blog post at:
http://www.michael-noll.com/blog/2014/09/15/apache-storm-training-deck-and-tutorial/
Many thanks to the Twitter Engineering team (the creators of Storm) and the Apache Storm open source community!
이것이 자바다 익명 객체 + Chap.11 기본 API 클래스(java) 발표용 PPT.
간단하게 정리한 것.
이것이 자바다 책을 기반으로 작성한 강의용 PPT입니다.
부족한 게 많으니 쓰실 때에는 추가하셔서 쓰세요~
참고 자료 : 이것이 자바다
사진 첨부 : http://palpit.tistory.com/
2. 스톰Storm
● 데이터의 스트림을 처리하는 시스템
○ 실시간 데이터 처리 목적
○ 예 - 주식 실시간 트레이딩, 기계 데이터 분석
● 주요 특징
○ 프로세싱 병렬 실행
■ 클러스터에서 연산 수행
○ 안정성
■ 데이터의 처리를 보장
○ 내고장성(fault-tolerant)
■ 프로세스 재시작으로 작업 재할당
4. 스톰 토폴로지
토폴로지(topology):
데이터 스트림 처리를 위한 작업 단위
스파우트(Spout):
스트림 데이터를
볼트에 전달.
외부 메시징 시스
템 등에서 데이터
가져옴
이미지 출처: http://storm-project.net/
볼트(Bolt):
데이터를 처리해서
다른 볼트에 전달
하거나 외부에 저
장
5. 스트림의 데이터: 튜플
튜플은 [이름:값, 이름:값, 이름:값, …] 형식의 데이터
튜플
튜플
튜플
볼트는 튜플을 입력으로 받아 연산 수행 후,
새로운 튜플을 생성해서 다른 볼트에 전달 또는
연산 결과를 별도 처리(DB 저장 등)
6. 스톰 클러스트
● 토폴로지를 실행
님버스(Nimbus):
토폴로지의 각 태스크를 Worker에
할당하고, 모니터링
수퍼바이저(Supervisor):
토폴로지의 태스크를 실행하기 위
해 worker 프로세스 생성
토폴로지:
jar 파일
Nimbus
(master)
주키퍼(Zookeeper):
토폴로지의 실행 상태 보관
Zookeeper 클러스터
Supervisor
Supervisor
Supervisor
7. 개발자가 해야 할 일
● 스톰 클러스터 구축
● 코드 구현
○ 스파우트 구현
○ 볼트 구현
○ 토폴로지 구성
-- 토폴로지 구성 예
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
8. 병렬 실행
● 워커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개의 태스크 실행
9. 스트림 그룹핑
● 태스크가 2개 이상일 때 각 태스크에 튜플을
분배하는 기준 필요
1번 태스크로 전
달?
word-reader 스파우트
word-normalizer 볼트
튜플
튜플
1번 태스크
2번 태스크
10. 스트림 그룹핑 종류
그룹핑
설명
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”));
11. 스파우트와 볼트 구현 방식
public class WordReader extends BaseRichSpout {
// 튜플을 스트림으로 보낼 때 사용
private SpoutOutputCollector collector;
public class WordNormalizer extends BaseRichBolt {
private OutputCollector collector;
@Override
public void prepare(Map conf, TopologyContext context,
OutputCollector collector) {
this.collector = collector;
…. // 데이터 처리 위한 준비
}
@Override
public void open(Map conf, TopologyContext context,
SpoutOutputCollector 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 nextTuple() {
… // 데이터를 읽어와 알맞은 튜플 생성
collector.emit(new Values(line), line);
}
@Override
public void declareOutputFields(
OutputFieldsDeclarer declarer) {
// 생성할 튜플의 필드 정의
declarer.declare(new Fields("line"));
}
@Override
public void declareOutputFields(
OutputFieldsDeclarer declarer) {
// 볼트가 튜플 생성할 경우, 필드 정의
declarer.declare(new Fields("word"));
}
@Override
public void close() { …연결 종료 등 처리 }
}
}
12. 메시지(튜플) 처리 여부 확인
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을 해야 함
13. 최초의 메시지가 여러 튜플을 거치면?
word-reader
ack로 인식
word-normalizer
ack
collector.emit(new Values(word));
collector.ack(input);
fail 응답이 원본 스파우트에 전
달되지 않음
word-counter
collector.fail(input);
14. Anchoring
● 메시지를 연결해서 전체에서 처리되었는지
확인하기 위한 방법
연결된 모든 튜플에 대해
ack를 받을 때 비로서 ack 처리
word-reader
word-normalizer
ack
-- 스트림에서 받은 input을 연결
collector.emit(input, new Values(word));
collector.ack(input);
ack
word-counter
collector.ack(input);
15. Fault tolerance
● 워커 프로세스 죽을 때
○ 수퍼바이저가 워커 프로세스 재 구동
● 님버스/수퍼바이저가 죽을 때
○ 얼른 재시작하면, 태스크 재시작
● 님버스가 실행 중인 노드가 죽을 때
○ 얼른 다른 장비 구해서 님버스 실행
■ 수퍼바이저는 기능 제공
● 수퍼바이저가 실행 중인 노드가 죽을 때
○ 님버스가 노드에서 실행 중인 태스크를 다른 노드에
할당