최근 몇 년전만 해도 응답시간 수초, 수십개의 서버, 기가단위의 데이터로 시스템이 구성되었지만 오늘날에는 모바일, 수천대의 클라우드 기반환경으로 변화하면 millisecond단위의 응답시간, 페타바이트 데이터 등의 요건으로 인해서 과거의 소프트웨어 아키텍처로는 이를 수용하기가 어려운 상태이다.

 결국 우리는 Responsive, Resilient, Elastic and Message Driven 한 시스템을 원하고 이것을  Reactive Systems이라고 부른다. ( 보다 유연하고 scalabe하면서 장애도 방지하는 그런 시스템)

Reactive Systems are:

Responsive: The system responds in a timely manner if at all possible. Responsiveness is the cornerstone of usability and utility, but more than that, responsiveness means that problems may be detected quickly and dealt with effectively. Responsive systems focus on providing rapid and consistent response times, establishing reliable upper bounds so they deliver a consistent quality of service. This consistent behaviour in turn simplifies error handling, builds end user confidence, and encourages further interaction.

Resilient: The system stays responsive in the face of failure. This applies not only to highly-available, mission critical systems — any system that is not resilient will be unresponsive after a failure. Resilience is achieved by replication, containment, isolation and delegation. Failures are contained within each component, isolating components from each other and thereby ensuring that parts of the system can fail and recover without compromising the system as a whole. Recovery of each component is delegated to another (external) component and high-availability is ensured by replication where necessary. The client of a component is not burdened with handling its failures.

Elastic: The system stays responsive under varying workload. Reactive Systems can react to changes in the input rate by increasing or decreasing the resources allocated to service these inputs. This implies designs that have no contention points or central bottlenecks, resulting in the ability to shard or replicate components and distribute inputs among them. Reactive Systems support predictive, as well as Reactive, scaling algorithms by providing relevant live performance measures. They achieve elasticity in a cost-effective way on commodity hardware and software platforms.

Message Driven: Reactive Systems rely on asynchronous message-passing to establish a boundary between components that ensures loose coupling, isolation, location transparency, and provides the means to delegate errors as messages. Employing explicit message-passing enables load management, elasticity, and flow control by shaping and monitoring the message queues in the system and applying back-pressure when necessary. Location transparent messaging as a means of communication makes it possible for the management of failure to work with the same constructs and semantics across a cluster or within a single host. Non-blocking communication allows recipients to only consume resources while active, leading to less system overhead.

Large systems are composed of smaller ones and therefore depend on the Reactive properties of their constituents. This means that Reactive Systems apply design principles so these properties apply at all levels of scale, making them composable. The largest systems in the world rely upon architectures based on these properties and serve the needs of billions of people daily. It is time to apply these design principles consciously from the start instead of rediscovering them each time.

참고)http://www.reactivemanifesto.org/

===============================================================================================================

슬라이드쉐어에서도 공유가 되고 있으니 참고할 수 있다.

http://www.slideshare.net/mircodotta/go-reactive-eventdriven-scalable-resilient-responsive-systems?qid=bc7cfcab-8c5b-4d37-a122-11590578803f&v=qf1&b=&from_search=11

===============================================================================================================

 디스크, 메모리, 서버등의 자원은 갈수록 저렴해지고 일반적이 되어가고 있으며 동시사용자는 기하급수적으로 늘어났다.

과거 중요한 서비스는 반드시 죽지 않아야 하고 고정되어 requset/response를 보장한다는 개념에서,

이제는 수백,수천개를 띄워놓고 사용자 수에 따라서 서비스량을 조정하면서도 약간의 문제는 상관하지 않고 돌아간다는 개념으로 변화하고 있다.

 

 

패러다임 변화에 따라서 어플리케이션도 변경이 되어야 한다는 내용.

이러한 내용을 반영하여 나온 것이 reactive programming으로 현재 typesafe에서 주도하고 있다.

akka,scala를 통해서 이를 구현하고 있으며 많은 IT서비스기업에서 사용하고 있다.

과거에는 WAS기반으로 앞단에 load balancer를 두는 아키텍처가 일반적이었다. 현재도 일반적이다.

