욱'S 노트

Apache Storm - Concepts 본문

Programming/Storm

Apache Storm - Concepts

devsun 2015. 11. 19. 17:24

이번 페이지에서는 스톰의 메인 컨셉을 나열해보고 더 자세한 정보를 제공에 대한 링크를 제공할 것이다. 논의될 컨셉은 다음과 같다.


  • Topologies
  • Streams
  • Spouts
  • Bolts
  • Stream groupings
  • Reliability
  • Tasks
  • Workers

Topologies


실시간 어플리케이션을 위한 로직은 스톰 토폴로지로 패키징 된다. 스톰 토폴로지는 맵리듀스 작업과 유사하다. 하나의 주요한 차이점은 맵리듀스 작업은 결국에는 종료되는 반면 토폴로지는 항상 수행중이다는 것이다. 토폴로지는 spout과 bolt의 stream grouping으로 연결된 그래프이다. 


Streams


스트림은 스톰의 핵심 추상화이다. 스트림은 투플의 일관되지 않는 순서이다. 투플은 분산환경에서 병렬로 처리되고 생성된다. 스트림은 스키마로 정의되어지는데 스키마는 스트림의 투플들의 필드명을 의미한다. 기본적으로 투플은 integers, longs, shorts, bytes, strings, doubles, floats, booleans, and byte arrays을 포함할 수 있다. 또한 커스텀한 serializer를 구현해서 사용할 수 있다.


모든 스트림은 정의 시 주어진 아이디를 가지고 있다. 싱글 스트림 spout과 bolt는 일반적이기 때문에 OutputFieldsDeclarer는 특정한 아이디없이 싱글 스트림을 정의하기 위한 편리한 메소드를 제공한다. 아 경우 스트림은 default라는 default id를 가진다.


Resources:


Tuple: 스트림은 투플들로 구성된다.

OutputFieldsDeclarer: 스트림과 그의 스키마를 정의하기 위해 사용된다.

Serialization: 투플의 다이나믹 타이핑 및 커스텀 serialization 정의에 대한 정보ISerialization: 커스텀 serializer는 반드시 이 인터페이스를 구현해야 한다. 

CONFIG.TOPOLOGY_SERIALIZATIONS: 커스텀 serializer는 이 설정을 이용해서 등록해야 한다. 


Spouts


Spout은 토폴로지 상의 스트림의 소스이다.  일반적으로 spout은 외부 소스로부터 투플을 읽어서 토폴로지 상에 투플을 발행한다. Spout은 reliable일수도 있고 unreliable일 수 있다. reliable일 경우 spout은 스톰에 의해 처리에 실패할 경우 다시 실행할 수 있는 기능을 가지게 되고, 반면에 unreliabe일 경우에는 다시 발행하는 순간 투플에 관한 내용을 잊어버린다.


Spout은 하나의 스트림 이상에 투플을 발행할 수 있다. 이렇게 하기 위해서는 OutputFieldsDeclarer의 declareStream 메소드를 이용하여 다수의 스트림을 정의하고, SpoutOutputCollector의 emit 메소드를 이용할 때 스트림을 명시해주면 된다.


Spout의 가장 주요한 메소드는 nextTuple이다. nextTuple은 새로운 투플을 발행할 수도 있고 만약 발행할 투플이 없다고 하면 단순히 리턴할수도 있다. 


다른 spout 구현을 위해 nextTuble은 절대 블락하지 않아야 한다. 기 이유는 스톰은 모든 spout 메소드를 하나의 스레드에서 호출하기 때문이다. 


또 다른 spout의 주요한 메소드는 ack와 fail이다. Spout으로부터 발행된 투플이 토폴로지를 완전히 완료하거나 완료에 실패했을때 이 메서드가 호출된다. ack와 fail은 reliable spout에서만 호출된다.


Resources:


IRichSpout: spout은 해당 인터페이스를 구현해야 한다.


Bolts


토폴로지의 모든 처리는 볼트내에서 완료된다. 볼트는 다음과 같은 모든것을 수행할 수 있다. (filtering, functions, aggregations, joins, talking to databases, and more.)


볼트는 단순한 스트림의 변경을 수행할 수 있다. 또한 복잡한 스트림 변경을 위해서는 종종 다수의 스텝 즉 다수의 볼트가 필요하기도 한다. 예를들어 tweet의 스트림을 trending images로 변경하기 위해서는 최소한 두개의 스텝이 필요하다. 


볼트 또한 하나 이상의 스트림에 발행할 수 있다. 이렇게 하기 위해서는 OutputFieldsDeclarer의 declareStream 메소드를 이용하여 다수의 스트림을 정의하고, SpoutOutputCollector의 emit 메소드를 이용할 때 스트림을 명시 해주면 된다.


볼트의 입력 스트림을 정의할 때는 항상 다른 컴포넌트의 특정한 스트림을 subscribe해야 한다. 만약 다른 컴포넌트로 부터 모든 스트림을 subscribe하기를 원한다면 개별적으로 각각 하나씩 subscribe를 해야 한다. InputDeclarer는 기본 stream id로 정의된 스트림을 명시하기 위한 syntatic sugar를 가지고 있다. declarer.shffleGrouping("1")은 컴포넌트 "1"의 기본 스트림을 구독하고 declarer.shuffleGrouping("1", DEFAULT_STREAM_ID)과 같은 의미이다.


볼트의 주요 메소드는 execute이다. 볼트는 OutputCollect 오브젝트를 사용하여 새로운 투플을 발행할 수 있고, 볼트는 그들이 처리한 모든 투플을 위해 OutputCollector의 ack 메소드를 반드시 호출해야 하는데, 그래야 스톰이 투플이 완료되었는지를 알 수 있기 때문이다. 입력한 투플을 처리하는 일반적인 경우 0개나 그 이상의 투플을 발행하게 되는데 그때 입력 투플을 acking해야 한다. Storm IBasicBolt 인터페이스를 제공하는데 이 인터페이스를 구현하면 자동으로 acking이 수행된다.