이러한 구조는 일단 확장이 어렵다. WAS를 추가하거나 서버를 추가할때 들어가야 할 설정들도 많고, 배포정책도 정해져야 한다. 기동/재기동에 따라서 묶이는 서비스의 단위(도메인)가 커서 영향범위도 넓다고 생각한다.

이를 보완하기 위해서 따라서 scale out이 쉽게 가능한 micro service 아키텍처가 많이 거론되고 있다.

뒷받침되어야 할 것들에 대해서 생각해보았다.

 

1. 외부로부터 데이터 입력/출력을 담당하는 부분

 데이터 사용량에 따라서 쉽게 scale out이 가능해야 한다. 이는 별도의 설정없이 slave node의 추가만으로 사용이 가능해야 한다. zookeeper나 hadoop의 구조를 생각하면 될 것 같다.

=> 4번과도 연관성이 있으며 다양한 형태의 서비스(ex, spring/storm/spark)와 효과적으로 연결되기 위한 grid bus형태가 필요하지 않을까 고민된다.

 

2. 실제 비니지스를 담당하는 어플리케이션의 모듈화

 각 어플리케이션을 설계할때 참조관계를 깊이 고려해야 한다. 이는 배포의 단위와 직결되며, 커지면 커질수록 단위 서비스를 위해 필요한 작업들이 증가하게 된다. application design에서는 cohension과 coupling으로 예전부터 강조되어왔던 개념이며 refactoring, restructuring을 통해서 초기단계뿐만 아니라 개발/운영단계가 진행될 때에도 계속 병행되어야 한다.

=> 이 부분은 framework개발을 할때부터 고민해왔던 부분인데(온라인/배치/센터컷을 어떻게 자연스럽게 연결할 것인지.. @.@), 앞으로도 계속 봐야할 것 같다.

 변하는 부분과 변하지 않는 부분에 대한 식별이 잘 이루어져야 한다. 무한하게 유연한 설계는 있을 수가 없다. 있다한들 엄청 복잡해지면서 아무도 사용하지 않게된다.. ㅜㅜ

 

3. immutable state

2번과 연관되는 내용이다. 어플리케이션 인스턴스가 일을 할때에는 순수히 메시지에 의존해서 일을 하도록 해야한다. state를 가지게 되는 순간 다양한 메시지에 대해서 어떻게 반응해야 하는지 고려가 되어야 하며(과거 java멤버변수들..), 설계복잡도가 급격히 증가하게 된다.

=> reactive programming를 보다가 과거에 나왔던 actor model에 대해서도 자연스럽게 접하게 되었고 akka도 보고 있다..  scala를 공부하면서 느끼는 내용은 함수형+객체형 언어스타일대로 구현하다보니 이게 자연스럽게 이루어진다. scala에서는 val을 최대한 사용할 것을 권장하고 있다. ^^;

 

4. 실시간 대용량 데이터 처리

 이미 hadoop기반의 배치성 빅데이터 분석은 어느정도 정착이 된 상태이고, storm이나 spark streaming을 통한 실시간 데이터분석도 많이 활용되고 있다. scale out과 연관되어서 약간은 다른 부분을 생각해보고 싶은 것은 분석대상이 될 데이터에 수집/처리에 대한 부분이다. 역시 1번과 연관성이 있지만 5번과 연관성이 더 깊다고 본다. 저장소에 대한 고민도 필요한 것 같다. 쉽게 쌓고, 쉽게 접근할 수 있어야 한다.

=>수집/처리/분석에 대한 Storage를 하나의 아키텍처로 가는것은 부담이 있기 때문에 NoSQL, HDFS, RDB의 적절한 조합이 필요하다고 생각한다. 수집부분에서는 NoSQL로 무조건 쌓아두고, ACID가 보장되어야 하는 데이터들에서는 RDB처리한다. 수집과 처리가 끝난부분에 대해서 선택적으로 HDFS로 옮겨서 분석을 수행한다.(사실 Spark가 너무 좋아져서 이부분이 점점 의미가 없어지기는 한다..;)

 

5. 클라우드 기반

 하나의 서버를 추가하는 것이 손쉽게 이루어져야 한다. 서버자원이 많이 남아돌아서 이를 충분히 활용하기 위해서 가상화기술이 발달해왔다면 앞으로는 어플리케이션 레벨에서의 가상화를 위해서 발전될 것으로 예상한다.

=> docker 기술이 또 주목받고 있다. 하나의 서비스를 이미지화하여 서비스사용량이 증가하면 쉽게 대응할 수도 있고, 어플리케이션 변경이나 버전업이 생길경우에도 이미지를 새로 생성하여 배포하도록 한다. OS가 포함되지 않아서 이미지크기도 부담이 없다.

 

 그 외에도 데이터가 올라와야 하는 Device나 Web, Open API들의 표준화, 다양한 서비스를 효과적으로 연계하기 위한 메시지 포멧/프로토콜 등 고민해야 할 부분이 많다. 하지만 시도해볼 가치는 있다고 생각한다.

 이와 같은 아키텍처를 통하면??

메뉴에서 각 버튼이 하는 액션을 하나의 서비스로 정의하여 구현 => 사용자가 많이 클릭하는 서비스는 인스턴스를 많이 띄우면 된다!

 

앞으로의 목표는 다양한 사업에서 적용될 수 있는 클라우드 기반 아키텍처가 포함된 플랫폼을 만들어서 사용자(비니지스 개발자)에게 쉽게 제공하는 것!

========================================================================================================

 소프트웨어는 역시 코드로 말해야 한다. 워낙 다양한 오픈소스가 있어서 받아보고, 돌려보고, 읽어보고 해야하는 내용도 많고 이들을 엮어서 사용하는 것도 쉽지 않다. 또한 중요한 것은 해당 프로젝트의 개념과 목적을 명확히 이해해야 한다.

1)용도에 맞지 않게 사용하거나,

2)비슷한 개념을 가진 오픈소스를 섞어쓰거나

3)비슷한 목적이지만 구현방법이 다른 오픈소스를 같이 쓰게 되면 두고두고 고생한다.

 

'Software Architecture' 카테고리의 다른 글

Communication_Offerings  (0) 2015.03.25
Go Reactive Systems  (0) 2015.03.25
빅데이터 분석에서 배치활용  (0) 2014.10.21
배치 어플리케이션 개발시 고려사항  (0) 2014.04.20
Batch Architecture 고려사항  (0) 2014.03.31

빅데이터 배치처리외에 실시간 대량데이터에 대한 처리요건도 늘어감에 따라 스터디를 진행하고 있다.

대표적으로 Storm이 있는데 Spout와 Bolt의 연결을 이용한 Stream 처리 엔진으로 보면 될 것 같다.


모든 책에서 대표적으로 소개되고 있는 로그파일처리부분을 살펴보면 

- 로그파일은 flume을 통해서 읽고

- kafka를 통해서 message 병렬분산 처리를 한다.

- storm과의 연결은 kafka spout를 통한다. (인터넷에 다양한 spout가 이미 존재한다.)


각 구성요소의 개념을 간단히 살펴보면


1. Spout
데이터를 입력받는 곳이다. 공식사이트에서 수도꼭지로 표현되며 단어의 의미는 주둥이,분출

데이터를 끌어오는 개념이며 현재 다양한 source로 부터 받을 수 있도록 spout이 존재한다.

spout과 spout간의 연결도 가능하다.

- open메소드 : 최초 한 번 수행되며 일반적으로 환경구성이 필요한 내용들이 들어간다.

nextTuple 메소드 : 데이터가 넘어올 때 마다 수행되며, 실제 데이터를 분출시키는 부분이다.

SpoutOutputCollector를 통해서 데이터를 전달한다. (collector.emit메소드를 호출)

declareOutputFields  : 보내는 데이터에 대해서는 key값을 정의해주어야 OutputFieldsFieldsDeclarer.declare메소드를 호출한다. 해당 Spout에 연결된 Spout/Bolt에서는 이 Key값을 통해서 Value를 가져올 수 있다.