OutputCollector는 스레드 세이프하지 않다. 모든 emits, acks, fails 하나의 스레드에서 발생한다.


Resources:


IRichBolt: 볼트를 위한 일반적인 인터페이스

IBasicBolt: 필터링 또는 단순한 기능을 수행하기 위해 편리하게 사용할 수 있는 인터페이스 

OutputCollector: 볼트가 그들의 출력 스트림으로 투플을 발행할 때 사용하는 클래스


Stream groupings


토폴로지 정의의 한 부분으로 각 볼트를 위해 그들의 받을 입력을 명시할 수 있다. Stream grouping은 볼트의 작업들 사이에 스트림을 어떻게 분할할지를 명시한다.


스톰에는 8개의 빌트인 stream grouping이 있다. 커스텀 stream grouping을 구현하고자 한다면 CustomStreamGrouping 인터페이스를 구현하면 된다.


Shuffle grouping: 투플이 랜덤하게 볼트의 작업으로 분배된다. 이 경우 각 볼트는 같은 수의 투플을 처리하게 된다.

Fields grouping: 스트림은 그룹핑에 명시된 필드로 분할된다. 예를 들어 스트림이 user-id라는 필드로 그룹핑되어 있다면, 똑같은 user-id를 가진 투플은 항상 똑같은 작업으로 전달될 것이다. user-id가 다른 값을 가지면 다른 타스크로 전달된다.

Partial Key grouping: 스트림은 그룹핑에 명시된 필드에 의해 파티션된다. Fields 그룹핑과 유사하지만 두개의 downstream 볼트 사이에 로드 밸런스가 수행된다. 더 좋은 리소스 활용이 제공되어 한쪽으로 쏠려서 데이터가 몰리는 것이 방지된다. 

All grouping : 스트림은 모든 볼트 타스크에 복제된다. 이 그룹핑을 사용할때는 특별히 유의하자.

Global groping : 전체 스트림이 하나의 볼트 타스크로 전달된다. 구체적으로 말하자면 lowest id의 타스크로 전달된다.

None grouping : 이 그룹핑은 스트림이 어떻게 그룹핑되는지 신경쓰지 않는다는 것이다. 현재 none groupnig은 shuffle grouping과 동일하다.

Direct grouping : 이것은 특별한 타입의 그룹핑이다. 이 방식에서 그룹핑된 스트림은 투플의 producer가 투플의 consumer를 지정한다. Direct grouping에서는 direct stream으로 명시된 stream에서만 정의될 수 있다. Direct stream이 발행된 투플은 반드시 emitDirect method를 사용해서 발행되어야만 한다. 볼트는 TopogyContext로 부터 제공되어진 consumer들의 task 아이디를 조회할 수 있고, OutputCollector의 emit메소드의 출력을 추적할 수 잇다.

Local or shuffle grouping: 타겟 볼트가 하나 또는 그 이상의 타스크를 같은 워커 프로세스에서 가지고 있다면 투플은 인프로세스 파스크로 전달된다.


Resources:


TopologyBuilder: 토폴로지를 정의하기 위해 이 클래스를 사용한다.

InputDeclarer: TopologyBuilder의 setBolt메소드를 호출하면 이 오브젝트가 리턴된다. 볼트의 input stream을 정의하기 위해 사용되며 스트림을 어떻게 그룹핑할지를 명시한다.

CoordinatedBolt: 분산 RPC 토폴로지에 유용한 볼트이다. Direct stream과 direct grouping을 heavy하게 사용할 수 있게 해준다.


Reliability


스톰은 모든 spout 투플이 토폴로지에 의해 완전하게 처리되는 것을 보장한다. 이것은 모든 spout 투플에 의해 트리거된 투플 트리 추적에 의해 달성된다. 투플 트리가 성공적으로 완료되었는지를 판단한다. 모든 토폴로지는 message timeout을 가진다. 만약 타임아웃내에 완료되지 않으면 스톰은 투플의 실패로 감지하고 이후 투플을 다시 실행시킨다. 


스톰의 reliablity의 이점을 누릴려면 투플 트리에 새로운 엣지가 생기면 반드시 스톰에게 알려야 한다. 이것은 볼트가 투플을 발행하기 위해 사용하는 OutputCollect 오브젝트를 이용하여 수행할 수 있다. Anchoring이 완료되면 명시적으로 투플이 완료되었다고 ack 메소드를 사용해야 한다.


Tasks


각 spout과 볼트는 클러스터상의 많은 작업을 수행한다. 각 작업은 하나의 스레드의 수행과 일치하며 stream 그룹핑은 하나의 타스크를 또 다른 파스크로 어떻게 전달하는지를 명시한다. 각 spout과  bolt의 parallelism을 정의할 수 있다. 이 때 TopologyBuilder의 setSpout과 setbolt 함수를 이용한다.


Workers


토폴로지는 하나 또는 그 이상의 worker 프로세스를 실행한다. 각 워커 프로세스는 하나의 물리적인 JVM이며 토폴로지를 위한 모든 타스크의 서브셋을 실행한다. 예를 들어 만약 토폴로지가 300개의 병렬 타스크로 구성되어 있고 50개의 워커 스레드가 있다면 각 워커는 6개의 타스크가 할당된다.


Resources:


Config.TOPOLOGY_WORKERS: 토폴로지를 실행하기 위한 워커의 수는 다음의 설정에 명시할 수 있다.

Comments