전달 키값을 동일하게 쓰면 받는 쪽에서는 구분없이 하나의 데이터 처리가 가능하며 
전달 키값을 분리하면 분리 처리도 가능함

키값에 대해서는 Topology정의시 상수화 하는 것도 하나의 방법이 될 수 있다.


ack / fail은 필요에 따라 구현한다.



2. Bolt
실제 각 활용영역별로 커스터마이징이 이루어져야 하는 부분이다.

- prepare : 최초 한 번 수행되며 준비에 필요한 내용들이 들어간다. (ex, 환경, IP 등)

- execute : 실제 넘어온 Tuple을 가지고 로직을 수행한다. tuple.getValueByField 메소드를 호출하여 사전에 정의된 Key값을 통해서 value를 가지고 올 수 있다.

declareOutputFields  : Spout와 동일함


3. Topology

만들어진 Spout와 Bolt를 서로 연결하여 망을 형성한다.

TopologyBuilder를 통해서 구성하고 subtmit한다.

이후 해당 Topology는  사전에 기동된 Storm 프로세스 ( Nimbus )에 전달되고 Nimbus는 각 Supervisor로 할당하여 작업을 수행한다.

작업이 수행되면 별도로 Worker 프로세스가 기동되며 Worker 프로세스내에 Topolog상의 component가 분배되어 Thread로 수행된다. 커스터마이징을 통해서 수동으로 component위치를 지정하여 자원사용량을 분산시키는 것도 가능한다. 

topology 별로 최소 worker 1개 이상이 필요하고 그 이상 지정도 가능하다.

4. Architecture

Nimbus : HDFS의 Namenode와 유사하여 마스터 노드의 역할을 한다. Topology를 받아서 각 Supervisor에게 배포하고 작업을 수행하며 추적한다.

Supervisor : Nimbus로부터 명령을 받아서 Worker 프로세스르 구동한다.

Worker : 실제 컴포넌트 (Bolt, Spout)가 할당되어 task를 수행한다.


5. 정리
분산 병렬처리를 위해서는 기본적으로 Key/Value형태의 데이터로 구성되어야 핞다. (ex, Map/Reduce, Spark 등)

Storm도 마찬가지로 데이터 전달시 Key/Value형태로 전달하도록 되어있다.

빅데이터를 이야기 할 때 항상 나오는 Iteration 과 Interactive를 좀더 공부할 필요가 있다.

 

6. Storm과 Spark 간단비교

 a. Storm
Apache에서 Storm을 보면 Distributed, real-time computation system으로 소개된다.

실제 Spout나 Bolt의 구현부를 보면 건단위의 흐르는 데이터 (Streaming...) 처리에 적합한 구조로 되어있다.

로그파일은 어쨌든 파일인데 왜 Storm으로 처리하는 예제가 나올까라는 의문을 가졌었는데 로그파일의 경우 실시간 row단위로 쌓이는 데이터이기 때문에 흘러가는 데이터로 보는게 맞다는 생각이 들었다.

어쨌든 Storm은 데이터를 저장하는 것이 아니라 계속 흘려보내는 의도로 출발된 구조로 보면 되겠다.

번외로 Spout와 Bolt간의 특정데이터를 공유해야 할 필요가 있을때는 IMDG를 사용할 수 있을 듯 하다.


 b. Spark

Apache에서 Spark는 Fast and general engine for large-scale data processing 으로 소개된다.
내용과 실제 구현방법을 보면  배치성처리 컨셉이 강하며, 기본적으로는 Map/Reduce처리방식과 유사하다.

RDD개념을 도입하여 Disk I/O를 최소화 했기 때문에 iteration에 강하고, 결과를 다시 인풋으로 받는 (ex, kmeans) 알고리즘 구현시 강점이 있다. Stream처리를 위한 개념으로 Spark Streaming도 있지만 결국 간격이 짧은 배치를 수행하는 컨셉이다.
기본적으로 RDD생성은 파일 또는 다른 RDD에서만 가능하기 때문에 실시간 Stream에는 적합하지 않는 것으로 보인다.


'BigData' 카테고리의 다른 글

Hadoop Securiy for Multi tenant #1  (0) 2017.01.17
Flume-Kafka-Elasticsearch 테스트  (0) 2016.03.14
CAP 정리  (0) 2014.11.28
NoSQL  (0) 2014.11.28
Hadoop 이란  (0) 2014.11.28

Spark관련 논문 Resilient Distributed Datasets 을 읽던 중 coarse-grained 와 fine-grained 의 내용이 있어서 간단히 정리를 해본다.

영어를 사용하는 문화권에서는 확실히 이해가 쉬울 듯 한데..

grain은 곡식을 하나하나의 낱알로 만드는 작업을 의미한다. 이 작업을 듬성듬성 크게 할지, 아니면 곱고 가늘게 할지에 따라서 coares와 fine으로 표현한다.

이를 소프트웨어 공학에서는 하나의 프로세스를 쪼개는 정도에 따라서 구분하는 정도로 사용한다.

 

1. Fine-Grained

잘게 쪼개는 것으로 예를 들면 다음과 같다.

타행이체의 경우 당행잔액조회 => 타행입금계좌 확인 => 타행으로송금 단계로 나눌 수 있고 이를 각각 메소드로 구성할 수 있다. 또한 이 기능들이 다양하게 활용된다면 메소드를 모아서 하나의 모듈로 만들 수 도 있어서 변경이 발생했을 때 보다 유연하게 개발할 수 있는 장점이 있다. 또한 유사하지만 다른 새로운 비지니스가 만들어 질 때 재사용을 통해서 보다 빠르게 구현할 수 있다.즉, Flexible System상에서 유용하다.

 

2. Coarse-Grained

덩어리로 작업한다.

타행이체의 경우 그냥 "타행이체" 하나 만들어서 사용한다. 일반적으로 EnterpriseApplicationDesign에서는 선호하지 않는 방식이지만 Distributed System상에서 유용하다.

 

그동안은 Java기반의 EnterpiseApplication을 주로 수행했기 때문에 1번이 많이 친숙하지만, 앞으로는 BigData를 위한 병렬처리쪽으로 구현이 필요한 경우(Spark,Akka등..) 가 생길 것 같아서 2번으로의 전환이 필요할 것 같다.

 


정리 및 첨언

최근 프로그래밍의 추세도 함수형 프로그래밍이라고 하는데 객체지향과 상반된다고 오해하는 경우가 있다. 

함수형 프로그래밍 = 순차적 프로그래밍 으로 보는 것은 옳지 않다.


내 생각에는 함수형 프로그래밍이라는 것은 수학적함수와 비슷한 개념으로 closure전달이 가능하다는 개념으로 보는 것이 더 낫지 않나 싶다. 대표적인 예를 scala로 볼 수 있다.


RDD논문을 보면 transformation에 대한 설명들이 나오는데 수학개념을 통해서 표현하면 매우 쉽게 이해할 수 있다. (ex, Map(a) => b ) 

Spark구현을 Scala로 한 것은 그 때문이 아닐까 혼자 생각해본다.

 

 

위키백과사전에서 찾아보면 다음과 같은 내용으로 나온다.

CAP 정리, 또는 브루어의 정리(Brewer -)는, 다음과 같은 세 가지 조건을 모두 만족하는 분산 컴퓨터 시스템이 존재하지 않음을 증명한 정리이다.

  • 일관성(Consistency): 모든 노드가 같은 순간에 같은 데이터를 볼 수 있다.
  • 가용성(Availability): 모든 요청이 성공 또는 실패 결과를 반환할 수 있다.
  • 분할내성(Partition tolerance): 메시지 전달이 실패하거나 시스템 일부가 망가져도 시스템이 계속 동작할 수 있다.

 

 

RDBMS로는 더이상 처리하기 힘든 대용량의 데이터를 어떻게 처리해야 하는가에 대해서 Hadoop 공부도 하고 NoSQL공부도 하던차에 찾은 자료이다.

과거 DBMS에서 이야기했던 ACID의 기본개념은 모두가 잘 알고 있다.

Atomic(원자성)

Consistent(일관성)

Isolated(고립성)

Durable(영속성)

 

그런데 QCon에서 구글에서 다음과 같은 의미가 될수도 있다고 발표했다.

Associative(결합) : 결합법칙이 적용되어야 한다. A+B+C = (A+B)+C = A+(B+C)

Commutative(교환) : 교환법칙이 적용되어야 한다.

Idempotent(멱등성) : 반복작업을 해도 결과는 변화하지 않아야 한다.

Distributed

 

이러한 내용은 클라우드 환경을 의미하는데, 이에 대한 또 다른 개념으로 BASE트랜잭션에 대한 소개가 있다.

Eric Brewer(UC Berkeley 교수)는 ACID와 대조적으로 가용성과 성능을 중시하는 특성을 가진 분산 시스템의 특성을 'BASE'라는 용어로 표현했다.

 

Basically Available
분산 시스템이기 때문에 항상 가용성을 중시한다. 반대로 말하면, 클라우드에서 분산되어있는 것은 필수이다.
클라우드의 Basically Availability의 실현은 친숙한 것들은 Optimistic Locking 및 큐 등이 있다. 

Soft-State
Soft-State는 '노드의 상태는 내부에 포함된 정보에 의해 결정되는 것이 아니라 외부에서 전송된 정보를 통해 결정된다는 상태의 사고 방식'이다.
중요한 것은 외부에서 보내진 정보에 의해 결정된다는 것이다. 즉, 떨어진 노드 간의 데이터 업데이트는 데이터가 노드에 도달한 시점에서 갱신된다. 
밖에서 받은 정보로 상태를 업데이트하므로 Soft-State하다고 생각한다는 사상이다.

Eventually Consistent
하지만 Soft-State 예제에서, 데이터를 해당 노드에 도달할 때까지는 데이터에 일관성이 없는 상태이다. 
그러나 데이터가 도착하기만 하면 또한 무결성을 보장 수 있으므로, 그 상황은 일시적이다. 그래서 일정 시간이 지나면, 다시 Consistency를 충족시킬 것이다. 
이것을 Eventually Consistent한다.
시스템상에서 일시적으로 Consistent하지 않은 상태가 되어도 일정 시간 후에는 Consistent 상태가 되는 성질을 우리는 Eventually Consistency한다.

 

참조

http://eincs.com/2013/07/misleading-and-truth-of-cap-theorem/

http://www.cs.berkeley.edu/~brewer/cs262b-2004/PODC-keynote.pdf

 

 

NoSQL은 분산데이터베이스로 CAP중 P에 집중하는 것이며, RDBMS의 기본사상에는 P가 빠져있다라고 보는 것이었다.

(2016-05-09 추가) 그러나 CAP이론으로는 설명이 부족한 부분도 있고, 한국 Wiki에서는 P에 대한 개념이 잘못되어 있는 부분이 있다. P는 C,A와는 약간 다르게 네트워크에 대한 속성이기 때문에 어느정도의 지연은 감내할 수 밖에 없다.

간단히 보자면 NoSQL역시 네트워크 장애상황에서는 C와 A중 많아도 하나밖에 선택할 수 없다.

결국 정상상황에 대한 분산시스템 동작을 설명할 수 없고, PACELC을 살펴보면 보완이 된다.

이 부분에 대해서는 추후 정리해야겠다!

 

 

'BigData' 카테고리의 다른 글

Flume-Kafka-Elasticsearch 테스트  (0) 2016.03.14
Storm특징 및 Spark와의 차이점  (0) 2014.12.12
NoSQL  (0) 2014.11.28
Hadoop 이란  (0) 2014.11.28
BigData 정의  (0) 2014.11.28

 

'BigData' 카테고리의 다른 글

Flume-Kafka-Elasticsearch 테스트  (0) 2016.03.14
Storm특징 및 Spark와의 차이점  (0) 2014.12.12
CAP 정리  (0) 2014.11.28
Hadoop 이란  (0) 2014.11.28
BigData 정의  (0) 2014.11.28

+ Recent posts