블로그 이미지
평범하게 살고 싶은 월급쟁이 기술적인 토론 환영합니다.같이 이야기 하고 싶으시면 부담 말고 연락주세요:이메일-bwcho75골뱅이지메일 닷컴. 조대협


Archive»


 
 

클러스터 상에서 하둡 배포 아키텍쳐


조대협 (http://bcho.tistory.com)


오늘 빅데이타 관련 교육을 받다가 클라우드 상에서 하둡 클러스터 활용에 대한 영감을 받은 부분이 있어서 정리해보고자 한다. 하둡의 경우에는 On-prem 환경에 적절하게 디자인이 된 오픈 소스라서, 이걸 클라우드에서 사용할 경우에도 on-prem에서 사용하는 형태와 유사하게 사용하는 경우가 많다. 일종의 습관 또는 관성이라고 해야 하나? 인프라가 바뀌면 그 장점에 맞는 아키텍쳐를 선택해야 하는데, 이 부분을 놓치고 있지 않았나 싶다.

Job별 클러스터를 생성하는 아키텍쳐

job을 수행하는 방법을 보면, 일반적으로 On-Prem에서 사용하는 방법은 하나의 하둡 클러스터에 Job을 실행하고 Job이 끝나면 다음 Job을 수행하는 방식을 사용한다.



이러한 경험(습관)때문인지 보통 클라우드 상에 하둡 클러스터를 만들어놓고 그 클러스터에 On-prem과 마찬가지 방식으로 Job을 넣고 그 작업이 끝나면 같은 클러스터에 Job을 넣는 방식을 사용한다.

그런데 클라우드의 특성상 자원이 거의 무한대인데, 여러개의 Job을 하나의 클러스터에서 순차적으로 실행할 필요가 있을까?


Job별로 클러스터를 생성해서 연산을 하고 Job이 끝나면 클러스터를 끄는 모델을 사용하면, 동시에 여러 작업을 빠르게 처리할 수 있지 않을까?



이 경우 문제가 될 수 있는 것이 같은 데이타셋을 가지고 여러가지 Job을 실행할 경우 기존의 On-Prem의 경우에는 동시에 같은 데이타셋에 접근할 경우 오버로드가 심하기 때문에, 어렵지만 클라우드의 경우에는 바로 HDFS를 사용하는 것보다는 GCS와 같은 클라우드 스토리지를 사용하는데, 여기서 오는 장점이 이런 클라우드 스토리지에 저장된 데이타는 동시에 여러 하둡 클러스터에서 접근이 가능하다.


이러한 아키텍쳐를 생각하게된 이유는 구글 클라우드의 특성 때문인데, 구글 클라우드의 과금 모델은 분당 과금 모델을 사용한다. 그래서 Job별로 클러스터를 전개했다가 작업이 끝난 다음에 끄더라도 비용 낭비가 없다. 시간당 과금인 경우에는 클러스터를 껐다켰다 하면 비용 낭비가 발생할 수 있기 때문에 바람직하지 않을 수 있다. 예를 들어서 1시간 10분이 걸리는 작업과 20분이 걸리는 작업을 각각 다른 클러스터에서 돌린다면 2시간, 그리고 1시간 비용이 과금되기 때문에 총 3시간이 과금된다.

그러나 구글의 분당 과금을 적용하면 총 1시간30분이 과금되기 때문에 비용이 1/2로 절감된다.


또한 구글 클라우드의 경우 하둡 클러스터 배포시간이 통상 90초이내로 빠르기때문에, Job마다 클러스터를 생성하고 끈다고 해도, 실행 시간이 크게 늘어나지 않는다.


클러스터별로 인프라를 최적화

만약에 위에처럼 Job별로 클러스터를 나눈다면, Job 의 특성에 맞춰서 클러스터의 인스턴스 수나 구조(?)를 변경하는 것도 가능하다.

즉 많은 컴퓨팅 작업이 필요한 Job이라면 클러스터에 많은 인스턴스를 넣고, 그렇지 않다면 인스턴스 수를 줄일 수 있다.




조금 더 나가면, 상태 정보 같이 HDFS에 저장하는 데이타가 적을 경우 워커노드가 중간에 정지되더라도 전체 연산에 크게 문제가 없을 경우에는 Preemptible VM과 같이 가격은 싸지만 저장 기능이 없는 VM의 수를 늘려서 전체 비용을 낮출 수 있다.




여기서 한걸음 더 나가면, 구글 클라우드의 인스턴스 타입중의 하나가 Cutomizable 인스턴스로 CPU와 메모리 수를 마음대로 조정할 수 있다. 즉 Job이 메모리를 많이 사용하는 Spark과 같은 Job일 경우 클러스터를 구성하는 인스턴스에 CPU보다 메모리를 상대적으로 많이 넣고 구성하는 것들이 가능하다.


아키텍쳐 설계도 의미가 있었지만, 그동안 간과하고 있었던 점이 기술이나 인프라가 바뀌면 활용 하는 방법도 다시 고민해야 하는데, 그동안의 관성 때문인지 기존 시스템을 활용하는 방법을 그대로 의심 없이 사용하려 했다는 것에 다시한번 생각할 필요가 있었던 주제였다.






저작자 표시 비영리
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

Google 앱앤진에 node.js 애플리케이션을 배포하기


조대협 (http://bcho.tistory.com)

PaaS 서비스란?

PaaS란 Platform as a service의 약자로, 간단하게 설명하면, Linux VM등에 직접 node.js나 기반 환경을 설치하고 디스크와 네트워크 구성, 오토스케일링등의 구성이 필요 없이, 개발자가 작성한 코드만 올려주면, 이 모든 것을 클라우드에서 대행해주는 서비스의 형태이다.

인프라 운영을 위한 별도의 작업이 필요하지 않기 때문에, 숫자가 적은 기업이나 개발에만 집중하고 싶은 기업에는 적절한 모델이라고 볼 수 있다.

근래에 스타트업 비지니스가 발달하고 또한 사용하는 기술 스택들이 복잡해짐에 따라 각각의 기술 스택에 대한 설치나 운영에 대한 인력을 두기보다는 PaaS와 같은 매니지드 서비스를 이용해서 애플리케이션을 개발하는  방식이 스타트업을 중심으로 많이 이루어지고 있다.

구글 클라우드 소개

구글 클라우드는 전세계에 걸쳐 유투브와 구글 검색, 이메일등의 서비스를 하는 구글의 인프라의 경험을 구글 외부의 개발자들에게 개방하기 위해서 개발된 클라우드 서비스이다.

글로벌을 대상으로 서비스를 하던 경험을 기반으로 글로벌 그리고 대용량 서비스에 적절한 특징들을 많이 가지고 있는데, 그 중에서 눈여겨 볼만한것이 네트워크와 빅데이타 서비스이다.

네트워크

구글은 자체 서비스를 위해서 전세계에 걸쳐서 많은 네트워크 망을 가지고 있다. 특히 전세계에 걸쳐 70개 이상의 Pop (Point of Presence)라는 서버들을 보유하고 있는데, 구글 클라우드에서 동작하는 애플리케이션은 클라이언트가 직접 그 데이타 센터의 서버로 인터넷을 통해서 접속하는 것이 아니라, 먼저 가장 가까운 Pop 서버로 연결이 된 후, Pop 서버와 구글 클라우드 데이타 센터간은 구글의 전용 광케이블을 이용해서 접속이 되기 때문에 빠른 네트워크 성능을 보장한다.

예를 들어 한국에서 미국의 서버를 접속하게 되면 일반 인터넷망을 타는 것이 아니라, 가까운 일본에 있는 구글 Pop 서버를 접속한 후에, 구글 광케이블망을 통해서 미국 데이타 센터에 접속하게 된다. 얼마전 7월에 일본-미국을 연결하는 20TB의 구글 클라우드 전용망이 오픈되었기 때문에, 훨씬 더 빠른 접속 속도를 보장받을 수 있다.

이런 특징 때문에, 구글 클라우드를 사용할 경우 여러 국가에 서비스를 제공하는 글로벌 서비스의 경우 이러한 망 가속의 잇점을 볼 수 있다.


또한 내부 네트워크 역시, 1 CPU당 2 GB의 대역폭을 제공한다. (실제 테스트해보면 1.6~1.8 GB정도가 나온다) 최대 8 CPU에 16 GB의 대역폭 까지 지원하기 때문에, 내부 노드간 연산이 많거나 또는 노드간 통신이 많은 클러스터링 솔루션을 사용할때 별도의 비용을 지불하지 않고도 넉넉한 네트워크 대역폭 사용이 가능하다.

빅데이타

구글은 사람들에게 알려진바와 같이 데이타를 기반으로 한 서비스에 강하며 특히 빅데이타를 처리하는 능력이 뛰어난 회사이다. 이러한 빅데이타 처리 기술이 클라우드 서비스로 제공되는데, 알파고와 같은 예측 통계학적인 머신러닝이나 딥러닝 이외에도, 분석 통계학적인 데이타 분석 서비스가 많은데 그중에서 특출난 서비스들로 Pub/Sub, Dataflow, BigQuery 등이 있다.

Pub/Sub은 전달 보장이 가능한 대용량 큐 시스템이다. 오픈소스 Kafka와 같은 서비스라고 보면 되고, 이러한 분산큐를 직접 깔아서 운영하기 어려운 사람들에게 쉽게 대용량 큐 서비스를 제공한다.

Dataflow는 스트리밍 및 배치 분석 시스템인데, Spark Streaming이나 Apache Flink와 같은 스트리밍 프레임웍과 유사하다고 보면된다. 윈도우,트리거,워터마크와 같은 스트리밍 서비스에서 발전된 개념을 이미 내장하고 있다.

마지막으로 BigQuery는 대용량 데이타 저장/분석 시스템으로 SQL과 같은 문법으로 데이타 분석이 가능하며, 데이타 저장 비용은 구글에서도 가장 싸다는 데이타 저장소인 CloudStorage 보다 저렴하며, 1000억개, 4TB의 레코드에 대해서 like 검색을 하는데 소요되는 시간이 불과 30여초로, 빠른 성능을 보장한다. (이 30초 동안에 CPU가 수천개, DISK역시 수천개가 사용된다.)


구글 클라우드 앱앤진

오늘 살펴볼 서비스는 구글 클라우드 중에서도 앱앤진이라는 PaaS 서비스이다. 구글은 처음 클라우드 서비스를 시작할때 PaaS 기반의 서비스를 제공하였고, 내부적으로도 PaaS 서비스를 오랫동안 제공해온 만큼, 진보된 형태의 PaaS 플랫폼을 가지고 있다.

그중에서 이번에는 새롭게 앱앤진 Flex environment 라는 새로운 서비스를 소개 하였다.

Flex environment에는 기존의 Java,PHP뿐 아니라, 요즘 스타트업등에서 많이 사용되는 Python, Ruby on rails 그리고 node.js를 지원한다.

그리고 재미있는 점 중의 하나는 일반적인 PaaS가 VM에 대한 로그인 (telnet 이나 SSH)를 지원하지 않는데 반하여, Flex environment 는 SSH 로그인을 제공함으로써, 고급 사용자들에게 많은 기능과 디버깅에 있어서 편의성을 제공한다.

계정 가입

자아 그러면 이제, 구글 앱앤진 Flex environment를 이용하여, node.js 애플리케이션을 배포해보도록 하자.

먼저 GCP 클라우드를 사용하기 위해서는 구글 계정에 가입한다. 기존에 gmail 계정이 있으면 gmail 계정을 사용하면 된다. http://www.google.com/cloud 로 가서, 좌측 상당에 Try it Free 버튼을 눌러서 구글 클라우드에 가입한다.




다음 콘솔에서 상단의 Google Cloud Platform 을 누르면 좌측에 메뉴가 나타나는데, 메뉴 중에서 “결제" 메뉴를 선택한후 결제 계정 추가를 통해서 개인 신용 카드 정보를 등록한다.


개인 신용 카드 정보를 등록해야 모든 서비스를 제한 없이 사용할 수 있다.  단 Trial의 경우 자동으로 한달간 300$의 비용을 사용할 수 있는 크레딧이 자동으로 등록되니, 이 범위를 넘지 않으면 자동으로 결제가 되는 일이 없으니 크게 걱정할 필요는 없다. (사용자가 Plan을 올려야 실제 카드에서 결재가 된다. 그전에는 사용자의 카드에서 결재가 되지 않으니 걱정하지 마시기를)


프로젝트 생성

계정 생성 및 결제 계정 세팅이 끝났으면 프로젝트를 생성한다.

프로젝트는 VM이나 네트워크 자원, SQL등 클라우드 내의 자원을 묶어서 관리하는 하나의 집합이다. 여러 사람이 하나의 클라우드를 사용할때 이렇게 프로젝트를 별도로 만들어서 별도로 과금을 하거나 각 시스템이나 팀별로 프로젝트를 나눠서 정의하면 관리하기가 용이하다.


화면 우측 상단에서 프로젝트 생성 메뉴를  선택하여 프로젝트를 생성한다.



프로젝트 생성 버튼을 누르면 아래와 같이 프로젝트 명을 입력 받는 창이 나온다. 여기에 프로젝트명을 넣으면 된다.


node.js 애플리케이션 준비

클라우드 프로젝트가 준비되었으면, 이제 구글 클라우드에 배포할 node.js 애플리케이션을 준비해보자.

Node.js 애플리케이션은 Express 프레임웍을 이용한 간단한 웹 애플리케이션을 작성해서 배포하도록 한다.

기본적으로 nodejs와 npm이 설치되어 있다고 가정한다. 이 글에서는 node.js 4.4.4 버전과 npm 2.15.1 버전을 기준으로 작성하였다.

Express generator 설치

Express 프로젝트는 Express 프로젝트 고유의 디렉토리 구조와 의존되는 파일들을 가지고 있다. 그래서 프로젝트를 생성하려면 Express generator가 필요하다. Express generator가 Express 프로젝트에 맞는 프로젝트 구조를 생성해주는데, Express generator를 설치하려면 아래 그림과 같이

% npm install express-generator -g

명령을 사용하면 설치가 된다.



프로젝트 생성

Express generator 설치가 끝났으면 이제, express 프로젝트를 생성해보자.

다음 명령어를 이용하여 helloappengine이라는 Express 프로젝트를 생성한다.

% express --session --ejs --css stylus helloappengine




Express 프로젝트 및 Express 프레임웍에 대해서는 http://bcho.tistory.com/887 http://bcho.tistory.com/888 글을 참고하기 바란다.

코드 수정

생성된 코드에서  ~/routes/index.js 파일을 다음과 같이 수정한다.


var express = require('express');

var router = express.Router();


/* GET home page. */

router.get('/', function(req, res, next) {

 res.render('index', { title: 'Hello Appengine' });

 console.log('Hello Appengine');

});


module.exports = router;


의존성 모듈 설치와 node.js 런타임 버전 정의

Express 애플리케이션 개발이 다 끝났다. Express 애플리케이션을 실행하려면, Express 프로젝트에 필요한 모듈들을 설치해야 하는데, 의존 모듈들은 ~/package.json에 이미 자동으로 생성되어 있다.

이 파일을 다음과 같이 수정한다.

“engines”라는 항목에 node.js의 버전을 아래와 같이 명기하는데, 이는 구글 앱앤진이 이 애플리케이션을 수행할때 어느 버전의 node.js를 가지고 수행을 할지를 지정한다.


{

 "name": "helloappengine",

 "version": "0.0.0",

 "private": true,

 "scripts": {

   "start": "node ./bin/www"

 },

 "engines":{

    "node":"4.4.4"

 },

 "dependencies": {

   "body-parser": "~1.15.1",

   "cookie-parser": "~1.4.3",

   "debug": "~2.2.0",

   "ejs": "~2.4.1",

   "express": "~4.13.4",

   "morgan": "~1.7.0",

   "serve-favicon": "~2.3.0",

   "stylus": "0.54.5"

 }

}




이 의존성 모듈 설치는 package.json 파일이 있는 디렉토리에서 아래와 같이

% npm install

명령어만 실행해주면 자동으로 설치된다.


테스트

샘플 애플리케이션 개발 및, 이를 실행하기 위한 환경 설정이 모두 끝났다.

그러면 이제 샘플 애플리케이션을 로컬에서 실행해보자.

실행은 ~/ 디렉토리에서 다음과 같은 명령을 실행하면된다.

% node ./bin/www



실행한 후, 결과를 확인하려면 http://localhost:3000 번으로 접속하면 아래와 같은 결과가 나오는 것을 확인할 수 있다.



구글 앱앤진으로 배포 준비

애플리케이션 개발 및 테스트가 끝났으면 이제 구글 앱앤진으로 이 애플리케이션을 배포해보자.

app.yaml 파일 작성

구글 앱앤진 Flex environment 로 애플리케이션을 배포하기 위해서는 애플리케이션에 대한 기본 정보를 app.yaml에 정의해야 한다. 이 파일은 배포할 node.js 애플리케이션이 있는 ~/ 디렉토리에 위치 시킨다.

runtime은 어떤 언어 (node.js , ruby 등)을 지정하고, VM으로 실행할지를 vm:true 로 정의한다.


runtime: nodejs
vm: true


Google Cloud SDK 설치

다음으로 배포를 하려면, gcloud라는 명령을 사용해야 하는데, 이 명령어는 Google Cloud SDK를 설치해야 사용할 수 있다. Google Cloud SDK는 https://cloud.google.com/sdk/downloads 에서 다운 받아서 설치한다.

Google cloud SDK 설정하기

Google cloud SDK 설치가 끝났으면, 혹시 google cloud SDK가 업데이트 되었을 수 있으니, 다음 명령어를 이용하여 최신 SDK로 업데이트 한다. (알파,베타 버전과 같은 신 기능이 들어가면 업데이트가 된다.)


% gcloud component update


라는 명령어를 수행하면 다음과 같이 업데이트 된 내용이 나오면서 업데이트 를 할 것인지 물어보고 “Y”를 선택하면 자동으로 Google Cloud SDK를 업데이트 한다.



Google Cloud SDK 배포가 끝났으면 gcloud 명령을 이용하기 위해서 초기화 작업을 해야 한다. 초기화 작업은 gcloud 명령을 사용했을때, 내 구글 클라우드 프로젝트 중 어느 프로젝트에 명령을 내릴 것인지, 그리고 어떠한 구글 계정을 사용할것인지 그리고 명령을 내릴때 어떤 리전을 디폴트로 해서 명령을 내릴것인지를 정하는 것이다. 사용자에 따라서 여러개의 프로젝트를 가질 수 도 있고, 또한 관리 목적상 여러개의 클라우드 계정을 가질 수 도 있기 때문이다.

초기화 방법은 다음과 같이 명령어를 실행하면 된다

% gcloud init

이 명령을 사용하면, 앞에서 언급한 바와 같이, gcloud 명령을 내릴 때 사용할 계정과, 디폴트 프로젝트 그리고, 리전을 선택하게 된다.


이제 배포를 위한 모든 준비가 끝났다.

구글 앱앤진으로 배포

이제 배포를 해보자. 배포는 매우매우 쉽다.

앞서 작성한 Express 애플리케이션이 있는 ~/ 디렉토리에 가서 다음 명령어를 수행하면 된다.

% gcloud app deploy

명령을 실행하면 다음과 같이 node.js 애플리케이션이 배포 되는 과정을 볼 수 있다.

배포는 수분이 소요된다. (내부적으로는 Docker 컨테이너를 이용하여 배포가 된다.)

서비스 기동확인

배포가 완료되면 자동으로 서비스가 기동이 된다.

서비스 기동 확인은 http:{프로젝트명}.appspot.com 으로 자동으로 서비스가 뜨게 된다.

해당 URL을 접속해보자. 여기서는 프로젝트명이 “useful-hour-138023”이다.


서비스가 정상적으로 기동 됨을 확인하였다.

모니터링

구글 클라우드 콘솔에 들어가 보면 현재 기동중인 node.js 앱을 확인할 수 있다.

콘솔에서 “App Engine”을 선택하면 다음과 같은 화면이 나온다.



아래 Instances 부분을 보면 Flexible 이라는 이름으로 현재 2개의 인스턴스가 기동되고 있고, 평균 QPS (Query Per Second : 초당 처리량)이 10.898 인것을 확인할 수 있다.


매니지드 서비스이기 때문에, 부하가 늘어나면 자동으로 인스턴스를 추가하고 줄어들면 자동으로 삭제하여 부하에 탄력적으로 대응을 자동으로 해준다.


로그 모니터링은 클라우드 콘솔에서 “Logging”이라는 메뉴를 선택하면 아래와 같은 화면이 나온다.


앱앤진 관련 request log 및 기타 로그들이 다 나오는데, 앞서 샘플코드에서 console.log(“Hello Appengine”) 명령어를 이용하여 Stdout으로 “Hello Appengine”이라는 문자열을 출력하도록 하였기 때문에, 이 문자열이 제대로 출력되었는지를 확인해보자.

App Engine 을 선택하고, 다음 “stdout”을 선택하면 위와 같이 앱앤진의 Stdout으로 출력한 로그들만 볼 수 있는데, 위와 같이 “Hello Appengine” 문자열이 출력된것을 확인할 수 있다.

수정 및 재 배포

그러면 다음으로 애플리케이션을 수정해서 배포해보자. routes/index.js를 다음과 같이 수정해보자


var express = require('express');

var router = express.Router();


/* GET home page. */

router.get('/', function(req, res, next) {

 res.render('index', { title: 'Hello Appengine is updated' });

 console.log('Hello Appengine is updated');

});


module.exports = router;



코드 수정이 끝났으면 배포를 해보자. 재 배포 역시 간단하게

%gcloud app deploy

명령어를 수행하면 간단하게 배포가 된다.

배포가 완료된 후 URL로 들어가서 확인을 해보면


애플리케이션이 업데이트 된것을 확인할 수 있다.

롤백

앱앤진의 장점 중에 하나가 배포도 쉽지만, 롤백도 매우 쉽게 가능하다는 것이다.

클라우드 콘솔에서 App Engine을 선택하고, 아래와 같이 Versions라는 메뉴를 선택하면 아래와 같은 그림을 볼 수 있다.




현재 두개의 버전이 배포되어 있고, 위의 최신 버전에 Traffic Allocation이 100%로 되어 있는 것을 확인할 수 있다. 이는 새로 배포된 버전으로만 트래픽이 100% 가고 있다는 의미인데, 롤백은 트래픽을 예전 버전으로 라우팅 해주고, 새버전의 서비스를 정지 시키면 된다.


아래 그림과 같이 예전 버전을 선택한 후에, 상단 메뉴에서 “Migrate Traffic”을 선택한다.



그러면 아래와 같이 트래픽이 이전 버전으로 100% 가고 있음을 확인할 수 있다.

그리고 나서 새 버전을 선택한 후 상단의 STOP 버튼을 눌러주면 아래 그림과 같이 새버전의 상태가 Serving 에서 Stopped로 변경된것을 확인할 수 있다.




예전 버전으로 롤백이 잘 되었는지를 확인해보자.

아래 그림처럼 예전 버전으로 롤백이 되었음을 확인할 수 있다.



버전별로 트래픽 분산하기

앱앤진의 장점 중의 하나가 여러 버전을 유지할 수 있고, 버전간에 트래픽을 자유롭게 조절할 수 있다. 예를 들어서 v1으로 90%, v2로 10% 의 트래픽을 보내는 것등이 가능하다.


이렇게 트래픽을 조절하는 것은 크게 2가지 방법으로 활용이 가능한데, 서버단의 A/B 테스팅과 카날리 테스팅이다.

A/B 테스팅은 사용자를 두개 이상의 집단으로 나눈후, 기능 A,B 에 대한 반응을 본 후, 반응이 좋은 기능을 선택하는 방식으로, 모바일 클라이언트단에서 많이 사용되고, 서버단에는 구현이 쉽지 않았는데, 트래픽을 버전별로 나눠서 주는 기능을 사용하면 손쉽게 A/B 테스팅을 수행할 수 있다.


다음으로 카날리 테스트는 옛날에 광부들이 광산에 들어갈때 카나리아 새를 데리고 들어가서 유독가스가 나오면 카나리아 새가 먼저 죽는 것을 보고 위험을 감지하는 방법에서 유래된것으로 서버 배포에서는 전체 사용자를 대상으로 새 버전을 배포하는 것이 아니라 1~2%의 사용자에게 배포해보고 문제가 없으면 전체 사용자에게 배포하는 개념으로, 마찬가지로 v2에 1~2%의 트래픽만 할당하고 나머지 98~99%는 v1에 할당하는 방식으로, 해서 v2에 대한 안정성 검증을 한 후에, v2를 전체 배포 하는데 활용할 수 있다.


버전간 트래픽 비율을 지정하는 방법은 클라우드 콘솔의 앱앤진 메뉴에서 Version을 선택하고 상단 메뉴에서 → 가 두개 겹쳐진 아이콘 (맨 우측)

를 선택하면 아래와 같이 Split traffic 이라는 메뉴가 나온다.

여기서 1개 이상의 Version을 추가한 후에, 각 버전으로 보낼 트래픽의 비중 (%)을 정의한다.






위의 예제에서는 xxx4403 버전으로 30%, xxxx3136 버전으로 70%의 트래픽을 보내도록 하였다.

설정을 완료한 후에 SAVE를 누르고, 다시 Version 부분을 보면, 수분 있다가 아래 그림과 같이 xxxx3136 버전에 70% 트래픽이 xxx4403 버전으로 가게 된다.


부가 기능에 대해서

구글 클라우드에서 앱앤진만 쓸 수 있는 몇가지 좋은 서비스 들이 있는데, 다음과 같다.

매니지드 memcached

앱앤진에서는 구글 매니지드 memcached 서비스를 사용할 수 있다 별도의 설정 없이 바로 사용이 가능하며, 최대 100GB 까지 사용이 가능하다. (100GB 이상도 요청하면 사용이 가능) Shared memcached의 경우에는 별도의 비용없이 일반적인 캐쉬로 사용이 가능하지만, 용량이나 성능등이 보장이 되지 않으니 주의가 필요하다.

https://cloud.google.com/appengine/docs/python/memcache/

보안 스캐닝 (Security Scanning)

매우 유용한 기능중의 하나가 보안 스캐닝 기능이다 앱앤진 메뉴에서 Security Scanning이라는 메뉴를 선택하면 앱앤진으로 개발한 웹 사이트에 대한 보안 스캐닝을 할 수 있는데, 한번만 스캐닝할 수 도 있고 자동 스케쥴 방식으로, 주기적으로 스캐닝 하는 것도 가능하다.


보안 정책이 수시로 업데이트 되기 때문에, 정기적으로 보안 스캔을 하는 것을 권장한다.

텍스트 검색 (Search)

node.js에는 지원하지 않지만, Python,Java,PHP,Go (앱앤진 Standard environment)에서만 지원되는 기능중 하나는 구글 검색 엔진과 같은 검색 엔진을 지원한다. 텍스트 검색 HTML 그리고 GEO_POINT (위/경도 기반 검색)이 가능하다.

https://cloud.google.com/appengine/docs/java/search/?hl=en_US

결론

지금까지 간략하게나마 구글 클라우드에 대한 소개, 앱앤진에 대한 개념 및, 간단한 node.js express 애플리케이션을 작성해서 배포해봤다. 다음글은 앱앤진에 대한 조금 더 구체적인 환경에 대해서 알아보도록 하겠다.


저작자 표시 비영리
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

빅쿼리 #2-아키텍쳐


조대협 (http://bcho.tistory.com)


이번글에서는 앞에서 소개한 구글의 대용량 데이타 저장/분석 시스템인 빅쿼리의 내부 아키텍쳐에 대해서 알아보도록 한다.

컬럼 기반 저장소

다음과 같은 테이블이 있다고 하자




전통적인 데이타 베이스는 파일에 물리적으로 데이타를 저장할때 개념 적으로 다음과 같은 방식으로 저장한다.


FILE 1 : “001;Cho;Terry;Seoul;30,002;Lee;Simon;Suwon;40,003;Kim;Carl;Busan;22”


그래서 하나의 레코드를 가지고 오면 그 레코드에 해당하는 모든 값을 가지고 올 수 있다.

반면 컬럼 기반 저장소의 경우에는 각 컬럼을 다음과 같이 다른 파일에 나눠서 저장한다.


FILE 1: 001:Cho,002:Lee,003:Kim

FILE 2: 001:Terry,002:Simon,003:Carl

FILE 3: 001:Seoul;002:Suwon:003:Busan

:


이렇게 컬럼 단위로 저장을 하게 되면 장점은 Last Name 컬럼의 내용만 읽고 싶을때 로우 단위로 저장한 시스템의 경우, 모든 데이타를 다 스캔해야 하는데, 컬럼 단위로 저장한 시스템은 Last Name을 저장한 파일 하나만 스캔하면 되고, Last Name 이외의 다른 컬럼의 데이타는 읽어드리지 않아도 되기 때문에 데이타 효율성이 높다.


그래서 특정 컬럼만 읽어서 개수를 세거나 통계를 내는 분석용 데이타 베이스(OLAP)  작업등에 유리하다.

Columnar databases boost performance by reducing the amount of data that needs to be read from disk, both by efficiently compressing the similar columnar data and by reading only the data necessary to answer the query.

In practice, columnar databases are well-suited for OLAP-like workloads (e.g., data warehouses) which typically involve highly complex queries over all data (possibly petabytes). However, some work must be done to write data into a columnar database. Transactions (INSERTs) must be separated into columns and compressed as they are stored, making it less suited for OLTP workloads. Row-oriented databases are well-suited for OLTP-like workloads which are more heavily loaded with interactive transactions.”

출처 : https://en.wikipedia.org/wiki/Column-oriented_DBMS

실제로 빅쿼리도 하나의 파일에 하나의 컬럼 데이타만 저장하도록 되어 있다.

빅쿼리는 앞의 글에서도 설명하였듯이 데이타의 안정성을 위해서 3개의 데이타 센터에 나눠서 데이타를 저장하는데, 각 컬럼을 저장하는 파일이 총 3개의 복제본으로 그림과 같이 각각 다른 데이타 센터에 나줘서 저장이 된다.


트리 구조의 데이타 처리 구조

실제로 빅쿼리의 시스템 구조는 다음과 같이 되어있다.



출처 https://codelabs.developers.google.com/codelabs/cp100-big-query/#3


GFS (Google File System)의 후속 파일 시스템인 분산 스토리지 Colossus가 맨 아래에서 저장소를 제공하고, Jupiter 라는 TB 급의 네트워크 망을 통해서, 컴퓨팅 노드와 통신을 한다.

그리고 연산을 담당하는 컴퓨팅 계층은 Leaf , Mixer 1, Mixer 0 계층으로 되어 있다.

이 컴퓨팅 계층은 디스크 없이 Colossus에서 읽은 데이타를 처리해서 각각 위의 계층으로 올리는 역할을한다.


다음 SQL이 어떻게 연산이 수행되는지를 살펴보면 아키텍쳐를 이해할 수 있다.




natality라는 테이블에서 1980~1990년대에 태어난 아이들의 수를 주(state)별로 그룹핑해서 내림차순으로 정렬한 후 상위 10개의 데이타만 출력해주는 쿼리이다.


이 쿼리를 수행하면 빅쿼리는 내부적으로 다음과 같은 연산을 수행한다.



  • STORAGE : 디스크에서 STATE,YEAR 컬럼만을 읽어드린다.

  • LEAF : 다음 각각의  LEAF 노드에서, 읽어드린 데이타를 가지고 1980~1990년대 데이타를 주 단위로 태어난 아이들의 수를 카운팅 한다.

  • MIXER 1:에서 LEAF에서 계산해온 주(STATE) 별 아이들의 수를 합친다.

  • MIXER 0:에서는 MIXER 1에서 올라온 모든 값을 합치면서 소팅을 한다. (머지 소트를 생각하면 된다.). 소팅이 끝난 후에, 맨 위의 10개의 레코드만을 리턴한다.


조인이나 그룹핑의 경우 조금 더 복잡한 연산이 실행되기는 하지만 큰 흐름은 유사하다.

다른 구조적인 특징

빅쿼리가 대용량과 성능을 지원하기는 하지만 일반적인 데이타 베이스와 다소 다른 특성을 가지고 있다.

NO-KEY,NO-INDEX (FULL SCAN ONLY)

빅쿼리에는 키나 인덱스의 개념이 없다. 무조건 풀스캔이다. (스캔의 범위를 조정할 수 있는 기법이 있는데 이는 나중에 설명하도록 한다.)

NO UPDATE,DELETE ROW

빅쿼리는 성능을 위해서 테이블에 데이타를 추가 (APPEND)하는 것만을 지원한다. 한번 입력된 데이타는 변경되거나 삭제될 수 없으며, 데이타가 잘못 입력되었을 경우에는 테이블을 지우고 다시 생성해야 한다. (이 문제를 해결하는 디자인 패턴에 대해서는 나중에 설명한다.)

EVENTUAL CONSISTENCY

데이타를 3개의 데이타 센터에 걸쳐서 복제하기 때문에, 데이타를 입력한 후 바로 조회하면 데이타가 조회가 되지 않을 수 있다. 이는 데이타를 복제하는데 소요되기 때문인데, 보통 바로 반영되거나 상황에 따라서 최대 수분이 걸릴 수 있다.


다음 글에서는 빅쿼리의 데이타 모델과 인터페이스에 대해서 알아보도록 한다.


참고 자료



저작자 표시 비영리
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

대용량 시스템 아키텍쳐 설계에 대한 강의를 진행합니다.


조대협입니다.

잠깐의 휴식 시간에 짬을 내서, 패스트 캠퍼스에서 대용량 시스템 아키텍쳐 설계에 대한 강의를 합니다.

4/9~4/10일 양일간입니다.



패스트 캠퍼스를 통해서 아키텍쳐 설계 강의를 하게되었습니다
이번에는 실습을 통해 저와 같이 설계를 하는 과정도 같이 들어갑니다.

강의를 개설하게 된 이유는 종종 아키텍쳐에 대한 컨설팅이나 도움을 요청하시는 분들이 있어서 시스템들을 살펴보면, 기술적인 부분에 체계가 안잡혀 있는 것도 문제지만 아키텍쳐를 정의하고 설계하는 흐름에 대해서 이해가 부족한 경우를 많이 봐왔습니다. 짧은 시간이지만 많은 도움이 되려고 합니다.


홍보 때문에 인터뷰도 했어요. http://www.fastcampus.co.kr/dev_workshop_architect_blog_instructor_1/


모처럼 많은 신청 부탁합니다.


신청은

http://www.fastcampus.co.kr/dev_workshop_architect/



저작자 표시 비영리
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

 IBM 블루믹스의 openwhisk 에 대한 소개


조대협 (http://bcho.tistory.com)


오늘 IBM의 블루믹스 세미나에 다녀왔습니다.

세미나 내용중에서 흥미로운 기술들이 있어서 간단하게 소개합니다.

IBM 블루믹스 클라우드의 새로운 기능으로 Openwhisk 라는 서비스입니다http://www.ibm.com/cloud-computing/bluemix/openwhisk/

https://developer.ibm.com/openwhisk/ 아마존의 람다 기능과 유사한 기능인데 개념을 보면 다음과 같다.

 

이벤트가 발생하면, 이벤트 내용을 받아서 비지니스 로직이 들어 있는 액션을 수행한다.

아래 그림을 보면 REST API로 호출하거나 또는 데이타 베이스에 어떤 내용이 변경이 되거나 또는 Kafka와 같은 메세지 큐에 새로운 메세지가 들어오면 정해진 규칙 (이를 Openwhisk에서 Rule이라고 한다.)에 따라서 비지니스 로직을 호출한다. 이 비지니스 로직 덩어리를 Action이라고 하는데, Action을 여러개로 묶어서 아래 그림과 같이 체이닝이 가능하다.



 

이벤트 방식으로 비지니스 로직을 Invoke해주는 방식인데, 뒷단에 ActionAuto scaling이 가능해서 시스템의 용량등에 상관 없이 사용이 가능하다.

또한 이 ActionSwift, node.js, Java 와 같이 다양한 언어로 구현이 가능하다.

개발자는 아래 인프라를 신경쓸 필요가 없이 비지니스 로직만 구현하면 된다는 것이다.

 

과금 정책은 실제 Action이 실행되는 시간만 과금이 된다. 해당 로직을 수행하는데 30ms만 걸렸다면 30ms에 대한 금액만 과금된다. 유사한 기능을 EC2와 같은 VM위에 올리면, CPU를 많이 사용하는 로직일 경우 계속 CPU가 큰 CM을 켜놔야 하기 때문에 비용이 많이 나오지만 이 구조를 사용하면 비용이 딱 사용한 부분만 나온다.

 

다른 흥미로운 점은 IBM이 이 기능을 개발하면서 이 Openwhisk를 오픈소스화 했다는 것이다.

소스는 https://github.com/openwhisk/openwhisk 에 있는데, 이 말은 블루믹스를 사용하지 않더라도 AWS나 구글 글라우드에 Openwhisk를 옮길 수 있다는 것이다. 즉 클라우드 락인에 대한 문제를 해결하고 시작했다는 것이다.

 

AWS 람다와 유사한데, 근래 들어서 이런 형태의 기능들이 클라우드에 많이 나오는 것 같다.

톰캣이나 파이썬 장고와 같은 웹서버나 미들웨어를 알필요도 없고 복잡한 설정이나 스케일링에 대한 고려를 할필요도 없고 클라우드 자체를 플랫폼으로 그위에 비지니스 로직만 올리는 형태로 점점 클라우드가 발전해 가는 모습이 보인다.  나중에는 미들웨어 없이 클라우드 자체에 코드만 올리는 형태가 되지 않을까? 이미 AWS에서는 람다, 다니나모, S3, API 게이트웨이등을 조합하면 별도의 미들웨어 없이 왠만한 API들은 구현이 가능하다.

 

저작자 표시 비영리
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

안드로이드 플랫폼 기본 아키텍쳐


조대협 (http://bcho.tistory.com)


안드로이드 플랫폼의 기반 아키텍쳐를 살펴보면 다음 그림과 같다.




리눅스 커널
일단 가장 아랫단에, Linux 커널 이 올라가 있다. 일반적인 Linux 커널과 크게 다르지는 않지만, 모바일 디바이스에 최적화된 전력 관리 기능이나 안드로이드에 최적화된 Binder IPC (프로세스간 커뮤니케이션) 부분등이 포함되어 있다.

시스템 라이브러리
리눅스 커널위에는 C로 구현된 몇가지 네이티브 라이이브러리들이 올라가 있다. 3차원 그래픽을 위한, OPEN GL, 로컬 데이타 베이스를 제공하는 SQLLite 데이타 베이스, 웹 브라우징을 위한 WebKit, 멀티미디어 재생을 위한 Media Framework들이 올라가 있다. 
이러한 시스템 라이브러리들은 내부적으로 JNI 인터페이스를 통해서 자바 코드로부터 호출되게 된다. 

안드로이드 런타임
이러한 시스템 라이브러리 위에, 안드로이드 런타임이 올라가 있는데, 안드로이드 런타임은 JVM (Java Virtual Machine)이다. 단, 모바일 애플리케이션을 위해서 최적화된 JVM으로 안드로이드는 달빅(Dalvik)이라는 이름의 VM이 올라간다. 이 달빅 JVM이 실제로 안드로이드 애플리케이션을 시작하게 되낟.   그리고, 그위에 코어 자바라이브러리들이 올라가게 된다. (java.*, javax.* ,org.* ...등)


애플리케이션 프레임웍
안드로이드 런타임 까지 기본 JVM과 자바 라이브러리가 올라갔다면 애플리케이션 개발 프레임웍은 라이브러리이다. 마치 서버 개발에서 자바 위에, JEE 나 스프링,Hibernate와 같은 프레임웍이 있는 것 같이 애플리케이션 개발용 프레임웍이 올라가 있다. 
  • Package manager : 어떤 애플리케이션들이 설치되어 있는지를 관리한다. 
  • Windows manager : 윈도우 화면을 관리 (윈도우란, 영역으로 맨 윗부분의 네비게이션바, 다이얼로그 형식으로 나오는 윈도우등등 모든 윈도우 시스템을 관리하는 부분이다.)
  • View manager : 기본적인 그래픽 컴포넌트를 관리 한다. 라디오 버튼이나, 탭, 버튼등. 
  • Resource manager  : 컴파일이 되지 않는 리소스를 관리한다. 예를 들어 폰 애플리케이션에 같이 패키징된 string, 이미지 파일등을 관리한다. (안드로이드 프로젝트상 main/res 내에 있는 것을 관리하는 듯)
  • Activity manager : 안드로이드의 액티버티를 관리한다. 이 액티버티는 안드로이드 애플리케이션내의 하나의 화면에 해당(?)하는 것으로, 이 액티버터의 생성 및 소멸까지의 라이프 싸이클을 관리한다.
  • Contents provider: 데이타 저장소에 대한 추상화된 계층으로, 이 Contents Provider 계층을 통하여, 데이타를 저장할 수 있고, 이 저장소를 다른 애플리케이션에게 공유하여 애플리케이션 간에 데이타를 공유할 수 도 있다.  
  • Location manager : 위치 관련 서비스 기능을 제공한다.  
  • Notification manager : notification bar에 중요한 이벤트를 보여주는 기능을 제공한다. (푸쉬 시스템도 여기서 관리 하나?)


기본 애플리케이션

그위에, 기본적으로 폰에 프리로드 되어 설치되는 애플리케이션들이 존재한다. 연락처, 메신져, 브라우져, 카메라등의 기본적인 애플리케이션 등이 이에 해당한다. 


저작자 표시 비영리
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

아키텍쳐 문서화는 어떤 도구를 사용하는게 좋을까?

조대협(http://bcho.tistory.com)


제 현재 본업은 아키텍트 입니다. 주로 시스템을 설계하는 역할을 하는데, 이 아키텍쳐 문서를 주로 PPT를 사용합니다. 문서는 워드로 만드는게 좋을 수 도 있고, EA나 StarUML등등 많은 툴이 있는데,  굳이 PPT를 사용하는 이유를 적어놓고자 합니다.

사실 예전에는 MS WORD로 설계문서를 만들었습니다. 만들어 놓으면 멋도 있고, 자세한 내용 표현이 가능해서 탐독하면서 이해하기도 좋습니다. 

그런데, 고객사의 요구 때문에, PPT로 바꾼후, 거의 습관처럼 PPT로 아키텍쳐 문서를 만들다 보니, 몇가지 장점이 있습니다.





1. PPT 는 표현에 제약이 없다.

아키텍쳐 디자인은 특성상 많은 다이어그램과 노트등을 달아야 하는데, WORD로 작성할 경우, 다른 툴에서 다이어그램을 그린 후 가져다 붙여야 합니다. 문서 만드는데 여간 노력이 많이 들어가고, 또한 UML 도구 같은 것을 사용하면 그 도구에서만 제공하는 다이어그래밍이 가능하지 다양하고 쉬운 다이어그래밍이 어렵습니다. 그냥 그리고 싶은 데로 표현하고 싶은데로 자유롭게 하면 되니 일단 문서 작성이 쉽습니다.


2. PPT는 발표용이지 문서용이 아니다

SI때나, 예전 전통적인 개발 방법론에서는 아키텍쳐 설계서 산출물이 나오면 이걸 받아서 개발자들이 잘 읽고 개발을 시작하는 프로세스였다면 근래의 개발 프로세스는 아키텍트가 설계를 하고,이 내용을 개발자들에게 설명을 합니다.

그냥 문서 하나 휙던지고 마는게 아니라는 겁니다. 예전 포스팅에서도 몇번 언급했지만, 문서화는 커뮤니케이션을 원할하게 하기 위한 하나의 도구이지, 산출물이 목적이 아닙니다.

그런점에서 PPT는 발표를 위한 도구인점에서 메리트가 많습니다. 보고용 자료가 아니라 발표/토론용 자료를 만드는 게 아키텍쳐 문서화의 목적이면 거기에 맞는 툴을 쓰는게 맞기 때문입니다.



저작자 표시 비영리
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

MSA 아키텍쳐 구현을 위한 API 게이트웨이의 이해 #1

조대협 (http://bcho.tistory.com)


MSA(마이크로 서비스 아키텍쳐, 이하 MSA)와 함께 근래에 떠오르고 있는것이 API 게이트 웨이이다. API 게이트웨이는 API서버 앞단에서 모든 API 서버들의 엔드포인트를 단일화하여 묶어주고 API에 대한 인증과 인가 기능에서 부터 메세지에 따라서 여러 서버로 라우팅 하는 고급기능 까지 많은 기능을 담당할 수 있다.

API 게이트웨이의 시작은 MSA가 SOA(서비스 지향 아키텍쳐)에서 시작한것 처럼 ESB (Enterprise Service Bus)에서 부터 시작 되었다. 그래서 ESB의 대부분의 컨셉을 많이 승계했는데, ESB의 실패와 단점을 보완해서 만들어진 사상이 API 게이트웨이이다. ESB가 SOAP/XML 웹서비스 기반의 많은 기능을 가지는 구조였다면, API 게이트 웨이는 JSON/REST 기반에 최소한의 기능을 처리하는 경량화 서비스 이다. 그리고 ESB는 SOA의 사상에서 개념적으로 탄생한 솔루션이라면, API 게이트 웨이는 ESB의 실패와, MSA, REST 구현 사례를 통해서 필요에 의해서 탄생한 솔루션이기 때문에, 그 실용성이 차이가 난다.


MSA에 대한 개념은 http://bcho.tistory.com/948 를 참고하기 바라며, 이 글은 API 게이트웨이에 대한 바른 이해를 돕고, API 게이트웨이를 도입하고자 하는데 필요한 내용을 서술하고자 한다.


API 게이트웨이의 주요 기능


먼저 API 게이트웨이의 주요 기능에 대해서 알아보자


인증/인가에 관련된 기능


API 게이트웨이의 가장 기본적인 기능은 API 에 대한 인증과 인가 관련 기능이다. 인증은, API 를 호출하는 클라이언트에 대한 identity(신분)를 확인 해주는 기능이고, 인가는 클라이언트가 API를 호출할 수 있는 권한이 있는지를 확인해주는 기능이다. 

쉽게 이야기 하면 내가 페이스북 계정을 가지고 있는 사용자가 맞는지 , API 호출시 어느 권한 (일반사용자, 관리자 권한)까지 호출할 수 있는지를 판단하여 API 호출을 허가하는 기능이라고 볼 수 있다.


API 토큰 발급


인증 인가를 거칠때 마다 매번 사용자의 인가/인증 절차를 거치기는 불편하다. 사용자로 부터 매번 사용자 ID와 비밀 번호를 받기는 번거롭고, 그렇다고 사용자 ID와 비밀 번호를 저장해놓는 것은 해킹의 빌미를 제공한다.

그래서 보통 사용하는 방식이 토큰이라는 방식을 사용하는데, 사용자 인가가 끝나면, 사용자가 API를 호출할 수 있는 토큰을 발급해준다. API 서버는 이 토큰으로 사용자의 identity 와 권한을 확인한후, API 호출을 허가해준다.


API 게이트 웨이는 클라이언트를 인증한 후, 이러한 API 토큰을 생성 및 발급해주는 역할을 한다.


 

<그림. 일반적은 토큰 발급 절차>


토큰 발급을 위해서는 먼저 클라이언트를 인증해야 한다.


클라이언트를 인증하는 방법은 가장 간단하게 사용자의 id와 password를 넣는 방법에서 부터, 공인 인증서를 이용하는 방법, 지문이나 OTP (One time password) 등을 이용하는 방법등 다양한 방법이 있다. 각 보안 요건에 요구 되는 다양한 방식에 따라서 클라이언트를 인증한 후에, apitoken을 발급하게 된다.


이때, 클라이언트에 대한 인증은 직접적으로 API 게이트웨이가 하지 않고 뒷단에 있는 인증 서버가 이를 수행하는데, 간단하게는 내부 계정 관리를 위한 Active Directory, LDAP 또는 RDBMS등이 될 수 도 있으며, 외부 인증 서버로는 예를 들어서 온라인 게임 서비스에 가입할때, 페이스북 계정을 사용하는 경우, 온라인 게임 서버가 페이스북에 이 사용자의 인증을 요청하고, 페이스북이 인증을 해주면 온라인 게임서버가 apitoken을 발급해주는 흐름등을 들 수 있다.


그래서 API 게이트웨이의 중요한 기능중의 하나는 다양한 인증 서버와 연계가 가능한 것이 좋다.


이렇게 발급된 토큰을 API를 호출할 수 있는 권한 정보와 연관이 되는데, 이 권한 정보를 토큰 자체에 저장하느냐 또는 서버에 저장해놓느냐에 따라서 두 가지 종류로 나눌 수 있다.

토큰 자체가 이러한 정보를 갖는 형태를 클레임 기반의 토큰 (Claim based token)이라고 하는데, 근래에 유행하는 JWT (JSON Web Token)이나 SAML 토큰등이 이에 해당한다. 예를 들어 토큰 자체가 아래와 같은 정보를 가지고 있는 형태라고 생각하면 된다. 


{

“name”:”Terry”,

“role”:[“admmin”,”enduser”]

“org”:”petstore”

}

<그림. 클레임 기반의 토큰 예>

JWT가 이러한 형태의 토큰인데 JWT에 대한 자세한 설명은 http://bcho.tistory.com/999 와 http://bcho.tistory.com/1000 를 참고하기 바란다.

클레임 기반의 토큰이 아닌 경우, 이러한 클레임 정보를 서버에 저장해놓게 되는데, 클라이언트로는 unique한 string만을 리턴해주는 경우이다.

 


<그림. 서버에 토큰을 저장하는 경우>


이 서버 기반의 토큰이 현재 일반적으로 가장 많이 사용되는 형태인데, token에 연관되는 정보가 서버에 저장되기 때문에 안전하고, 많은 정보를 저장할 수 있으며, token에 대한 정보를 수정하기가 용이하다. 그러나 서버단에서 별도의 토큰 저장소를 유지해야 하기 때문에 구현 노력이 더 높게 든다. 토큰은 매 API 호출마다 정보를 가지고 와야 하기 때문에, DBMS와 같은 FILE IO 기반의 저장소 보다는 redis, memcached와 같이 메모리 기반의 고속 스토리지를 사용하는 것이 좋다.


클레임 기반의 토큰은 이러한 토큰 저장소가 필요 없다는 장점이 있어서 구현은 용이하지만, 토큰 자체에 클레임 정보가 들어가 있기 때문에, 토큰의 길이가 커지기 때문에 일정 양 이상의 정보를 담기가 어려우며, 한번 발급된 토큰은 변경이 어렵다. 예를 들어 role:admin으로 관리자 권한으로 발급된 토큰은 서버쪽에서 파기가 불가능하기 때문에 토큰 통제가 어렵다는 단점을 가지고 있다. 그래서, 클레임 기반의 토큰을 사용할때는 토큰의 유효기간을 둬서 반드시 강제적으로 토큰을 주기적으로 재발급 받도록 하는 것이 좋다.


엔드포인트별 API 호출 인증


Apitoken이 발급되었으면, 클라이언트는 이 apitoken을 이용하여 API를 호출하는데, 이 때 API 게이트웨이는 apitoken을 검증함으로써 API 호출을 승인할지 여부를 결정한다.

서버에 토큰 정보가 저장되는 형태의 경우 매 API 호출 마다 해당 apitoken을 가지고 연관 정보를 토큰 저장소로 부터 읽어와서 비교한후, 그 정보를 기반으로 API 호출 가능 여부를 결정한다.

 




<그림. Apitoken을 이용한 API 호출 인증>


클레임 기반의 토큰의 경우에는 이러한 작업이 없이 그냥 API 게이트 웨이에서 apitoken을 까보고, 그 안에 있는 내용을 가지고 API 호출 가능 여부를 결정한다.


이렇게 api token으로 인증을 하는 방법이 일반적인 방법이지만, 서버대 서버간의 통신은 내부 서버의 경우 별도의 인증 없이 API 를 제공하는 경우도 있고, 외부 서버와의 통신은 특정 ip 주소와 통신을 허용 하거나 높은 보안을 요구하는 경우 양방향 SSL등의 인증 방식을 사용함으로써 apitoken없이도 API 호출을 인증하는 방법도 있다..

이렇게 각각의 클라이언트나 서비스 별로 제공되는 엔드포인트에 대해서 API 인증 방식이 다르기 때문에, API 게이트웨이에서는 각 엔드 포인트 별로 다양한 형태의 인증 방식을 제공해야 한다. API 게이트를 이용하여 다양한 엔드포인트를 통해 서비스를 제공하는 방법은 뒤에서 다시 설명하도록 한다.


엔드포인트별 API 요청 인가


인증(Authentication)과 인가(Authorization)은 다른 의미를 갖는데, API를 호출 하는 것이 Terry가 맞다는 것을  확인 해주는 것을 인증이라고 한다면, 이 Terry가 이 API를 호출할 수 있는 권한이 있는 것을 확인해주는 것이 인가(Authorization)이다. 쉽게 생각하면, 일반 사용자용 API와 관리자용 API를 생각하면 이해가 쉽다.


이렇게 권한을 제어하는 방식은 여러가지가 있는데, 각 개별 권한을 토큰에 부여 하는 방식과 역할(ROLE) 기반으로  권한을 부여하는 방식이 대표적이다.


개별 권한을 토큰에 부여 하는 방식은 다양한 권한 정책을 세밀하게 관리할 수 있다는 장점을 가지고 있다.

 


<그림. 토큰에 역할을 부여하는 방식>


토큰에 제한적으로 권한을 부여할 수 있다는 장점을 가지고 있는데, 페이스북이 이런 형태의 권한 통제 모델을 사용한다. 

https://developers.facebook.com/docs/facebook-login/permissions/v2.2?locale=ko_KR

에 보면 api 토큰에 연동할 수 있는 권한 리스트들이 있는데, 페이스북의 써드파티 애플리케이션을 보면, 페이스북의 API의 권한을 일부 요청 하는 형태로 토큰에 권한을 연결한다.


그렇지만,이 방식의 경우에는 권한의 종류가 많을 경우, 관리가 어려워 지고 복잡해지기 때문에, 일반적으로 역할(ROLE)기반으로 권한을 관리 하는 방식을 많이 사용한다.


직접 권한을 토큰에 연결하는 것이 아니라, 역할이라는 개념을 두고, 역할별로 권한을 연결한 다음에, 이 역할을 토큰에 부여하는 개념이다 쉽게 이야기 하면, 관리자용 기능과 일반 사용자용 기능을 분리한 다음에, 관리자나 일반 사용자와 같은 역할(ROLE)을 토큰에 부여하는 방식이다. 이를 RBAC (Role Based Access Control)이라고 한다.


이 RBAC 기반으로 하면, 통제 해야 하는 권한의 숫자가 줄어들기 때문에, 다음과 같이 엔드포인트를 나눠서 권한 접근 제어가 가능하다. (예를 들어 총 권한이 100개가 있다고 했을때, 이를 관리자용 기능과 일반 사용자용 기능으로 나누어 버리면, 관리해야 하는 두개의 권한 집합을 나뉘어 진다.) 


이런 경우 관리자용 API 엔드포인트(/service/admin), 일반 사용자용 API 엔드포인트(/service/users) 두 개로 나눈 다음에, apitoken에 권한을 admin,user 두가지 종류로 정의한 후에, /service/admin 엔드포인트에서는 api token이 admin 권한이 있을 경우에만, 호출을 허용하도록 하면 된다. 


 

<그림. 역할(ROLE)별로 엔드포인트를 나눠서 권한 인가를 하는 구조>

API 라우팅


API 게이트웨이에서 다음으로 유용한 기능중의 하나가 API 호출을 라우팅 하는 기능이다. 같은 API라도 사용하는 서비스나 클라이언트에 따라서 다른 엔드포인트를 이용해서 서비스를 제공하거나, 데이타 센터가 여러개일때, 데이타 센터간의 라우팅등을 지원하는 기능이다. 주요 기능들을 보면 다음과 같다.


백엔드 API 서버로의 로드 밸런싱


가장 기본적인 기능으로는 로드밸런서 기능이다. API 게이트 웨이 뒷단에 다수의 API 서버가 있다고 할때, 여러개의 API 서버로 부하를 분산하는 기능이 필요하다.

 


<그림. API 게이트 웨이를 통한 API 서버로의 로드 밸런싱>


단순하게 Round Robin 방식으로 부하를 분산하는 기능뿐만 아니라, 각 서버 하드웨어에 따라 부하를 가중치를 줘서 분산하는 기능등을 고려해볼 수 있겠고, 무엇보다 중요한 기능은 API 서버가 장애가 났을때 이를 감지해서 로드 밸런싱 리스트에서 빼고, 복구 되었을때 다시 로드 밸런싱 기능에 넣는 기능들이 필요하다.


단순하게, HA Proxy와 같은 L4의 기능처럼, 뒷단의 서버가 살아 있으면 부하를 보내고 죽었으면 부하를 안보내는 기능에서 부터, 고급 기능으로는 API 서버가 Hang up (멈춤)에 걸렸을 때 이를 인지해서 부하를 안보내는 기능등을 고려해볼 수 있다. 이러한 고급 기능은 API 서버의 애플리케이션 상태를 인지해야 하기 때문에 단순히 IP 포트가 살아 있음을 가지고 판단 하는 것이 아니라 쓰레드 수, 응답 시간등으로  서버의 장애 상태를 판단해야 한다.  


서비스 및 클라이언트 별 엔드포인트 제공


또 다른 유용한 기능중의 하나는, 같은 API를 여러개의 엔드포인트를 통해서 서비스를 제공할 수있다는 점인데, 하나의 시스템이 다양한 서비스나, 다양한 클라이언트등으로 서비스를 제공할때, 각각 다른 서비스 별 또는 클라이언트 별로 다른 엔드포인트를 제공할 수 있다.

예를 들어서 IOT 플랫폼 서비스가 있다고 하자. 이 플랫폼은 REST API를 제공하는데, 이를 통해서 센서로 부터 데이타를 수집해서 분석하는 시스템이라고 가정하자.

이 시스템은 선박용 서비스, 비행기용 서비스, 차량용 서비스를 지원한다고 가정하자.

각 서비스별로 API의 특성이나 노출되는 API가 다소 다를 수 있는데, 각 서비스 별로

  • 선박용 /ships/
  • 비행기용 /airplanes/
  • 차량용 /cars/

라는 식으로 각각의 다른 엔드 포인트를 제공할 수 있다.

그리고, 이 서비스에서는 센서로 부터 데이타를 수집하는 시나리오와, 관리자가 웹을 통해서 시스템을 관리하기 위한 API가 있다고 가정하면, 앞의 API는 다음과 같이 클라이언트의 종류에 따라서 분리 될 수 있다.


  • 선박 센서용 /ships/sensors/, 선박 관리자 웹 /ships/admin
  • 비행기 센서용 /airplanes/sensors/, 비행기 관리자용 /airplanes/admin
  • 차량 센서용 /cars/sensors, 차량 관리자용 /cars/admin

그리고 각각의 엔드포인트 별로 노출(expose)하는 API를 다르게 할 수 있다.

 


< 그림. API를 엔드포인트 별로 다르게 노출>


API 게이트 웨이는 API 서버가 공통적인 API를 가지더라도, 각 서비스나 클라이언트 타입에 따라서 각각 다른 API 를 선별적으로 서비스 할 수 있도록 해준다.


※ 실제로 멀티 서비스를 제공하는 플랫폼형태의 경우에는 이 기능이 매우 유용하다.특히 같은 API라도 클라이언트의 종류에 따라서 인증 방식이 다를 수 있고 보안 메커니즘이 다를 수 있다.


메세지 또는 헤더기반 라우팅


라우팅에서 유용한 기능중의 하나는 메세지 내용을 기반으로 하는 라우팅이다. 예를 들어 그림과같이 HTTP 헤더에 country code가 있을 경우, country code에 따라서 유럽에 있는 API를 호출하거나 또는 미국에 있는 API 서버를 호출할 수 있도록 Routing을 할 수 있다.

 


<그림. 메세지 기반의 글로벌 라우팅 예시>


특히 글로벌 단위로 배포되는 시스템인 경우 각 데이타 센터간에 메세지를 라우팅 시키는데 유용하게 사용할 수 있다. 위의 예에서 처럼, 특정 데이타 센터로 조건에 따라 라우팅을 할 수 도 있고, 또는 중앙 집중형 시스템의 경우, 각 지역에 API 게이트 웨이를 두고, 클라이언트는 가까운 API  게이트 웨이를 호출하지만, 중앙 데이타 센터에만 있는 API 서버의 경우 중앙 데이타 센터로 호출을 라우팅 할 수 있다.


데이타 복제가 필요할 경우, 미국에 있는 API 게이트웨이로 호출하면 API 게이트 웨이가 미국 API서버와, 유럽 API 서버를 동시에 호출해서, 업데이트성 트렌젝션을 모든 데이타 센터에 복제함으로써 API를 통한 데이타 복제가 가능해진다.

라우팅에 있어서 고려해야할 사항은 먼저 메세지에 대한 라우팅인데, REST API를 기준으로 설명하면, REST API는 HTTP URL,HTTP Header,HTTP Body 3가지로 구분이 된다.


메세지를 기반으로 라우팅을 하기 위해서는 API 게이트 웨이가 이 메세지를 파싱해야 한다.

예를 들어 country_code가 HTTP Body에 JSON으로 다음과 같이 들어가 있다고 가정하자


{

“country_code”:”US”

  :

}


이 경우 이 API 호출에 대해서 라우팅 정보를 추출하기 위해서 매번 HTTP Body에 있는 JSON을 API 게이트웨이가 파싱해서 열어봐야 한다. 이는 빠르게 메세지가 통과해야 하는 API 게이트웨이의 역할에 많은 부담을 준다. 만약에 이러한 라우팅 정보를 HTTP Header로 옮긴다면, HTTP Body는 파싱하지 않고, Header만 파싱한후, Body 정보는 라우팅되는 서버로 그냥 포워딩만 해도 된다.


그래서 메세지 기반의 라우팅을 사용할 때는 이러한 파싱에 대한 오버헤드를 잘 고려하고, 가능하면, HTTP URL이나 HTTP Header에 라우팅 필드를 넣는 것이 좋다. 


부득이하게, HTTP Body에 있는 내용으로 라우팅을 해야 하는 경우에는 호출 빈도가 적은 API인 경우 API 게이트웨이에서 담당하고, 다른 경우에는 별도의 게이트웨이 인스턴스(프로세스)로 분리를 하거나 뒷단의 API서버가 라우팅을 하도록 하는 것도 하나의 방안이 된다.


공통 로직 처리


API 게이트웨이는 특성상 모든 API 서버 앞쪽에 위치 하기 때문에, 모든 API 호출이 이 API 게이트를 거쳐간다. 그렇기 때문에, 모든 API 가 공통적으로 처리해야 하는 공통 기능이 필요할 경우 이러한 공통 기능을 API 게이트웨이로 옮기게 되면 별도로 API 서버에서 이러한 기능을 개발할 필요 없이 비지니스 로직 자체 구현에만 집중할 수 있게 된다.

아래 그림은 각 API 서버에서 인증과, 로깅에 관련된 로직을 API 게이트웨이로 이전한 구조이다.

API 로깅이나 인증은 전체 시스템에 대해 공통된 기능으로, 공통 계층에서 처리하게 되면 개발 중복을 줄일 수 있는 장점뿐만 아니라, 표준 준수가 더 쉽다는 장점을 가지고 있다. 

 


<그림 API 게이트웨이를 이용하여 공통 로직을 API 서버에서 API 게이트웨이로 이전한 구조>


메디에이션 기능 (Mediation)


메디에이션이란, 한글로 “중재”또는 “조정” 이라는 의미를 갖는데, API서버에서 제공되는 API가 클라이언트가 원하는 API 형태와 다를때, API 게이트웨이가 이를 변경해주는 기능을 이야기 한다. 구체적인 기능을 보자


메세지 포맷 변환 (Message format transformation)


메세지 포맷을 변환하는 기능이란, JSON으로 된 요청(Request) 메세지가 들어왔을때, 이를 API 서버로 보낼때 변환 해서 보내거나, 또는 API 서버에서 생성된 응답을 클라이언트에 리턴할때 변경해서 보내는 기능을 의미한다.


예를 들어보자, 아래와 같이 terry의 연봉(salary) 정보를 구하는 API가 필요하다고 하자. 그런데, 시스템에는 연봉 정보만 주는 API는 없고, 전체 사용자 정보를 리턴하는 API만 있는 상황이다.


이런 경우, API 게이트 웨이를 통해서 /users/salary라는 새로운 API를 제공하고, 이를 기존에 전체 사용자 정보를 주는 /users/details라는 API로 라우팅 한다. /users/details에서 사용자 정보를 뽑았을때, 클라이언트에게 응답을 줄때는 API 게이트웨이에서 아래 그림과 같이 name과 salary 정보만 뽑아서 리턴하도록 한다.

 


<그림. 메세지 포맷 변환의 예시>


일단 간단한 기능으로 구현이 가능하기 때문에 서술은 해놨지만, 그다지 권장하고 싶지 않은 기능이다. 메세지 포맷이 변환이 된다면, 차라리 필요한 포맷에 맞는 API를 따로 뽑아 내는 것이 났지 않나 싶다.


프로토콜 변환 


다양한 서비스나 클라이언트를 지원하게 되면, 클라이언트나 서비스별로 다른 통신 프로토콜을 사용해야 하는 경우가 있다. 웹에서는 JSON기반의 REST가 많이 사용되지만, 배나 비행기에 사용되는 센서들의 경우에는 REST도 무겁기 때문에 바이너리 기반의 경량 프토토콜을 사용하거나, 또는 예전 엔터프라이즈 시스템의 경우 XML 기반의 웹서비스를 이용할 수 도 있다.


이렇게 다양한 타입의 프로토콜을 지원하기 위해서, 각 서비스들이 새롭게 구현을 하는 것이 아니라 API 게이트웨이 계층에서 프로토콜 변환을 통하여, 같은 API를 다른 프로토콜로 서비스 할 수 있도록 할 수 있다.

 


<그림. API 게이트 웨이를 통한 프로토콜 변환>


실제로 유용한 기능인데, 내부 API는 REST가 아니라 페이스북 Thrift나 구글의 Protocol Buffer로 구현을 하고, 외부에 제공하는 API는 API 게이트 웨이단에서 REST 로 변경해서 서비스 하는 구조를 이용하면, 내부 API 성능을 올리고, 외부로는 REST API로 서비스 함으로써 범용성을 확보할 수 있다. (실제 사례가 있었다.)


또한 근래에 M2M이나 IOT (Internet of things)와 같은 개념이 활성화 되면서, HTTP REST 뿐 아니라 기존의 센서에서 통신에 사용되는 다양한 프로토콜을 지원하여 백엔드 API 서버의 프로토콜로 맞춰줘야 하는 필요가 점점 증대되고 있다.


메세지 호출 패턴 변환 (Message Exchange Pattern : MEP)


메세지 호출 패턴, 보통 MEP(Message Exchange Pattern)라고 하는데, 동기,비동기 호출과 같은 API를 호출하는 메세지 패턴을 정의한다.

API 게이트웨이의 좋은 기능중의 하나가 이 MEP를 변경할 수 있다는 건데, 쉽게는 Async API호출을 Sync 호출로 바꿔 준다거나, 하나의 API 호출을 여러 데이타 센터로 복제 해준다거나 하는 형태의 메세징 패턴을 변화 시킬 수 있다.

 


<그림. 비동기 호출을 API게이트웨이를 통해서, 동기 호출로 변경한 구조>


위의 그림의 예제는 로그를 수집하는 시스템에 대한 구조이다.뒷단의 로그저장 API 서버가 대용량 트래픽에 대한 대응 능력이 없을때, API 게이트 웨이에서 큐를 이용해서 API 요청을 받고 (1), 바로 클라이언트에 ACK를 준후에, 메세지큐 연동을 이용하여 메세지를 저장한후, 로그 저장 API 서버의 성능에 맞게 흘려주는 방식이다. 클라이언트 입장에서는 동기 호출이지만 실제 메세지 흐름은 큐를 이용한 비동기 구조로 변경되었다.


어그레게이션 (aggregation)


SOA에서는 Orchestration(오케스트레이션)이라고 불렀는데, 여러개의 API를 묶어서 하나의 API로 만드는 작업을 이야기 한다. 예를 들어서, 계좌 이체를 한다고 했을때,


A은행에서 잔액 확인

A은행에서 인출

B은행으로 입금


하는 3개의 API 호출을 하나의 API 인 POST transfer(인출계좌,입급계좌,금액)으로 구현한다고 하자.이를 API 게이트웨이에서 구현 하면 다음과 같은 형태로 구현할 수 있다.

 


<그림. API 게이트 웨이를 이용한 API Aggregation>


대부분의 API 게이트 웨이 제품들은 이러한 aggregation을 할 수 있는 일종의 워크플로우 엔진과 유사한 기능들을 가지고 있다.


 


<그림. Apigee 제품의 워크플로우 저작도구 화면>


이러한 aggregation 기능이 언뜻 보면 좋아보이지만, 하나의 플로우에서, 여러 API를 호출해야 하고, 비지니스 로직을 수행하면서 실제로 API 메세지 BODY까지 파싱해야 하기 때문에, API 게이트 웨이 입장에서는 부하가 매우 크다. 


MSA 의 전신인 SOA에서 API 게이트웨이와 유사한 역할을 했던 ESB역시 이러한 aggregation (ESB에서는 보통 오케스트레이셔이라고 함)을 남발해서, ESB의 성능이 떨어져서 시스템 개발이 실패하는 아키텍쳐를 많이 봤다.

그래서 본인의 경우에는 이러한 무거운 aggregation 로직은 별도의 Mediator API 서버라는 계층을 만들어서, API 게이트웨이 밖에서 따로 하는 방법을 권장한다.


아래 그림과 같이 여러 API를 조합하는 목적의 API 서버를 별도로 둬서, 이러한 기능을 API 게이트웨이에서 제거한다.

 


<그림. API aggregation을 API 게이트웨이에서 Mediation API 서버로 분리한 구조>


aggregation 로직을 API 게이트웨이 안에 넣으면 확실하게  게이트웨이가 받는 부하량은 올라간다. 설치형 API 게이트웨이의 경우, 이는 추가적인 하드웨어 박스를 더 구매하고, 상용 API 게이트웨이의 경우 라이센스를 더 구매해야 한다는 것을 의미하기 때문에, Mediation API 서버 계층을 사용하는 것을 권장한다.


클라우드형 API 게이트웨이의 경우, 호출 수로 과금을 하기 때문에 aggregation 로직을 API 게이트웨이에 넣는 방안을 고려해볼 수 있으나, aggregation 로직이 게이트웨이 안에 있으면 디버깅이나 테스팅이 쉽지 않기 때문에, 이를 적절히 고민한 후 판단해서 aggregation 로직의 위치를 결정해야 한다.


로깅 및 미터링


API 게이트웨이의 비기능적인 요건으로 중요한 기능이 로깅과 미터링이다. 


API 호출 로깅


앞서 공통 로직 처리 부분에서도 언급하였지만, API 호출시 API 게이트웨이는 공통적으로 호출되는 부분인 만큼 모든 로그를 중간에서 수집하기가 가장좋다.


근래의 애플리케이션 아키텍쳐가 클라이언트와 서버간의 통신이 모두 API를 기반하는 형태로 변경이되어감에 따라 API 호출 패턴을 분석하면 사용자의 사용 패턴을 분석해낼 수 있기 때문에, 빅데이타 영역과 연계하여 API 호출 로그는 아주 중요한 자산으로 다루어지고 있다.


또한 API 호출 로그는 차후 문제가 발생하였을때, 문제를 추적하기 위한 중요한 자료로 사용된다. (Audit: ‘감사’의 목적) 그래서, API 로그 수집은 단순 분석 목적뿐 아니라, 향후 감사 목적용으로도 저장되어야 한다.


근래에 출시되고 서비스되는 클라우드형 API 게이트웨이의 경우에는 특히나 이 API에 대한 로그 분석 기능을 강화해서 출시되고 있다.

 


<그림. Apigee.com의 API 모니터링>


API 미터링 & 차징 (Metering & Charing)


API 미터링과 차징은 유료 API 서비스를 위한 기능으로,  미터링은 과금을 위한 API 호출 횟수,클라이언트 IP, API 종류,IN/OUT 용량등을 측정 기록하는 서비스이고,

차징은 미터링이 된 자료를 기반으로 하여, API 서비스 사용 금액을 금액 정책에 따라서 계산 해내는 서비스이다. 

대부분의 SNS 오픈 API 서비스는 무료인 경우가 많지만, 구글 API 의 경우에도, 특정 호출 횟수(/일)을 넘어가면 과금등을 하도록 되어 있다.


QoS 조정 (Quality of service)


마지막으로 QoS 조정 기능이란, API 서비스를 클라이언트 대상에 따라서 서비스 레벨을 조정하는 기능이다.

유료 서비스가 있는  API 서비스라고 가정할때, 무료 사용자의 경우 1일 1000건으로 호출횟수를 제한 한다거나, 전송 용량이나, 네트워크 대역폭을 유료/무료 사용자에 따라 다르게 적용하는 것과 같은 기능을 QoS 기능이라고 한다.

유료 서비스인 경우만 아니라, 플랫폼 차원에서 다양한 클라이언트나 다양한 서비스로 API 를 제공하는 경우, 각 클라이언트나 서비스에 따라서 이 QoS를 조정하는 기능은 유용하게 사용될 수 있다. 특정 서비스나 클라이언트가 폭주하여 API를 과도하게 사용하여 다른 서비스들이 API를 사용할 수 없게 한다던가 그런 문제를 미연에 예방할 수 있다.


결론


지금까지 간단하게나마 API 게이트웨이의 대략적인 기능에 대해서 알아보았다. 다음에는 API 게이트웨이 기반 아키텍쳐를 확장하는 방법과 API 게이트웨이의 안티패턴과 설계 방법론 등에 대해서 소개하도록 한다.


참고

API 플랫폼의 이해 http://bcho.tistory.com/808

대용량 분산 시스템을 위한 마이크로서비스 아키텍쳐 http://bcho.tistory.com/948




저작자 표시 비영리
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

대충보는 Storm #5-Apache Storm 병렬 분산 처리 이해하기

 조대협 (http://bcho.tistory.com)

 

Storm에 있는 Spout Bolt들은 여러개의 머신에서 어떻게 나눠서 처리될까? Storm 클러스터는 여러대의 분산된 서버에서 운용되기 때문에, 당연히 Spout Bolt도 나눠서 처리된다 그렇다면 이런 Storm의 병렬 처리 구조는 어떻게 되는 것일까?

이 글에서는 Spout Bolt를 병렬로 처리하는 Storm의 구조에 대해서 알아보도록 한다.

Storm의 병렬 처리를 이해하기 위한 개념

Storm의 병렬 처리를 이해하기 위해서는 몇가지 개념을 정리해야 한다. Node,Worker,Exectutor,Task 이 네 가지 개념을 이해해야 한다.


Node

Node는 물리적인 서버이다. Nimbus Supervisor 프로세스가 기동되는 물리적인 서버이다.

Nimbus는 전체 노드에 하나의 프로세스만 기동하며, Supervisor는 일반적으로 하나의 노드에 하나만 기동한다. 여러대를 기동시킬 수 도 있지만, Supervisor의 역할 자체가 해당 노드를 관리하는 역할이기 때문에 하나의 노드에 여러개의 Supervisor를 기동할 필요는 없다.


Worker

Worker Supervisor가 기동되어 있는 노드에서 기동되는 자바 프로세스로 실제로 Spout Bolt를 실행하는 역할을 한다.


Executor

Executor Worker내에서 수행되는 하나의 자바 쓰레드를 지칭한다.


Task

Task Bolt Spout의 객체를 지칭한다. Task Executor (쓰레드)에 의해서 수행된다.

이 개념을 다시 정리해보면 다음과 같은 그림이 된다.



<그림. Node,Worker,Executor,Task 의 개념>

각 슬레이브 노드에는 Supervisor 프로세스가 하나씩 떠있고, conf/storm.yaml에 정의된 설정에 따라서 worker 프로세스를 띄운다.supervisor.slots.ports에 각 Worker가 사용할 TCP 포트를 정해주면 된다. 아래는 5개의 Worker 프로세스를 사용하도록 한 설정이다.



<그림. Storm 설정에서 Supervisor 5개 띄우도록한 설정>

 

그리고 난후에, Topology를 생성할때, Topology에 상세 Worker,Executor,Task의 수를 정의한다. 앞에서 예제로 사용했던 HelloTopology 클래스 코드를 다시 살펴보자. 아래 코드는 Worker,Executor,Task등을 설정한 예이다.

package com.terry.storm.hellostorm;

 

import backtype.storm.Config;

import backtype.storm.StormSubmitter;

import backtype.storm.generated.AlreadyAliveException;

import backtype.storm.generated.InvalidTopologyException;

import backtype.storm.topology.TopologyBuilder;

 

public class HelloTopology {

        public static void main(String args[]){

               TopologyBuilder builder = new TopologyBuilder();

               builder.setSpout("HelloSpout", new HelloSpout(),2);

               builder.setBolt("HelloBolt", new HelloBolt(),2)

                       .setNumTasks(4)

                       .shuffleGrouping("HelloSpout");

              

              

               Config conf = new Config();

               conf.setNumWorkers(5);

               // Submit topology to cluster

               try{

                       StormSubmitter.submitTopology(args[0], conf, builder.createTopology());

               }catch(AlreadyAliveException ae){

                       System.out.println(ae);

               }catch(InvalidTopologyException ie){

                       System.out.println(ie);

               }

              

        }

 

}

<코드. Worker,Executor,Task 수를 설정한 HelloTopology 예제>

     Topology가 사용할 Worker 프로세스의 수 설정
Config
에서 setNumWorkers(5)를 이용해서 이 토폴로지에서 사용한 Worker 프로세스 수를 5개로 지정했다.

     Spout Executor(쓰레드 수) 설정
다음으로 setSpout에서 3번째 인자로 “2”라는 숫자를 넘겼는데, setSpout에 마지막 인자는 Executor의 수이다. 이를 Parallelism 힌트라고 하는데, Spout 컴포넌트가 수행될 쓰레드의 수이다. 여기서는 Spout Task (객체의 수)를 정의하지 않았는데, 정의하지 않은 경우 디폴트로 Executor의 수와 같이 설정된다.

     Bolt Executor(쓰레드 수)Task(객체)수 설정
Bolt
도 마찬가지로 setBolt 3번째 마지막 인자가 Parallelism 힌트인데, 역시 2개로 지정하였다. 여기서는 Task수를 별도로 지정하였는데, setTaskNum(4)을 이용해서 지정한다. 이렇게 설정하면 HelloBolt 객체는 총 4개가 생기고 2개의 Thread에서 번갈아 가면서 실행하게 된다.

자아 그러면 실제로 설정하는데로 동작하는 지 몇가지 확인을 해보자. 자바의 jps 명령을 이용하면 현재 동작중인 자바 프로세스 수를 볼 수 있다.



<그림 Worker 프로세스 수의 확인>

위의 테스트는 하나의 환경에서 nimbus,zookeeper,supervisor,worker를 모두 띄워놓은 형태인데,worker가 설정대로 5개의 프로세스가 떠있고, nimbus,supervisor가 떠 있는 것이 확인되고, QuorumPeerMainzookeeper 프로세스이다.

실제로 Executor가 지정한데로 Thread가 뜨는지 확인을 해보자. 여러개의 Worker 프로세스에 나눠서 뜨면 모니터링하기가 복잡하니 편의상 conf.setNumer(1)로 해서, 하나의 Worker 프로세스에서 모든 Executor가 뜨도록 Topology를 변경한후, Worker 프로세스의 쓰레드를 모니터링 하니 다음과 같은 결과를 얻었다.

코드상에서 HelloSpout에 대한 Parallelism 힌트를 2로 설정하고, HelloBolt에 대한 Parallelism 힌트도 2로 설정하였다.



<그림. Worker 프로세스의 쓰레드 덤프>

실제로 Worker 프로세스내의 쓰레드를 보면 HelloSpout용 쓰레드가 2, HelloBolt용 쓰레드가 2개가 기동됨을 확인할 수 있다.


리밸런싱

Storm 운영중에 노드를 추가 삭제 하거나 또는 성능 튜닝을 위해서 운영중인 환경에 Worker, Executor의 수를 재 조정이 가능하다. 이를 rebalance라고 하는데, 다음과 같은 명령어를 이용해서 가능하다.

% bin/storm rebalance [TopologyName] -n [NumberOfWorkers] -e [Spout]=[NumberOfExecutos] -e [Bolt1]=[NumberOfExecutos] [Bolt2]=[NumberOfExecutos]

미들웨어 엔지니어로써 본 Storm 튜닝

본인의 경우 경력이 톰캣이나 오라클社의 웹로직에 대해 장애진단과 성능 튜닝을 한 경력을 가지고 있어서 JVM이나 미들웨어 튜닝에 많은 관심을 가지고 있는데, 이 미들웨어 튜닝이라는 것이 대부분 JVM과 쓰레드 수등의 튜닝에 맞춰 있다보니, Storm의 병렬성 부분을 공부하다 보니, Executor Worker,Task의 수에 따라서 성능이 많이 차이가 나겠다는 생각이 든다.

특히나 하나의 토폴리지만 기동하는 것이 아니라, 여러개의 토폴로지를 하나의 클러스터에서 구동 할 경우 더 많은 변수가 작용할 수 있는데, 쓰레드란 것의 특성이 동시에 하나의 코어를 차지하고 돌기 때문에, 쓰레드수가 많다고 시스템의 성능이 좋아지지 않으며 반대로 적으면 성능을 극대화할 수 없기 때문에, 이 쓰레드의 수와 이 쓰레드에서 돌아가는 객체(Task)의 수에 따라서 성능 차이가 많이 날것으로 생각된다. 아마도 주요 튜닝 포인트가 되지 않을까 싶은데, 예전에는 보통 JVM당 적정 쓰레드 수는 50~100개 정도로 책정했는데 (톰캣과 같은 WAS 미들웨어 기준). 요즘은 코어수도 많아져서 조금 더 많은 쓰레드를 책정해도 되지 않을까 싶다. 쓰레드 수 뿐 아니라, 프로세스수도 영향을 미치는데, JVM 프로세스의 컨텐스트 스위칭은 쓰레드의 컨텐스트 스위칭보다 길기 때문에, 프로세스를 적게 띄우는 것이 좋을것으로 예상 되지만, JVM 프로세스는 메모리 GC에 의한 pausing 시간이 발생하기 때문에 이 GC 시간을 적절하게 나눠주기 위해서 적절 수 의 프로세스를 찾는 것도 숙제가 아닐까 싶다. 디폴트 worker의 옵션을 보니 768M의 힙 메모리를 가지고 기동하게 되어 있는데, 메모리를 많이 사용하는 연산는 다소 부족하지 않을까 하는 느낌이 든다.

Bolt가 데이타 베이스, 파일 또는 네트워크를 통해서 데이타를 주고 받는 연산을 얼마나 하느냐에 따라서도 CPU 사용률이 차이가 날것이기 때문에 (IO작업중에는 쓰레드가 idle 상태로 빠지고 CPU가 노는 상태가 되기 때문에) IO 작업이 많은 경우에는 쓰레드의 수를 늘리는 것이 어떨까 한다.

Bolt Spout와 같은 통신은 내부적으로 ZeroMQ를 사용하는 것으로 알고 있는데, 아직 내부 구조는 제대로 살펴보지는 않았지만, 같은 프로세스내에서는 네트워크 호출 없이 call-by-reference를 이용해서 통신 효율을 높이고, 통신이 잦은 컴포넌트는 같은 프로세스에 배치 하는 affinity와 같은 속성(?)이 있지 않을까 예측을 해본다.

결과적으로 튜닝 포인트는, Worker,Executor,Task 수의 적절한 산정과, 만약에 옵션이 있다면 리모트 호출을 줄이기 위한 Bolt Spout 컴포넌트의 배치 전략에 있지 않을까 한다.


다음 글에서는 이런 병렬 처리를 기반으로 각 컴포넌트간에 메세지를 보낼때, 여러 Task간에 어떻게 메세지를 라우팅을 하는지에 대한 정리한 그룹핑(Grouping)에 대한 개념에 대해서 알아보도록한다.


저작자 표시 비영리
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

람다 아키텍쳐의 소개와 해석

조대협 (http://bcho.tistory.com)


람다 아키텍쳐란

람다 아키텍쳐는 트위터에서 스트리밍 컴퓨팅에 있었던Nathan Marz에 의해서 소개된 아키텍쳐로, 실시간 분석을 지원하는 빅데이타 아키텍쳐이다.

아키텍쳐에 대한 자세한 내용은 http://lambda-architecture.net/ 에 소개되어 있다.


문제의 정의

아키텍쳐에 대한 이해를 돕기 위해서 예를 들어 설명해보자.

 페이스북과 SNS 애플리케이션 SNS가 있다고 가정하자. 이 애플리케이션은 모바일 애플리케이션이며, 글쓰기, 읽기, 댓글 달기, 스크롤 하기, 페이지 넘기기등 약 1000여개의 사용자 이벤트가 있다고 가정하자.

 사용자 수는 대략 1억명이며, 매일 이 각 사용자의 행동 패턴을 서버에 저장하여, 일별로, 사용자 이벤트의 개수를 통계로 추출한다고 하자.

클라이언트 디바이스로 부터 올라오는 데이타는 다음과 같다

  • 사용자 : 조대협

  • 날짜 : 2015년 1월 5일



<그림 1. 클라이언트에서 올라오는 데이타 포맷>

이런 환경에서, 기간별 특정 이벤트 추이, 가장 많이 활용되는 이벤트 TOP5 등의 통계 정보를 실시간으로 보고 싶다고 가정하자

가장 단순한 접근은 RDBMS에 저장하고 쿼리를 수행하는 방법이다.


<그림 2. 로그 데이타를 RDBMS에 저장한 포맷>

RDBM에 저장하고 SQL 쿼리문을 돌리면 되겠지만, 문제는 간단하지 않다. 1000개의 컬럼에, 1억명이 사용하는 시스템이다. 즉. 하루에 최대 1000개의 컬럼 짜리, 1억개의 레코드가 생성이 된다것이다.한달이면 30억개의 레코드이다.

이런 많은 데이타를 동적 SQL로 실행하였을때 그 수행시간이 많이 걸린다.


배치를 활용

그러면 이런 시간이 많이 걸리는 문제를 어떻게 해결하면 좋을까? 이를 위한 전통적인 접근 방식은 배치(BATCH)를 활용하는 것이다. 배치는, 어떤 특정 정해진 시간에, 계산을 미리 해놓는 것이다.

즉 데이타를 모아 놓았다가.밤마다.그날짜의 사용자들의 이벤트들의 합을 매일 계산해놓은 테이블을 만들어 놓으면 된다.



<그림 3. 일별 배치로 생성된 이벤트 데이타 테이블>

자아, 이렇게 배치로 테이블을 만들어 놓으면, 특정 기간에 각 이벤트별 통계를 내기가 쉬워 진다. 1년분의 데이타라하더라도 365 행 밖에 되지 않기 때문에, 속도 문제가 해결이 된다.

실시간 데이타의 반영

테이블 조인

이렇게 배치 테이블을 생성하면, 성능에 대한 문제는 해결이 되지만, 데이타가 배치 주기에 따라 최대 1일의 편차를 두게 된다. 즉 실시간 반영에 대한 문제가 발생한다.

그렇다면 어떻게 해결을 해야 할까? 해결은 배치 테이블과 그날의 데이타 테이블을 두개를 같이 사용하면 된다.

즉 어제까지의 데이타는 일별 배치로 생성된 테이블을 사용하고, 오늘 데이타 부분은 사용자별로 기록된 로그 테이블을 사용하여 두 테이블을 조인 하면, 오늘의 지금 순간의 통계값까지 볼 수 있다.

 


<그림 4. 테이블 조인을 이용한 실시간 데이타 통계 추출 >


실시간 집계 테이블의 활용

하루에 쌓이는 데이타량이 얼마 되지 않는다면 문제가 되지 않겠지만, 이 시나리오에서 하루에 쌓이는 데이타는 일 최대 1억건이 된다. 즉, 오늘 쌓이는 데이타 테이블을 조인 하면 1억개의 행에 대한 연산이 발생하여 적절한 성능을 기대하기 어렵다. 

그렇다면, 배치는 매일 돌리되, 오늘 데이타에 대한 통계 값을 실시간으로 업데이트 하는 방법을 생각해볼 수 있다. 

아래 그림과 같이 로그서버에서 클라이언트에서 받은 로그를 원본 데이타 테이블에 계속 저장을 하고, 오늘 통계에 대한 실시간 집계 테이블에, 글쓰기, 글 읽기 등 개별 이벤트의 값을 계산해서 더해 주면 된다.

 


<그림 5. 실시간 집계 테이블>

이렇게 하면, 실시간 집계 테이블과, 배치 테이블을 조인하여 빠르게 실시간 통계를 볼 수 있다.

즉 일별 실시간 통계는 다음 그림과 같이 당일전의 배치뷰와 당일의 실시간뷰를 합쳐서 통계를 낸 형태가 된다.

 


<그림 6. 실시간 통계를 뽑기 위한 테이블들의 관계>


람다 아키텍쳐를 활용

이 개념을 람다 아키텍쳐로 해석해보자. 데이타 흐름을 도식화 해보면 다음과 같다.

 


<그림 7. 람다 아키텍쳐의 개념>


먼저 배치 처리를 위해서, 로그 서버는 모든 로그 데이타를 저장소에 저장하고, 배치 처리 계층에서 일일 또는 일정한 시간을 주기로 배치 처리로 계산을 해서 배치 뷰(배치 테이블)을 만든다.

그리고 다른 흐름으로 실시간 처리쪽에 데이타를 전송해서 실시간 집계를 해서 실시간 집계 테이블을 만든다.

마지막으로, 이 두개의 뷰를 합쳐서 통계를 만든다.

배치뷰는 배치로 돌때만 쓰기가 가능하고 평상시에는 데이타를 읽기만 가능하게 한다. 이를 통해서 데이타가 변경되거나 오염(Corrupt)되는 것을 막을 수 있다.

실시간 뷰는 실시간으로 데이타를 쓰고, 읽을 수 있는 시스템을 사용한다.

위의 문제 정의 예제에서는 컬럼의 개수를 카운트 정도하는 간단한 예를 들었지만, 실제 빅데이타 분석에서는 단순 통계뿐 아니라 복잡한 수식이나 다단계를 거쳐야 하는 데이타 파일의 가공이 필요하기 때문에 복잡한 프로그래밍이 가능한 처리(배치/실시간)이 필요한데, 이 처리 계층에는 프로그램을 이용하려 알고리즘을 삽입할 수 있어야 한다.

이러한 특성에 맞춰서 각 데이타 처리 흐름에 솔루션을 맵핑 해보면 다음과 같다.



<그림 8. 람다 아키텍쳐에 대한 솔루션 맵핑> 


저장소는 대량의 데이타를 저비용으로, 안정성 있게 (유실이 없게) 저장할 수 있는 것이 필요하다. 그리고 이런 대량의 데이타를 배치로 처리할 때 되도록이면 빠른 시간내에 복잡한 알고리즘을 적용해서 계산할 수 있는 계층이 필요한데, 이러한 솔루션으로 제시되는 솔루션이 하둡의 HDFS(Hadoop File System)과 하둡의 MR (Map & Reduce)이다.

이렇게 계산된 배치 데이타를 저장할 장소가 필요한데, 하둡에서는 이런 데이타를 저장하고 고속으로 액세스할 수 있도록 HBase라는 NoSQL을 제공한다.

실시간 처리는 복잡한 알고지즘을 빠르게 데이타를 처리할 수 있는 솔루션이 필요한데, 대표적으로 Apache Storm등이 있으며, 빠른 읽기와 쓰기를 지원해야 하기 때문에, Redis와 같은 In-memory 기반의 NoSQL이 적절하게 추천되고 있다.

일반적으로 람다 아키텍쳐를 소개할때, 제안되는 솔루션의 형태이기는 하나, 람다 아키텍쳐는 특정 솔루션을 제안하는 아키텍쳐이기 보다는 데이타의 처리 기법을 소개하는 솔루션에 종속성이 없는 레퍼런스 아키텍쳐이다.

그래서 다른 솔루션 조합을 고려해볼 수 있는데, Dr.dobbs (http://www.drdobbs.com/database/applying-the-big-data-lambda-architectur/240162604)

에 소개된 솔루션 조합과 필자가 추천하는 조합을 추가해서 보면 다음과 같다.


<그림 9. 람다 아키텍쳐의 솔루션 조합>


여기서,필자가 Dr.Dobbs의 추천 솔루션 이외에, 배치 뷰와 실시간 뷰 쪽에, RDBMS를 추가하였는데, 배치뷰에 추가한 Amazon RedShift의 경우 아마존 클라우드 서비스에서 제공되는 Postgres 기반이 서비스로, 최대 16PB(페타바이트)까지의 용량을 지원한다. 이미 빅데이타라고 부를만큼의 충분한 데이타 사이즈를 지원할 뿐더라, RDBMS 기반의 SQL을 이용하여 유연한 데이타 조회가 가능하며, 리포트를 출력하기 위한 기존의 BI 툴과도 호환이 잘되서 많은 개발에 관련된 부분을 덜 수 있다. 실제로 통계 리포팅에서 가장 많은 시간이 소요되는 작업이, 비즈니스쪽 요구에 맞는 리포트를 만드는 작업이다.어떤 테이블과 그래프를 이용해서 데이터에 대한 의미를 보여줄 지는 단순한 리포팅 작업이라고 치부하기에는 매우 중요한 작업이며, 다양한 비즈니스 요건에 맞는 뷰를 보여 주기 위해서는 BI툴과의 연동은 많은 장점을 제공한다.

위에서 설명한 람다 아키텍쳐를 계층(Layer)로 나눠서 소개 하면 다음 그림과 같다.

실시간 데이터를 처리하는 부분을 스피드 레이어라고 부르며, 배치 처리는 배치 저장소와 배치 처리 부분을 배치 레이어라고 명명하고, 배치에 의해서 처리된 요약 데이터를 제공하는 부분을 서빙 레이어(Serving Layer)라고 한다.

 


<그림 10. 계층별로 추상화된 람다 아키텍쳐>

배치 레이어의 의미

배치 레이어의 저장소에는 가공전의 원본 데이터를 모두 저장한다. 데이터가 처리된 후에도 저장소에 데이터를 삭제 하지 않는다.

이렇게 원본 데이터를 저장함으로써, 배치 뷰의 데이터가 잘못 계산되었거나, 유실 되었을때, 복구가 가능하고, 현재 데이터 분석에서 없었던 새로운 뷰(통계)를 제공하고자 할 때 기존의 원본 데이터를 가지고 있음으로써, 기존 데이터에 대해서도 새로운 뷰의 통계 분석이 가능하다.


람다 아키텍쳐의 재구성

RDBMS를 활용한 유연성 증대 방안

이러한 람다 아키텍쳐는 대용량 데이터 처리와 실시간 정보 제공을 위한 장점을 가지고 있음에도 불구하고 대부분 하둡이나 NOSQL등의 솔루션을 조합해서 구현하는 경우가 대부분이기 때문에, 유연성 측면에서 문제점을 가지고 있다.

예를 들어 배치 뷰를 HBase를 사용하고, 실시간 뷰를 Redis를 사용할 경우, 상호 솔루션간 데이터 조인이 불가능할 뿐더러, 인덱스나 조인,그룹핑, 소팅 등이 어렵다. 이러한 기능이 필요하다면 각각 배치 처리와 실시간 처리 단계에 추가적으로 로직을 추가해서 새로운 뷰를 만들어야 한다.

쉽게 설명하면, 일반적인 NoSQL은 키-밸류 스토어의 개념을 가지고 있다.

그래서, 위의 그림3과 같은 테이블이 생성되었다 하더라도, 특정 컬럼 별로 데이터를 소팅해서 보여줄수 가 없다. 만약 소팅된 데이터를 표현하고자 한다면, 소팅이 된 테이블 뷰를 별도로 생성해야 한다.

참고 : NoSQL 데이터 모델링 패턴

http://bcho.tistory.com/665 , http://bcho.tistory.com/666

그래서 이런 문제점을 보강하기 위해서는 위에서도 잠깐 언급하였듯이 실시간 뷰와 배치 뷰 부분을 RDBMS를 사용하는 것을 고려해볼 수 있다. 쿼리에 특화된 OLAP 데이터 베이스를 활용하는 방법도 있고, 또는 HP Vertica 등을 활용할 수 있다. (HP Vertica는 SQL을 지원하지만, 전통적인RDBMS가 데이터를 행 단위로 처리하는데 반하여, Vertica는 데이터를 열 단위로 처리해서 통계나 쿼리에 성능이 매우 뛰어나다. 유료이지만 1테라까지는 무료로 사용할 수 있으니 뷰 테이블 용도 정도로 사용하는데는 크게 문제가 없다.)


데이터 분석 도구를 이용한 새로운 분석 모델 개발

분석 통계 데이터를 제공하다 보면, 저장소에 저장된 원본 데이터를 재 분석함으로써 추가적인 의미를 찾아낼 수 있는데, 이 영역은 데이터 과학자의 영역으로, 저장소에 있는 데이터를 통해서 새로운 데이터 모델을 추출해 내는 방식이다.

예를 들어, 글읽기 이벤트와 글쓰기 이벤트간의 상관 관계를 파악해내거나, 요일별 이벤트 변화량등을 분석해낼 수 있는데,

  1. 이 저장소에 R이나 MetLab과 같은 데이터 분석 도구를 이용하여, 샘플(표본) 데이터를 추출해서 데이터의 상관 관계를 파악해보고,

  2. 이러한 분석을 통해서 새로운 통계 모델을 설계하고 검증해볼 수 있다.

  3. 만약 이러한 모델이 적절하다면 알고리즘을 구현하고 이를 빅데이타 엔지니어에게 넘겨 준다.

  4. 빅데이타 엔지니어는 데이터 과학자에게서 받은 알고리즘을 람다 아키텍쳐의 각 레이어에 배치된 솔루션에 알맞은 형태로 구현한다.


 


<그림 11. 새로운 데이터 모델의 개발>

이러한 과정의 반복을 통해서, 분석 시스템은 지속적으로 발전되어가면서 데이터에 대한 더 많은 인사이트를 제공할 수 있게 된다.


결론

간단하게나마 람다 아키텍쳐에 대해서 알아보았다.

람다 아키텍쳐는 꼭 빅데이타에 적용하거나, 또는 하둡을 이용해야 하는 아키텍쳐가 아니다. RDBMS나 CSV 파일 등, 어떤 데이터 형태라도 기본은 배치를 이용한 집계 테이블과 실시간 뷰 테이블을 조인한다는 개념이기 때문에, 솔루션에 억메이지 말고, 적절한 시나리오를 찾아서 적용할 수 있도록 하면 좋겠다.


참고 : 

http://www.drdobbs.com/database/applying-the-big-data-lambda-architectur/240162604

http://www.infoq.com/articles/lambda-architecture-scalable-big-data-solutions



저작자 표시 비영리
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

마이크로 서비스 아키텍쳐 (MSA의 이해)

조대협(http://bcho.tistory.com)

 

배경


마이크로 서비스 아키텍쳐(이하 MSA)는 근래의 웹기반의 분산 시스템의 디자인에 많이 반영되고 있는 아키텍쳐 스타일로, 특정 사람이 정의한 아키텍쳐가 아니라, 분산 웹 시스템의 구조가 유사한 구조로 설계 되면서, 개념적으로만 존재하던 개념이다.

얼마전 마틴파울러(Martin folwer)가 이에 대한 MSA에 대한 개념을 글로 정리하여, 개념을 정립 시키는데 일조를 하였다.

이 글에서는 대규모 분산 웹시스템의 아키텍쳐 스타일로 주목 받고 있는 MSA에 대한 개념에 대해서 알아보도록 한다.


모노리틱 아키텍쳐(Monolithic Architecture)


마이크로 서비스 아키텍쳐를 이해하려면 먼저 모노리틱 아키텍쳐 스타일에 대해서 이해해야 한다

모노리틱 아키텍쳐 스타일은 기존의 전통적인 웹 시스템 개발 스타일로, 하나의 애플리케이션 내에 모든 로직들이 모두 들어 가 있는 “통짜 구조” 이다.

예를 들어, 온라인 쇼핑몰 애플리케이션이 있을때, 톰캣 서버에서 도는 WAR 파일(웹 애플리케이션 패키징 파일)내에, 사용자 관리,상품,주문 관리 모든 컴포넌트들이 들어 있고 이를 처리하는 UX 로직까지 하나로 포장되서 들어가 있는 구조이다.




각 컴포넌트들은 상호 호출을 함수를 이용한 call-by-reference 구조를 취한다.

전체 애플리케이션을 하나로 처리하기 때문에, 개발툴 등에서 하나의 애플리케이션만 개발하면 되고, 배포 역시 간편하며 테스트도 하나의 애플리케이션만 수행하면 되기 때문에 편리하다.

문제점

그러나 이러한 모노리틱 아키텍쳐 시스템은 대형 시스템 개발시 몇가지 문제점을 갖는다.

모노리틱 구조의 경우 작은 크기의 애플리케이션에서는 용이 하지만, 규모가 큰 애플리케이션에서는 불리한 점이 많다.

크기가 크기 때문에, 빌드 및 배포 시간, 서버의 기동 시간이 오래 걸리며 (서버 기동에만 2시간까지 걸리는 사례도 경험해봤음)

프로젝트를 진행하는 관점에서도, 한두사람의 실수는 전체 시스템의 빌드 실패를 유발하기 때문에, 프로젝트가 커질 수 록, 여러 사람들이 협업 개발하기가 쉽지 않다

또한 시스템 컴포넌트들이 서로 로컬 콜 (call-by-reference)기반으로 타이트하게 연결되어 있기 때문에, 전체 시스템의 구조를 제대로 파악하지 않고 개발을 진행하면, 특정 컴포넌트나 모듈에서의 성능 문제나 장애가 다른 컴포넌트에까지 영향을 주게 되며, 이런 문제를 예방하기 위해서는 개발자가 대략적인 전체 시스템의 구조 등을 이해 해야 하는데, 시스템의 구조가 커질 수 록, 개인이 전체 시스템의 구조와 특성을 이해하는 것은 어려워진다.

특정 컴포넌트를 수정하고자 했을때, 컴포넌트 재 배포시 수정된 컴포넌트만 재 배포 하는 것이 아니라 전체 애플리케이션을 재 컴파일 하여 전체를 다시 통으로 재배포 해야하기 때문에 잦은 배포가 있는 시스템의 경우 불리하며,

컴포넌트 별로, 기능/비기능적 특성에 맞춰서 다른 기술을 도입하고자 할때 유연하지 않다. 예를 들어서, 전체 애플리케이션을 자바로 개발했다고 했을 때, 파일 업로드/다운 로드와 같이 IO 작업이 많은 컴포넌트의 경우 node.js를 사용하는 것이 좋을 수 있으나, 애플리케이션이 자바로 개발되었기 때문에 다른 기술을 집어 넣기가 매우 어렵다.

※ 모노리틱 아키텍쳐가 꼭 나쁘다는 것이 아니다. 규모가 작은 애플리케이션에서는 배포가 용이하고, 규모가 크더라도, call-by-reference call에 의해서 컴포넌트간 호출시 성능에 제약이 덜하며, 운영 관리가 용이하다. 또한 하나의 구조로 되어 있기 때문에, 트렌젝션 관리등이 용이하다는 장점이 있다. 즉 마이크로 서비스 아키텍쳐가 모든 부분에 통용되는 정답은 아니며, 상황과 필요에 따라서 마이크로 서비스 아키텍쳐나 모노리틱 아키텍쳐를 적절하게 선별 선택 또는 변형화 해서 사용할 필요가 있다.


마이크로 서비스 아키텍쳐


마이크로 서비스 아키텍쳐는 대용량 웹서비스가 많아짐에 따라 정의된 아키텍쳐인데, 그 근간은 SOA (Service Oriented Architecture : 서비스 지향 아키텍쳐)에 두고 있다.

SOA는 엔터프라이즈 시스템을 중심으로 고안된 아키텍쳐라면, 마이크로 서비스 아키텍쳐는 SOA 사상에 근간을 두고, 대용량 웹서비스 개발에 맞는 구조로 사상이 경량화 되고, 대규모 개발팀의 조직 구조에 맞도록 변형된 아키텍쳐이다.


아키텍쳐 구조


서비스


마이크로 서비스 아키텍쳐에서는 각 컴포넌트를 서비스라는 개념으로 정의한다. 서비스는 데이타에서 부터 비지니스 로직까지 독립적으로 상호 컴포넌트간의 의존성이 없이 개발된 컴포넌트(이를 버티컬 슬라이싱/Vertical Slicing-수직적 분할이라고 한다.)로 REST API와 같은 표준 인터페이스로 그 기능을 외부로 제공한다.

서비스 경계는 구문 또는 도메인(업무)의 경계를 따른다. 예를 들어 사용자 관리, 상품 관리, 주문 관리와 같은 각 업무 별로 서비스를 나눠서 정의한다. 사용자/상품 관리 처럼 여러개의 업무를 동시에 하나의 서비스로 섞어서 정의하지 않는다.

REST API에서 /users, /products와 같이 주요 URI도 하나의 서비스 정의의 범위로 좋은 예가 된다.  


마이크로 서비스 아키텍쳐의 구조


마이크로 서비스 아키텍쳐의 구조는 다음과 같은 모양을 따른다.

각 컴포넌트는 서비스라는 형태로 구현되고 API를 이용하여 타 서비스와 통신을 한다.



배포 구조관점에서도 각 서비스는 독립된 서버로 타 컴포넌트와의 의존성이 없이 독립적으로 배포 된다.

예를 들어 사용자 관리 서비스는 독립적인 war파일로 개발되어, 독립된 톰캣 인스턴스에 배치된다. 확장을 위해서 서비스가 배치된 톰캣 인스턴스는 횡적으로 스케일 (인스턴스 수를 더함으로써)이 가능하고, 앞단에 로드 밸런서를 배치하여 서비스간의 로드를 분산 시킨다.



가장 큰 특징이, 애플리케이션 로직을 분리해서 여러개의 애플리케이션으로 나눠서 서비스화하고, 각 서비스별로 톰캣을 분산 배치한 것이 핵심이다.


데이타 분리


데이타 저장관점에서는 중앙 집중화된 하나의 통 데이타 베이스를 사용하는 것이 아니라 서비스 별로 별도의 데이타 베이스를 사용한다.       보통 모노리틱 서비스의 경우에는 하나의 통 데이타 베이스 (보통 RDBMS를 사용) 하는 경우가 일반적이지만, 마이크로 서비스 아키텍쳐의 경우, 서비스가 API에서 부터 데이타 베이스까지 분리되는 수직 분할 원칙 (Vertical Slicing)에 따라서 독립된 데이타 베이스를 갖는다.



데이타 베이스의 종류 자체를 다른 데이타 베이스를 사용할 수 도 있지만, 같은 데이타 베이스를 사용하더라도 db를 나누는 방법을 사용한다.

이 경우, 다른 서비스 컴포넌트에 대한 의존성이 없이 서비스를 독립적으로 개발 및 배포/운영할 수 있다는 장점을 가지고 있으나, 다른 컴포넌트의 데이타를 API 통신을 통해서만 가지고 와야 하기 때문에 성능상 문제를 야기할 수 있고, 또한 이 기종 데이타 베이스간의 트렌젝션을 묶을 수 없는 문제점을 가지고 있다. (이러한 데이타 분산에 의한 트렌젝션 문제는 SOA 때부터 있어 왔다.) 데이타 분산으로 인한 트렌젝션 문제는 뒤에서 조금 더 자세하게 설명하도록 한다.


API Gateway


마이크로 서비스 아키텍쳐 설계에 있어서 많이 언급되는 컴포넌트 중의 하나가 api gateway 라는 컴포넌트 이다. api gateway는 마치 프록시 서버 처럼 api들 앞에서 모든 api에 대한 end point를 통합하고, 몇가지 추가적인 기능을 제공하는 미들웨어로, SOA의 ESB (Enterprise Service Bus)의 경량화 버전이다. Apigateway가 마이크로 서비스 아키텍쳐 상에서 수행하는 주요 기능을 살펴보면 다음과 같다.

EndPoint 통합 및 토폴로지 정리

마이크로 서비스 아키텍쳐의 문제점 중의 하나는 각 서비스가 다른 서버에 분리 배포 되기 때문에, API의 End point 즉, 서버의 URL이 각기 다르다는 것이다.

사용자 컴포넌트는 http://user.server.com, 상품 컴포넌트는 http://product.server.com 과 같은 분리된 URL을 사용하는데, 이는 API 사용자 경험 관점에서도 사용하기가 불편하다. 특히 마이크로 서비스 아키텍쳐는 컴포넌트를 되도록이면 업무 단위로 잘게 짜르는 fine grained (작은 덩어리)의 서비스를 지향하기 때문에, 컴포넌트의 URL 수는 더 많이 늘어 날 수 있다.

API를 사용하는 클라이언트에서 서버간의 통신이나, 서버간의 API 통신의 경우 p2p(Point to Point)형태로 토폴로지가 복잡해지고 거미줄 모양의 서비스 컴포넌트간의 호출 구조는 향후 관리의 문제를 일으킬 수 있다. 하나의 end point를 변경하였을때, 제대로 관리가 되지 않을 경우가 있다.




<그림. P2P 형태의 토폴리지>

이러한 토폴로지상의 문제점을 해결하기 위해서 중앙에 서비스 버스와 같은 역할을 하는 채널을 배치 시켜서, 전체 토폴로지를 p2p에서 hub & spoke 방식으로 변환 시켜서, 서비스간 호출을 단순화 시킬 수 있다.




<그림. 버스 기반의 Hub & Spoke 토폴리지>

Orchestration


다른 기능으로는 orchestration 이라는 개념이 있다. 기존 open api의 mash up과 같은 개념으로, 여러개의 서비스를 묶어서 하나의 새로운 서비스를 만드는 개념이다.

예를 들어, 포인트 적립과, 물품 구매라는 서비스가 있을때, 이 두개의 서비스를 묶어서 “물품 구입시 포인트 적립”이라는 새로운 서비스를 만들어 낼 수 있다. 이러한 orchestration 기능은, api gateway를 통해서 구현될 수 있다.

이는 마이크로 서비스 아키텍쳐가 서비스 자체가 fine grained 형태로 잘게 쪼게졌기 때문에 가능한 일인데, 사실 orchestration을 api gateway 계층에서 하는 것은 gateway 입장에서 부담이 되는 일이다. 실제로 과거의 SOA 시절에 많은 ESB(Enterprise Service Bus) 프로젝트가 실패한 원인 중의 하나가 과도한 orchestration 로직을 넣어서 전체적인 성능 문제를 유발한 경우가 많았다. 그래서 orchestration 서비스의 활용은 마이크로 서비스 아키텍쳐에 대한 높은 이해와 api gateway 자체에 대한 높은 수준의 기술적인 이해를 필요로 한다.

실제로 넷플릭스의 경우 마이크로 서비스 아키텍쳐를 사용하면서, 여러개의 서비스들을 gateway 계층을 통해서 orchestration 하는 모델을 사용하고 있다. 


공통 기능 처리 (Cross cutting function handling)


또한 API에 대한 인증 (Authentication)이나, Logging과 같은 공통 기능에 대해서 서비스 컴포넌트 별로 중복 개발해야 하는 비효율성을 유발할 수 있다. api gateway에서 이러한 공통 기능을 처리하기 되면, api 자체는 비지니스 로직에만 집중을 하여 개발에 있어서의 중복등을 방지 할 수 있다.

mediation

이외에도 XML이나 네이티브 메세지 포맷을 json등으로 상호 변환해주는 message transformation 기능이나, 프로토콜을 변환하는 기능, 서비스간의 메세지를 라우팅해주는 기능등 여러가지 고급 mediation 기능을 제공을 하지만, api gateway를 최대한 가볍게 가져간다는 설계 원칙 아래서 가급 적이면 고급적인 mediation 기능을 사용할 때는 높은 수준의 설계와 기술적인 노하우를 동반해야 한다.


※ ESB vs APIgateway

SOA 프로젝트의 실패중의 하나가 ESB로 꼽히는 경우가 많은데, 이는 ESB를 Proxy나 Gateway처럼 가벼운 연산만이 아니라, 여러개의 서비스를 묶는 로직에  무겁게 사용했기 때문이다. (사용하면 안된다는 것이 아니라 잘 사용해야 한다는 것이다.) ESB는 메세지를 내부적으로 XML로 변환하여 처리하는데, XML 처리는 생각하는것 보다 파싱에 대한 오버헤드가 매우 크다.  또한 ESB의 고유적인 버스나 게이트웨이로써의 특성이 아니라 타 시스템을 통합 하기 위한 EAI적인 역할을 ESB를 이용해서 구현함으로써 많은 실패 사례를 만들어 내었다. 그래서 종종 ESB는 Enterprise Service Bus가 아니라 EnterpriSe nightmare Bus로 불리기도 한다. J

이러한 개념적인 문제를 해결하기 위해서 나온 제품군이 apigateway라는 미들웨어 제품군들인데, ESB와 기본적인 특성은 유사하나 기능을 낮추고 EAI의 통합 기능을 제거하고 API 처리에만 집중한 제품군들로, 클라우드상에서 작동하는 PaaS (Platform As A Service)형태의 서비스로는 apigee.com이나 3scale.com 등이 있고, 설치형 제품으로는 상용 제품인 CA社의 Layer7이나 오픈소스인 Apache Service Mix, MuleSoft의 ESB 제품 그리고 WSO2의 API Platform 등이 있다.

Apigateway 부분에 마이크로 서비스 아키텍쳐의 다른 부분 보다 많은 부분을 할애한 이유는, 컴포넌트를 서비스화 하는 부분에 까지는 대부분 큰 문제가 없이 적응을 하지만 apigateway의 도입 부분의 경우, 내부적인 많은 잡음이 날 수 있고, 또한 도입을 했더라도 잘못된 설계나 구현으로 인해서 실패 가능성이 비교적 높은 모듈이기 때문이다. 마이크로 서비스 아키텍쳐의 핵심 컴포넌트이기도 하지만, 도입을 위해서는 팀의 상당 수준의 높은 기술적인 이해와 개발 능력을 필요로 한다.


배포


마이크로 서비스 아키텍쳐의 가장 큰 장점 중의 하나가 유연한 배포 모델이다. 각 서비스가 다른 서비스와 물리적으로 완벽하게 분리되기 때문에 변경이 있는 서비스 부분만 부분 배포가 가능하다 예를 들어서, 사용자 관리 서비스 로직이 변경되었을 때, 모노리틱 아키텍쳐의 경우에는 전체 시스템을 재 배포해야 하지만, 마이크로 서비스 아키텍쳐의 경우에는 변경이 있는 사용자 관리 서비스 부분만 재 배포 하면 되기 때문에, 빠르고 전체 시스템의 영향도를 최소화한 수준에서 배포를 진행할 수 있다.


확장성


서비스 별로 독립된 배포 구조는 확장성에 있어서도 많은 장점을 가지고 오는데, 부하가 많은 특정 서비스에 대해서만 확장이 가능하여 조금 더 유연한 확장 모델을 가질 수 있다. 모노리틱 아키텍쳐의 경우에는 특정 서비스의 부하가 많아서 성능 확장이 필요할때, 전체 서버의 수를 늘리거나 각 서버의 CPU 수를 늘려줘야 하지만, 마이크로 서비스 아키텍쳐의 경우에는 부하를 많이 받는 서비스 컴포넌트 만 확장을 해주면 된다.


Conway’s Law (컨웨이의 법칙)


마이크로 서비스 아키텍쳐의 흥미로운 점중의 하나는 아키텍쳐 스타일의 조직 구조나 팀 운영 방식에 영향을 준다는 것인데, 마이크로 서비스 아키텍쳐는 컨웨이의 법칙에 근간을 두고 있다.

컨웨이의 법칙은 “소프트웨어의 구조는 그 소프트웨어를 만드는 조직의 구조와 일치한다”는 이론이다.

현대의 소프트웨어 개발은 주로 애자일 방법론을 기반으로 하는 경우가 많다. 애자일 팀의 구조는 2 피자팀(한팀의 인원수는 피자 두판을 먹을 수 있는 정도의 인원 수가 적절하다.)의 모델을 많이 따르는데, 한 팀이 7~10명정도로 이루어지고, 이 인원 수가 넘어가면 팀을 분리하는 모델이다.

마이크로 서비스 아키텍쳐는 각 컴포넌트를 팀에 배치해서 책임지고 개발하는 것을 근간으로 하며, 팀간의 의존성을 제거해서 각 팀이 컴포넌트 개발을 독립적으로할 수 있는 구조로 잡혀있다.


마이크로 서비스 아키텍쳐의 문제점


분홍빛 미래 처럼 보이는 마이크로 서비스 아키텍쳐는 아무런 문제가 없는 것일까? 당연히 여러가지 장점을 제공하는 대신에 그만한 단점을 가지고 있다.


성능


모노리틱 아키텍쳐는 하나의 프로세스 내에서 서비스간의 호출을 call-by-reference 모델을 이용한다. 반면 마이크로 서비스 아키텍쳐는 서비스간의 호출을 API 통신을 이용하기 때문에 값을 json이나 xml에서 프로그래밍에서 사용하는 데이타 모델 (java object등)으로 변환하는 marsharing 오버헤드가 발생하고 호출을 위해서 이 메세지들이 네트워크를 통해서 전송되기 때문에 그만한 시간이 더 추가로 소요된다.


메모리


마이크로 서비스 아키텍쳐는 각 서비스를 독립된 서버에 분할 배치하기 때문에, 중복되는 모듈에 대해서 그만큼 메모리 사용량이 늘어난다.

예를 들어 하나의 톰캣 인스턴스에서 사용자 관리와 상품 관리를 배포하여 운용할 경우, 하나의 톰캣을 운영하는데 드는 메모리와, 스프링 프레임웍과 같은 라이브러리를 사용하는데 소요되는 메모리 그리고 각각의 서비스 애플리케이션이 기동하는 메모리가 필요하다.

그러나 마이크로 서비스 아키텍쳐로 서비스를 배포할 경우 사용자 관리 서비스 배포와 상품 관리 서비스 배포를 위한 각각의 별도의 톰캣 인스턴스를 운용해야 하고, 스프링 프레임웍과 같은 공통 라이브러리도 각각 필요하기 때문에, 배포하고자 하는 서비스의 수 만큼 중복된 양의 메모리가 필요하게 된다.

위의 두 문제는 반드시 발생하는 문제점이기는 하나 현대의 인프라 환경에서는 크게 문제는 되지 않는다. (기존에 비해 상대적으로). 현대의 컴퓨팅 파워 자체가 워낙 발달하였고, 네트워크 인프라 역시 기존에 1G등에 비해서 내부 네트워크는 10G를 사용하는 등, 많은 성능상 발전이 있었다. 또한 메모리 역시 비용이 많이 낮춰지고 32bit에서 64bit로 OS들이 바뀌면서, 가용 메모리 용량이 크게 늘어나서 큰 문제는 되지 않는다. 또한 성능상의 문제는 비동기 패턴이나 캐슁등을 이용해서 해결할 수 있는 다른 방안이 많기 때문에 이 자체는 큰 문제가 되지 않는다.

그보다 더 문제점은 아래에서 언급하는 내용들인데,


테스팅이 더 어려움


마이크로 서비스 아키텍쳐의 경우 서비스들이 각각 분리가 되어 있고, 다른 서비스에 대한 종속성을 가지고 있기 때문에, 특정 사용자 시나리오나 기능을 테스트하고자 할 경우 여러 서비스에 걸쳐서 테스트를 진행해야 하기 때문에 테스트 환경 구축이나 문제 발생시 분리된 여러개의 시스템을 동시에 봐야 하기 때문에 테스팅의 복잡도가 올라간다.

운영 관점의 문제


운영 관점에서는 서비스 별로 서로 다른 기술을 사용할 수 있으며, 시스템이 아주 잘게 서비스 단위로 쪼게 지기 때문에 운영을 해야할 대상 시스템의 개수가 늘어나고, 필요한 기술의 수도 늘어나게 된다.


서비스간 트렌젝션 처리


구현상의 가장 어려운 점중의 하나가, 트렌젝션 처리이다. 모노리틱 아키텍쳐에서는 RDBMS를 사용하면서 하나의 애플리케이션 내에서 트렌젝션이 문제가 있으면 쉽게 데이타베이스의 기능을 이용해서 rollback을 할 수 있었다. 여러개의 데이타베이스를 사용하더라도, 분산 트렌젝션을 지원하는 트렌젝션 코디네이터 (JTS – Java Transaction Service)등을 이용해서 쉽게 구현이 가능했는데, API 기반의 여러 서비스를 하나의 트렌젝션으로 묶는 것은 불가능 하다.

쉽게 예를 들어서 설명을 하면, 계좌에서 돈을 빼는 서비스와, 계좌에 돈을 넣는 서비스가 있다고 하자. 이 둘은 API를 expose했을 때, 계좌에서 돈을 뺀 후, 계좌에 돈을 넣기 전에 시스템이 장애가 나면, 뺀 돈은 없어지게 된다. 모노리틱 아키텍쳐를 사용했을 경우에는 이러한 문제를 트렌젝션 레벨에서 롤백으로 쉽게 해결할 수 있지만 API 기반의 마이크로 서비스 아키텍쳐에서는 거의불가능하다.

사실 이 문제는 마이크로 서비스 아키텍쳐 이전에도, 서비스와 API를 기본 컨셉으로 하는 SOA에도 있었던 문제이다.

이러한 문제를 해결하기 위해서 몇가지 방안이 있는데,

그 첫번째 방법으로는 아예 애플리케이션 디자인 단계에서 여러개의 API를 하나의 트렌젝션으로 묶는 분산 트렌젝션 시나리오 자체를 없애는 방안이다. 분산 트렌젝션이 아주 꼭 필요할 경우에는 차라리 모노리틱 아키텍쳐로 접근하는 것이 맞는 방법이다. 앞서도 언급했듯이 마이크로 서비스 아키텍쳐의 경우, 금융이나 제조와 같이 트렌젝션 보장이 중요한 엔터프라이즈 시스템보다는 대규모 처리가 필요한 B2C 형 서비스에 적합하기 때문에, 아키텍쳐 스타일 자체가 트렌젝션을 중요시 하는 시나리오에서는 적절하지 않다.

그럼에도 불구하고, 트렌젝션 처리가 필요할 경우, 트렌젝션 실패시 이를 애플리케이션 적으로 처리해 줘야 하는 데, 이를 보상 트렌젝션(compensation transaction)이라고 한다. 앞의 계좌 이체 시나리오에서 돈을 뺀 후, 다른 계좌에 넣다가 에러가 났을 경우에, 명시적으로, 돈을 원래 계좌로 돌려주는 에러 처리 로직을 구현해야 한다.

마지막 방법으로 복합 서비스 (composite service)라는 것을 만들어서 활용하는 방법이 있는데, 복합 서비스란 트렌젝션을 묶어야 하는 두개의 시스템을 트렌젝션을 지원하는 네이티브 프로토콜을 이용해서 구현한 다음 이를 API로 노출 시키는 방법이다.

두개의 데이타 베이스는 XA(eXtended Architecture)와 같은 분산 트렌젝션 프로토콜을 써서 서비스를 개발하거나 또는 SAP나 Oracle 아답터와 같이 트렌젝션을 지원하는 네이티브 아답터를 사용하는 방법이다. 기존에 SOA에서 많이 했던 접근방법이기는 하나, 복합 서비스를 사용할 경우, 복합서비스가 서로 다른 두개의 서비스에 걸쳐서 tightly coupled하게 존재하기 때문에, 마이크로 서비스 아키텍쳐의 isolation(상호 독립적)인 사상에 위배되고 서비스 변경시에 이 부분을  항상 고려해야 하기 때문에 아키텍쳐상의 유연성이 훼손되기 때문에 꼭 필요하지 않은 경우라면 사용하지 않는 것이 좋다.


거버넌스 모델


거버넌스 (governance)란, 시스템을 개발하는 조직의 구조나 프로세스를 정의한 것으로, 일반적으로 중앙 집중화된 조직에서 표준 프로세스와 가이드를 기반으로 전체 팀을 운용하는 모델을 사용한다. 이를 중앙 집중형 거버넌스 모델 (Centralized governance model) 이라고 하는데, 이 경우 전체 시스템이 동일한 프로세스와 기술을 가지고 개발이 되기 때문에, 유지 보수가 용이하고 팀간의 인원 교체등이 편리하다는 장점을 가지고 있다. 전통적인 개발 모델들은 이러한 중앙 집중현 거버넌스 모델을 사용한다.

그러나 현대의 웹 개발의 경우, 오픈 소스 발달로 선택 가능한 기술들이 많고 각 요구 사항에 따라서 효율성 측면등을 고려할때 각각 최적화된 기술을 사용하는 것이 좋은 경우가 있다.

예를 들어, 전체 표준을 자바+RDBMS로 정했다 하더라도, 파일 업로드 다운로드 관련 컴포넌트는 io 성능과 많은 동시접속자를 처리할 수 있는 node.js가 유리하다던지, 데이타의 포맷은 복잡하지만, 복잡한 쿼리가 없을 경우에는 json document 기반의 mongodb와 같은 NoSQL등이 유리한 사례 등이 된다. 이러한 기술을 도입하기 위해서는 중앙 집중형 거버넌스 모델에서는 모든 개발팀을 교육 시키고, 운영 또한 준비를 해야하기 때문에 기술에 대한 적용 민첩성이 떨어지게 된다.

이러한 문제점을 해결 하는 거버넌스 모델이 분산형 거버넌스 모델 (De-Centralized governance model)인데, 이는 각 팀에 독립적인 프로세스와 기술 선택 권한을 주는 모델로, 각 서비스가 표준 API로 기능을 바깥으로 노출할 뿐 내부적인 구현 기술 구조는 추상화되어 가능한 사상이다

분산형 거버넌스 모델을 수행하려면, 이에 맞는 팀구조가 필요한데, 이 팀 구조는 다음과 같은 몇가지 특징을 가지고 있어야 한다.


Cross functional team


기존의 팀 모델은 역할별로 나뉘어진 모델로 팀을 구분한다. 기획팀,UX팀,개발팀,인프라 운영팀 등 공통적인 특성으로 나누는 것이 기존의 팀 모델이다. 이런 팀 모델은 리소스의 운영에 유연성을 부여한다. 개발 인력이 모자르면 팀 내에서 개발인원을 다른 프로젝트에서 충당하는 등의 리소스 운영이 가능하지만 반대로 팀간의 커뮤니케이션이 팀이라는 경계에 막혀서 원할하지 않고 협의에 걸리는 시간으로 인해서 팀의 운영 속도가 떨어진다.

cross function team 모델은 하나의 팀에 UX, 개발팀,인프라팀등 소프트웨어 시스템을 개발하는데 필요한 모든 역할을 하나의 팀에 구성하고 움직이는 모델로, 각 서비스 개발팀이 cross functional team이 되서 움직인다.



<그림 역할 중심의 개발팀 과 cross functional team에 대한 모델 비교>

이 경우 서비스 기획에서 부터 설계,개발,운영이 가능해지고 다른 팀에 대한 의존성이 없어짐으로써 빠른 서비스 개발이 가능해진다.


You build,You run-Devops


기술에 대한 독립성을 가지려면 구현 뿐만 아니라 운영 또한 직접할 수 있는 능력을 가져야 한다. 그래서 개발과 운영을 하나의 조직에 합쳐 놓는 구조를 Devops라고 한다.

Devops는 Development와 Operation을 합성한 단어로, 개발팀과 운영팀이 다른 팀으로 분리되어 있어서 발생하는 의사 소통의 문제점을 해결하고, 개발이 운영을 고려하고, 운영에서 발생하는 여러 문제점과 고객으로부터의 피드백을 빠르게 수용하여 서비스 개선에 반영하는 개발 모델이다.

이런 모델이 가능해진 이유는 운영팀만의 고유 영역이었던 인프라에 대한 핸들링이 클라우드의 도입으로 인해서 쉬워져서, 애플리케이션 개발자도 웹사이트를 통해서 손쉽게 디스크나 네트워크 설정, 서버 설정등이 가능해졌기 때문이다.

Devops는 대단히 좋은 모델이고 아마존이나 넷플릭스등이 적용하고 있는 모델이기는 하나, 이 역시 대단히 높은 수준의 팀의 성숙도가 필요하다.

개발자가 애플리케이션 개발 뿐만 아니라, 인프라에 대한 설계 및 운영까지 담당해야 하기 때문에 기존의 애플리케이션만 개발하던 입장에서는 대단히 부담이 되는 일이다.

좋은 모델이기는 하지만 충분히 준비가 되지 않은 상태에서 넘어가게 되면은 운영상의 많은 장애를 유발하기 때문에, 팀의 성숙도에 따라서 심각하게 고민해보고 적용을 해보기를 권장한다.


Project vs product


분산형 거버넌스 모델에서 중요한 점 중의 하나는 연속성이다. 거버넌스를 분산 시켜버렸기 때문에 팀별로 다른 형태의 표준과 기술 프로세스를 통해서 개발을 하기 때문에, 새로운 인원이 들어오거나 다른 팀으로 인원이 이동하였을 경우 팀에 맞는 형태의 재 교육이 필요하고 그간의 축적된 노하우가 100% 활용되지 못할 수 가 있기 때문에 가능하면 팀원들은 계속해서 해당 서비스 개발에 집중할 필요가 있다.

이를 위해서는 프로젝트의 컨셉 변화가 필요한데, 일반적으로 프로젝트란 일정 기간에 정해진 요구 사항을 구현하는데 목표가 잡혀 있으며, 프로젝트가 끝나면 인원은 다시 흩어져서 새로운 프로젝트에 투입 되는 형태로 역할 중심의 프로젝트팀 운용 방식에는 적절하다.

그러나 분산형 거버넌스 모델에서는 팀원의 영속성을 보장해줘야 하는데 이를 위해서는 프로젝트가 아니라 프로덕트(즉 상품)형태의 개념으로 개발 모델이 바뀌어야 한다. 팀은 상품에 대한 책임을 지고, 요구사항 정의 발굴에서 부터 개발 그리고 운영까지 책임을 지며, 계속해서 상품을 개선해 나가는 활동을 지속해야 한다. 이를 상품 중심의 개발팀 모델이라고 한다.


Self-organized team


이러한 요건등이 만족 되면, 팀은 독립적으로 서비스 개발을 할 수 있는 형태가 된다. 스스로 기획하고 개발하며 운영을 하며 스스로 서비스를 발전 시키는 하나의 회사와 같은 개념이 되는 것이다.

이렇게 독립적인 수행 능력을 가지고 있는 팀 모델을 self-organized team 모델이라고 한다.


Alignment 


이러한 분산형 거버넌스 모델을 수행하기 전에 반드시 주의해야 할 점이 있는데, alignment 라는 개념이다 alignment는 각 팀간의 커뮤니케이션 방법이나 프로세스등 최소한 표준과 기술적인 수준을 맞추는 과정인데, 쉽게 이야기해서 개발 경험이 전혀 없는 대학을 갓졸업한 사람들로 팀을 만들고, 기존의 팀들은 4~5년차 경력 인원들만으로 팀을 만들어서 전체 팀을 운용하면 어떻게 될까?

마이크로 서비스 아키텍쳐는 각 서비스들이 상호 의존성을 가지고 있기 때문에, 개발경험이 없는 팀이 전체 팀의 개발 속도를 못 따라오고, 또한 품질등에도 심각한 문제가 생긴다. 그래서 어느 일정 수준 이상으로 팀의 능력을 끌어 올려주고, 전체 팀에서 사용하는 최소한의 공통 프로세스등에 대해서는 서로 맞추어 놓을 필요가 있다. 이것이 바로 alignment 의 개념이다.

분산형 거버넌스 모델을 잘못 해석하거나 악용이 되면 팀에게 무조건적인 자치권을 부여하는 것으로 오역되서.. “분산형 거버넌스가 대세랍니다. 우리팀은 우리가 알아서 할테니 신경 끄세요.” 라는 형태의 잘못된 요청으로 전체 팀과 전체 시스템 아키텍쳐를 망쳐 버릴 수 있다.

제대로 된 해석은 “우리는 전체 팀이 나가야 할 방향과 비지니스 밸류에 대해서 이해를 하고 있습니다. 또한 이미 팀간의 커뮤니케이션이나 전체 시스템 구조에 대한 이해를 하고 있습니다. 이를 바탕으로 조금 더 빠른 개발과 효율성을 위한 모든 기능(역할)을 가지고 있는 팀을 운영하고자 합니다.” 가 제대로 된 해석이라고 볼 수 있겠다.


Evolutionary Model (진화형 모델)


지금 까지 간략하게나마 마이크로 서비스 아키텍쳐에 대해서 알아보았다.

마이크로 서비스 아키텍쳐는 서비스의 재사용성, 유연한 아키텍쳐 구조, 대용량 웹 서비스를 지원할 수 있는 구조등으로 많은 장점을 가지고 있지만, 운영하는 팀에 대해서 높은 성숙도를 필요로 한다. 그래서 충분한 능력을 가지지 못한 팀이 마이크로 서비스 아키텍쳐로 시스템을 개발할 경우에는 많은 시행 착오를 겪을 수 있다.

마이크로 서비스 아키텍쳐를 적용할때는 처음 부터 시스템을 마이크로 서비스 아키텍쳐 형태로 설계해서 구현할 수 도 있겠지만, 모노리틱 시스템에서 부터 시작하여, 비지니스 운용시 오는 문제점을 기반으로 점차적으로 마이크로 서비스 아키텍쳐 형태로 진화 시켜 나가는 방안도 좋은 모델이 된다. 비지니스와 고객으로 부터 오는 피드백을 점차적으로 반영 시켜나가면서 동시에 팀의 성숙도를 올려가면서 아키텍쳐 스타일을 변화 시켜가는 모델로, 많은 기업들이 이런 접근 방법을 사용했다. 트위터의 경우에도, 모노리틱 아키텍쳐에서 시작해서 팀의 구조를 점차적으로 변환 시켜 가면서 시스템의 구조 역시 마이크로 서비스 아키텍쳐 형태로 전환을 하였고, 커머스 시장에서 유명한 이베이 같은 경우에도, 그 시대의 기술적 특성을 반영하면서 비지니스의 요구 사항을 적절히 반영 시켜가면서 시스템을 변화 시켜 나가는 진화형 모델로 아키텍쳐를 전환 하였다.


SOA와 비교


마이크로 서비스 아키텍쳐는 종종 SOA와 비교 되며, SOA는 틀리고 마이크로 서비스 아키텍쳐는맞다 흑백 논리 싸움이 벌어지고는 하는데,

SOA와 마이크로 서비스 아키텍쳐는 사실상 다른 개념이 아니라 SOA가 마이크로 서비스 아키텍쳐에 대한 조상 또는 큰 수퍼셋의 개념이다. 흔히 SOA가 잘못되었다고 이야기 하는 이유는 SOA를 아키텍쳐 사상으로 보는 것이 아니라 SOAP 기반의 웹서비스나, Enterprise Service Bus와 같은 특정 제품을 SOA로 인식하기 때문이다. SOA는 말 그대로 설계에 대한 사상이지 특정 기술을 바탕으로 한 구현 아키텍쳐가 아니다.

큰 의미에서 보자면 마이크로 서비스 아키텍쳐의 서비스 역시, SOA에서 정의한 서비스 중에서 fine grained 서비스로 정의되는 하나의 종류이며, api gateway역시 SOA 에서 정의한 ESB의 하나의 구현방식에 불과 하다.

만약에 기회가 된다면 마이크로 서비스 아키텍쳐에 대해 제대로 이해하기 위해서 SOA 를 반드시 공부해보기를 바란다.


결론


마이크로 서비스 아키텍쳐는 대용량 웹시스템에 맞춰 개발된 API 기반의 아키텍쳐 스타일이다. 대규모 웹서비스를 하는 많은 기업들이 이와 유사한 아키텍쳐 설계를 가지고 있지만, 마이크로 서비스 아키텍쳐가 무조건 정답은 아니다. 하나의 설계에 대한 레퍼런스 모델이고, 각 업무나 비지니스에 대한 특성 그리고 팀에 대한 성숙도와 가지고 있는 시간과 돈과 같은 자원에 따라서 적절한 아키텍쳐 스타일이 선택되어야 하며, 또한 아키텍쳐는 처음 부터 완벽한 그림을 그리기 보다는 상황에 맞게 점진적으로 진화 시켜 나가는 모델이 바람직하다.

 특히 근래의 아키텍쳐 모델은 시스템에 대한 설계 사상 뿐만 아니라 개발 조직의 구조나 프로젝트 관리 방법론에 까지 영향을 미치기 때문에 단순히 기술적인 관점에서가 아니라 조금 더 거시적인 관점에서 고려를 해볼 필요가 있다.

 

참고 자료

Ebay 아키텍쳐 : http://www.addsimplicity.com/downloads/eBaySDForum2006-11-29.pdf

Netflix 아키텍쳐 : http://techblog.netflix.com/2013/01/optimizing-netflix-api.html

infoQ Microservice Architecture : http://www.infoq.com/articles/microservices-intro

MicroService 개념 http://microservices.io/patterns/microservices.html

Martin folwer : http://martinfowler.com/articles/microservices.html

Dzone microservice architecture : http://java.dzone.com/articles/microservice-architecture

Thought works의 PPT : http://www.infoq.com/presentations/Micro-Services

node.js로 apigateway 만들기 : 정리 잘되어 있음. http://plainoldobjects.com/presentations/nodejs-the-good-parts-a-skeptics-view/

저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

Microservice architecture note

아키텍쳐 /SOA | 2014.08.20 16:37 | Posted by 조대협

MSA (Microservice Architecture) 

자료 수집


참고 자료

Ebay 아키텍쳐 : http://www.addsimplicity.com/downloads/eBaySDForum2006-11-29.pdf

Netflix 아키텍쳐 : http://techblog.netflix.com/2013/01/optimizing-netflix-api.html

infoQ Microservice Architecture : http://www.infoq.com/articles/microservices-intro

MicroService 개념 http://microservices.io/patterns/microservices.html

Martin folwer : http://martinfowler.com/articles/microservices.html

Dzone microservice architecture : http://java.dzone.com/articles/microservice-architecture

Thought works의 PPT : http://www.infoq.com/presentations/Micro-Services

node.js로 apigateway 만들기 : 정리 잘되어 있음. http://plainoldobjects.com/presentations/nodejs-the-good-parts-a-skeptics-view/


Conway's 법칙에 연관됨

You build, You run - Devops, Amazon

De-Centralized governance - 기술 표준화 보다는 다양한 기술을 허가. Microserice들을 스크립트 언어로 빠르게 만들어 버림. 

Cross platform, Self organized team 모델 지향 - Align 되기전에 Self organized로 이동되면. 망함. 

운영이 HELL이다. 높은 운영 능력, 장애 처리, Devops 필요.



==> 공감 x 100배 (나만 겪는 문제가 아니구만..)

ESB (Enterprise Night Bus.. ) 


저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

'아키텍쳐  > SOA' 카테고리의 다른 글

Microservice architecture note  (0) 2014.08.20
Open API design  (0) 2013.07.06
통신 사업자의 SDP의 필수 컴포넌트  (0) 2010.08.03
SDP (Service Delivery Platform)  (1) 2009.09.15
모차세대 시스템의 WAS 아키텍쳐 Blue Print  (8) 2009.07.30
EAI관점에서 본 SOA  (6) 2009.07.29

Couchbase Server

#6. Couchbase server 구조

조대협 http://bcho.tistory.com




이번에는 마지막으로 카우치베이스의 아키텍쳐에 대해서 알아보도록 하자

노드와 클러스터 (Node & Cluster)

노드는 물리적인 서버에서 기동하는 하나의 카우치베이스 인스턴스로, 카우치 베이스는 여러 개의 노드로 이루어진 클러스터로 구성된다


클라이언트 SDK (Client SDK)

프로그래밍 언어별로 카우치베이스에 접근하기 위한 API(SDK)를 제공한다.


vBucket 개념

카우치베이스는 실제데이타와 물리서버간의 맵핑을 vBucket이라는 것을 이용해서 관리한다. 카우치베이스는 키-밸류 스토어이다. 그래서, 각 키가 어디에 저장되어 있는지를 vBucket이라는 단위로 관리 하는데. 키에 대한 해쉬값을 계산한 후에, 각 해쉬값에 따라서 저장되는 vBucket을 맵핑한다음 각 vBucket을 노드에 맵핑한다.

아래는 서버 3대가 있었을 때, vBucket을 맵핑하는 구조에 대한 예제이다.



※ 출처 : http://docs.couchbase.com/couchbase-manual-2.5/cb-admin/#vbuckets

클라이언트 SDK는 이 vBucket와 노드에 대한 맵핑 정보를 클러스터로부터 받아서 관리한다. 즉 키에 대한 물리적인 서버 맵핑 정보를 클라이언트가 SDK를 통해 직접알 수 있기 때문에, 클라이언트가 PROXY등을 거치지 않고 직접 데이터가 저장된 노드로 접근이 가능하다.

CF. mongoDB의 경우 중간에 Proxy를 거쳐서 데이터가 저장된 물리 노드로 접근하게 된다.

만약에 노드가 추가되거나 삭제되었을 때, 물리적으로 데이터가 다른 노드로 다시 분산 배치되고, 새롭게 배치된 데이터에 따라서 vBucket to 노드간의 데이터 맵핑 정보도 업데이트 되는데, 이를 Rebalancing이라고 한다. (Rebalancing에 대한 내용은 뒤에 다시 설명)



http://docs.couchbase.com/couchbase-manual-2.5/images/vbuckets-after.png 


노드의 상세구조

그러면 각 노드는 어떤 형태로 구성이 될까? 아래는 노드의 대략적인 아키텍쳐이다.

카우치베이스의 노드는 아래 그림과 같이 크게 좌측의 Data Manager와 우측의 Cluster Manager로 나뉘어 진다.




Cluster Manager

Cluster Manager는 노드에 대한 상태와 클러스터에 대한 상태, 설정등을 관리하는 부분으로 Erlang/OTP 기반으로 구현되어 있다. 그 상위단에는 Admin Portal을 위한 Web UI가 8091 포트로 제공되고 있고, 같은 포트로 REST API가 함께 제공된다.

카우치베이스는 클라이언트 SDK는 이 8091 포트의 REST API를 통해서, 설정 정보와 앞서 설명한 vBucket 정보를 읽어온다. 여기에는 실제로 데이터에 대한 set/get이나 뷰 쿼리 수행용 포트정보도 포함이 되는데,  아래 Data Manager에서 제공되는 11211 포트나, 8092 포트가 사용된다..

그 외에도 클러스터 노드간의 통신을 위한 4389, 21100 포트등 다수의 포트가 사용되는데, 카우치베이스는 서버-클라이언트, 서버-서버간에 사용하는 포트들이 많기 때문에, 배포 전에 반드시 포트들을 확인하고 방화벽이나 네트워크 설정에 반영해야 한다.

※ http://docs.couchbase.com/couchbase-manual-2.5/cb-admin/#faqs 문서를 보면 배포시 오픈해야 하는 포트들이 설명되어 있다.


Data Manager

Data Manager 부분은 직접 데이터에 접근하는 부분으로 set/get 메서드를 이용하여 데이터를 저장하거나, 뷰에 대한 쿼리를 수행할 때 접근되는 인터페이스이다.

맨 아래단에는 멀티쓰레드 기반의 Persistence 엔진이 있으며, 디스크에 데이터를 저장하거나 읽어드릴때 사용되는 컴포넌트이다. 그 윗단에는 memcached가 있으며, 데이터를 캐슁하는데 사용된다. 또한 이 계층에서 뷰에 대한 쿼리 엔진이 제공된다.

Memcached 위에는 moxi 가 Proxy로 사용된다.


데이터 쓰기와 복제

클라이언트에서 데이터 쓰기가 발생했을 때, 카우치베이스는 어떻게 데이터를 저장할까?

먼저 클라이언트에서 Client SDK를 통해서 쓰기 요청을 하면, Client SDK는 해쉬 알고리즘에 따라데이터의 키 값에 맵핑 되는 vBucket을 찾아내고, 그 vBucket에 맵핑 되는 노드를 찾아서 쓰기 요청을 전달한다.

쓰기 요청은 해당 노드의 Listener로 전달되고, 이 Listener는 들어온 데이터를 로컬의 캐쉬에 쓰고 클러스터의 다른 노드로 복제 요청을 보낸다. 그리고 데이터는 노드의 디스크에 저장된다.




쓰기 과정중에 노드간의 복제가 발생한다.


노드별 메모리 레이아웃

그러면 각 노드별로 메모리 레이아웃은 어떻게 되어 있을까? 카우치베이스의 경우, memcached를 이용하는 만큼 서버의 메모리 공간 계산이 매우 중요하다. 앞서 글들에서도 설명하였지만, 메모리에 대해서 고려할 때, 카우치 베이스는 버킷의 키를 모두 메모리에 로딩해놓고 있다. 최소 메모리 공간은 전체키의 합보다는 최소한 커야 한다.그리고 각 도큐먼트당 60바이트의 메타 정보 저장공간이 필요하다. (키크기 + 60 바이트)*전체레코드수 / 노드수 * 3 (복제본수) 가 노드당 최소 메모리양이다. 최소 메모리란 말 그대로 최소한 돌릴 수 있는 수준을 이야기하는 것인데, 이 경우에는 캐쉬를 전혀 사용하지 못하기 때문에, 이 메모리 용량으로 서버를 운영하면 절대 안된다. (말그대로 아주 최~~소한이다.)


전체 하드웨어 공간에서 OS가 기본적으로 사용하는 용량을 제외 하면, 카우치베이스의 노드가 그 메모리 공간을 활용하는데, 카우치베이스에서는 노드에 할당된 메모리 공간을 버킷별로 다시 할당한다. (버킷을 생성할 때 설정할 수 있음)


리밸런스(Rebalance)

리밸런스 노드가 클러스터에 추가되거나, 장애등의 이유로 삭제되었을 때 데이터를 다시 노드에 분산 배치를 하는 작업이다. 노드간에 데이터 복제가 심하게 일어나기 때문에, 리밸런스는 부하가 적은 시간대에 하도록 권장하고 있다. (관리 콘솔을 보면 리밸런스를 멈추거나 시작할 수 있는 기능이 있다.) 향후에는 리밸런스를 Throttling 하는 기능이 나온다고 하니 기대해볼만하다.

NoSQL의 경우 특정 노드가 장애가 나서 시스템이 장애 나는 케이스보다 보통 노드를 추가/삭제할때 발생하는 이런 리밸런싱에 의해서 부하가 올라가거나 해서 장애가 나오는 케이스가 많기 때문에 특별히 주의를 기울일 필요가 있다.

 

XDCR

XDCR은 데이타 센터간에 카우치베이스 클러스터 데이타 복제를 지원하는 기능이다.

현재 최신 버전은 2.5 버전인데, 2.5 버전에서는 XDCR을 TLS/SSL을 이용해서 복제하기 때문에 자체적으로 보안을 지원한다. 그렇지만 무료 버전인 2.2 (Community Edition)의 경우 TLS/SSL 기반의 복제가 지원되지 않기 때문에, VPN 기반의 네트워크를 터널을 설정하고, VPN 터널을 통해서 XDCR 복제를 하도록 가이드 하고 있다.


Couchbase Gateway & CouchBase Mobile

카우치베이스의 흥미로운 점중의 하나는 모바일 디바이스에 탑재될 수 있는 Couchbase Lite버전을 제공한다는 것이다. iOS,안드로이드 버전을 제공하며, 또는 일반적인 애플리케이션에 사용할 수 있도록 자바버전과 .NET  버전도 제공된다. (모두 Community edition이 제공된다)

이 Couchbase Lite는 Couchbase 서버와 동기화가 가능하다.


다 못한 이야기

개발 관점에서는 GET/SET그리고 뷰 정도로 간편하지만, 운영과 설정에 대해서는 많아도 너무 많다. 대략적인 사용방법 아키텍쳐에 대해서 알아봤는데, 언급하지 못한 부분이 있어서 몇 가지만 언급하고자 한다.

카우치베이스는 다양한 커넥터를 이용하여 다른 솔루션과의 연동을 지원한다.

Elastic Search와 연동을 통하여 데이터에 대한 FTS (Full Text Search : 검색)을 지원할 수 있으며, Hadoop 연동을 통해서 Map & Reduce 기반의 데이터 처리가 가능하다. 또 오픈소스 ETL인 Talend 연동을 통해서 데이터를 다른 시스템으로 연동(복제)가 가능하며, 마지막으로, 데이터 암호화 솔루션인 Gazzang과 연동을 통해서 데이터를 암호화하여 저장할 수 있다.

http://www.couchbase.com/couchbase-server/connectors

 


저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

괜찮은 책들 정리




Security Patterns in Practice

저자
Fernandez-Buglioni, Eduardo 지음
출판사
John Wiley & Sons (Asia) Pte. | 2013-06-25 출간
카테고리
과학/기술
책소개
Learn to combine security theory an...
가격비교

Security 전반에 걸쳐, 인증, 암호화, 인가등 다양한 시나리오에 대해서 패턴 중심으로 설명, 개념 잡기 아주 좋음



OAuth 2.0에 대해서 이해가 잘되게 설명된 책. 이거 보고 개념 잡았음



Beyond Software Archiecture

저자
Hohmann 지음
출판사
Addison Wesley | 2003-01-01 출간
카테고리
과학/기술
책소개
Successfully managing the relations...
가격비교

읽어야지 하면서 아직 못본책, 아키텍쳐 설계와 특히 라이센스 관리에 대한 디자인이 들어 있는 책




저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

대용량 분산 시스템 아키텍쳐 디자인


대용량 분산 시스템에 대한 아키텍쳐 설계에 대한 내용을 공유합니다. 아직 많이 부족합니다. 많은 피드백 부탁드립니다.


1. 아키텍쳐 설계 프로세스


2. 대용량 분산 시스템 아키텍쳐


3. 대용량 분산 시스템 아키텍쳐 디자인 패턴


4. 레퍼런스 아키텍쳐 - SOA 


5. 레퍼런스 아키텍쳐 - REST


저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

조대협입니다.

오늘 JCO 컨퍼런스에서 발표한 자료입니다

>
시간이 짧아서 하고 싶은 이야기를 다 쏟아 놓지 못했습니다. 자세한 설명들은 

 

http://bcho.tistory.com/category/조대협의%20소프트웨어%20개발

(링크 다시 걸었습니다)

에 자세한 문서로 올려놓았습니다

참고하시구요. 피드백 많이 부탁드립니다.




저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

AWS (Amazon Web Service) 사용시 주의 사항


1. IP가 매번 바뀐다.

aws의 ec2 instance는 restart시 마다 ip가 매번 바뀐다. ip를 바꾸지 않으려면 EIP (Elastic IP)를 사용해야 하는데, 비용이 크다. 그래서 이런 경우에는 aws에 자체 dns 서버를 세팅하고, instance 가 start up 될때 마다, 고유 서버의 dns 이름을 새로 binding된 ip와 맵핑해서 dns서버에 등록하도록 스크립트를 짜 놓으면 유용하다.


2. io bandwidth를 믿지 마라

aws의 가장 큰 어려운 점이, 네트워크 대역폭이다. 아무래도 공유 서비스이다 보니 네트워크 대역폭이 매우 느리다. 즉 내부 서버간 예를 들어 application server - dbms 또는 application server간에 네트워크 대역폭이 느리고 또는 일정하지 않기 때문에 대 부분의 병목이 여기서 발생한다.

이를 해결하기 위한 방법은 큰 ec2 instance를 사용하면 높은 대역폭을 사용할 수 있으며,

Provisioned IOPS를 지원하는 ec2 instance의 경우에는 일정 수준의 IOPS를 보장해준다. (물론 돈을 내야 한다.)

또는 고 성능의 IOPS를 보장하는 인스턴스를 사용하는 것도 방법이 된다.

다른 방법으로는 Placement group이라는 옵션을 사용할 수 있다. 이는 clustering이 필요한 솔루션 (Nosql이나 cache 솔루션)을 사용할때 이 placement group을 이용하면, 해당 서버들을 가능하면 물리적으로 가까운 곳에 위치 시켜서, network 지연을 최소화 한다.

참고 http://bcho.tistory.com/630


3. 미리 resource를 확보해라.

EIP는 5개, EC instance는 20개가 처음 계정을 만들었을때 디폴트 값이다. 테스트 환경을 사용하거나 몬가 하다보면 eip나 ec2 instance가 모자르게 되는데, 미리 미리 확장에 대비해서 확보해놓는 것도 중요하다. 신규 신청시 시간이 걸리기 때문에 미리 신청해놔야 하며, 상품에 따라서 미리 확보해놓으면 과금이 될 수 있다. 아래는 디폴트로 확보되는 자원의 수이다.

EIP – 5
EC2 instance – 20
EBS Volumes – 5,000 volumes or an aggregate size of 20 TiB (max volume size is 1TB)
PIOPS - 10,000 Provisioned IOPS or an aggregate size of 20 TiB (whichever is smaller) S3 Buckets – 100 
Route53 - 100 Hosted Zones and 10,000 Resource Record Sets per Hosted Zone 
ELB - 10 concurrent load balancers 
RDS – 20 RDS MySQL instances (each instance has hard limit max 1024GB) and up to 5 Read Replica instances can be created from a Master. 
VPC – 5 VPCs, 20 subnets each, 50 Security Groups each, 50 rules per Security Group and 5 Security Groups per instance. 10 Network ACLS per VPC, 20 rules per ACL. 10 Route Tables per VPC and 20 entries per route table


4. 가급적이면 VPC를 사용하자.

VPC는 Virtual Private Cloud의 약자로 10.x.x.x 와 같은 내부 ip 대역을 사용할 수 있게 해준다. 이는 논리적으로 다른 서비스(다른 사용자의)와 분리하게 해줄뿐더러, ip를 고정으로 사용할 수 있게 해주시 때문에 위의 1번 문제를 회피할 수 있도록 해준다.


5. 과금에 관련해서.

안쓸때는 꺼놔라. 다 과금 된다.

1시간5분을 사용하더라도 2시간으로 과금된다. 서버의 startup과 down은 시간 단위로 하자.


6. RDS

최대 용량이 1TB이다. 장점은 AZ(Zone)간의 HA를 기본적으로 지원한다.

replica는 db당 최대 5개 까지만 지원한다.


7. multicast

AWS는 multicast를 지원하지 않는다. 상당수의 클러스터링 솔루션이 muticast를 사용하는 경우가 많다.(Oracle RAC) 이경우에는 AWS에서 클러스터를 사용할 수 없다.


8. ELB는 고정 IP가 아니다.

ELB는 HA와 확장성을 지원하기 위해서 DNS Round Robine 방식으로 연결된다. 즉 고정 IP를 사용할 수 없다. 시스템에 대한 접근 IP(방화벽등을 위해서)가 필요할 경우 ELB 앞단에 HA Proxy등 별도의 Proxy를 둬야 한다.


9. AWS에는 IDS가 없다.

기본적으로 탑재된 침입 탐지등의 ids/ips 솔루션이 없기 때문에, 보안이 중요한 경우 이를 사전 고려 해서 ec2 위에서 기동 될 수 있는 ids/ips 솔루션을 탑재하는 것이 좋다.


10. 장기적인 이용에는 on-demand instance를 이용하지 마라.

on-demand instance는 그때 그때 사용하기는 좋지만 과금 모델이 가장 비싸다. 어느정도 기간을 가지고 이용할 예정이면 reserved instance나 spot instance를 이용하는 것이 저렴하다.






저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

아키텍쳐 설계 프로세스

아키텍쳐 | 2012.09.04 17:55 | Posted by 조대협

아키텍쳐

아키텍쳐란 무엇일까? 소프트웨어 시스템에 대해서 이야기 하다보면, “아키텍쳐가 어떻다”. “최신 아키텍쳐를 적용했다.” 등 아키텍쳐에 대한 언급이 많다. 그렇다면, 소프트웨어 아키텍쳐에 대한 정의는 무엇일까?

http://www.sei.cmu.edu/architecture/start/glossary/community.cfm 를 보면, 수많은 아키텍쳐에 대한 정의가 있다. 지금부터 설명하고자 하는 아키텍쳐에 대한 정의는 다음과 같다.

아키텍쳐는 비지니스 요구 사항을 만족하는 시스템을 구축하기 위해서 전체 시스템에 대한 구조를 정의한 문서로, 시스템을 구성하는 컴포넌트와, 그 컴포넌트간의 관계, 그리고, 컴포넌트가 다루는 정보(데이타)를 정의한다.”

또한 소프트웨어 아키텍쳐는 현재의 요구사항뿐 아니라 변화되는 비지니스 전략에 대응이 가능하도록 장기적인 로드맵을 수용하여 확장가능한 형태로 디자인 되어야 하며 가능하면, 구현 및 사용하고자 하는 조직의 기술 수준, 조직의 규모와 형태 그리고 비지니스의 형태에 맞춰서 설계 되어야 한다.

아키텍쳐 설계 프로세스



앞에서 아키텍쳐에 대한 정의는 끝냈다. 그렇다면 실제 아키텍쳐는 어떤 형태로 설계해야 할까?

비지니스 아키텍쳐 이해

아키텍쳐는 앞서 정의하였듯이, 비지니스를 성공적으로 이끌기 위해서, 만들어지는 시스템에 대한 설계다. 목적이 비지니스의 성공에 있기 때문에, 그 비지니스 자체가 어떤 목표,전략을 가지고 있는지를 이해해야, 목표에 부합하는 아키텍쳐를 설계할 수 있다.

아키텍쳐 설계 원칙 정의 (Architecture Principals)

비지니스 아키텍쳐가 정의되었으면, 시스템을 설계 하기 위한 테크니컬 아키텍쳐를 설계하기 위한 원칙을 정한다. 품질 속성이나, 기간, 조직 운용론, 기반 기술등 설계의 기본 사상이 되는 원칙을 정의한다.

시스템 아키텍쳐의 (System Architecture) 설계

설계 원칙이 정해졌으면, 비지니스의 요구 사항을 이 설계 원칙에 따라서 설계한다. 시스템 아키텍쳐는 크게 아래와 같이 3가지로 나뉘어 정의된다.

     애플리케이션 아키텍쳐 (Application Architecture) : 개발해야하는 애플리케이션 소프트웨어에 대한 아키텍쳐를 설계한다. 여기에는 컴포넌트의 정의, 컴포넌트 간의 관계, 특정 기능에 대한 컴포넌트간의 호출 흐름, 그리고 컴포넌트간의 통신을 위한 메세지에 대한 규격 정의를 포함한다.

     테크니컬 아키텍쳐 (Technical Architecture) : 애플리케이션의 배포 구조를 정의한다. 애플리케이션을 배포할 하드웨어의 구조와, 애플리케이션 개발에 사용하는 미들웨어 (DBMS, 웹서버등)등의 배포 구조를 함께 정의한다.

     데이타 아키텍쳐 (Data Architecture) : 마지막으로, 애플리케이션에서 다루는 정보(데이타)의 구조와 관계를 정의한다.

이 아키텍쳐의 설계는 기반 지식이 없는 상태에서는 설계가 어렵다. 물론 경험을 가지고 할 수 있겠지만, 참고할 수 있는 레퍼런스가 있다면 실수나 실패를 줄이고, 시간 또한 단축 시킬 수 있다. 참고자료는 CBD,SOA,EAI와 같은 일반적인 애플리케이션을 개발하기 위해서 패턴화된 아키텍쳐 스타일을 응용하거나, 유사한 도메인의 CASE STUDY (선행 사례) 기반의 아키텍쳐, 그리고 솔루션을 사용할 경우, 솔루션 제공사의 컨설팅 서비스를 이용하면, 매우 효율적으로 아키텍쳐 설계를 할 수 있다.


※ 많은 분들이 이 페이지를 방문하시고, 질문이 많으셔서, 상세한 아키텍쳐 설계 프로세스, 아키텍쳐의 정의, 아키텍트의 역할, 그리고, 대용량 시스템 아키텍쳐에 대한 글을 별도 문서로 정리하였습니다.   http://bcho.tistory.com/695


저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

대용량 시스템 레퍼런스 디자인


SSAG - Face book Server Side Architecture Group

http://www.facebook.com/groups/serverside

조대협 (bwcho75 골뱅이 지메일닷컴)


I. 배경

웹로직,JBOSS 가 유행이던, J2EE 시대만 하더라도, 웹서버+WAS+RDBMS면 대부분의 업무 시스템을 구현할 수 있었다. 오픈소스가 유행하면서 부터는 프레임웍 수는 다소 많기는 했지만 Spring,IBatis or Hibernate,Struts 정도면 대부분 구현이 가능했다.

그러나 근래 수년 동안 벤더 중심에서 오픈소스 중심에서 기술의 중심이 구글,페이스북이 주도하는 B2C 기반의 서비스의 유행과 더불어 대규모 분산 시스템을 위한 대용량 아키텍쳐가 유행하게 되었는데, 이 아키텍쳐의 특징이 오픈소스 중심에 상당히 다양한 수의 솔루션이 사용 되었다.


II. 내용

이 글에서는 일반적인 대용량 시스템을 구축하기 위한 레퍼런스 아키텍쳐를 소개한다.

일반적인 웹이나 서버 플랫폼을 개발할 수 있는 레퍼런스 아키텍쳐이며, 자주 사용되는 오픈 소스 솔루션을 조합하였다.


또한 이 아키텍쳐는 데이타 분석등의 용도가(OLAP)이 아니라 온라인 트렌젝션 처리 (OLTP)성 업무를 위해서 디자인된 아키텍쳐이다.


III. 레퍼런스 아키텍쳐



1. Reverse Proxy Layer - Routing & Load Balacing

첫번째 계층은 Reverse Proxy 계층으로, 첫번째에 들어오는 HTTP Request에 대한 관문 역할을 한다.

이 Reverse Proxy에서는 초기 Request에 대한 Logging, 필요하다면, Authentication & Authorization 처리를 수행하고, 뒷쪽에 Request를 보낼때, 뒷단의 Node로 Routing 또는 Load Balancing을 한다.

뒷단에 클러스터가 업무에 따라서 여러 클러스터로 나뉠 수 있기 때문에 이에 대한 라우팅을 수행하거나, 같은 업무에 대해서는 단일 클러스터에 대해서 여러 서버에 대한 로드 밸런싱을 수행한다.


뒤에 살아 있는 서버에 대한 리스트나 클러스터에 대한 정보는 ZooKeeper에 저장하며, Scale In/Out시 또는 장애시에는 이 정보를 ZooKeeper에 업데이트 하여, ZooKeeper에 저장된 클러스터 정보를 기준으로 라우팅을 한다.


사용할만한 솔루션으로는 Apache,NginX,HA Proxy등이 있다.

성능 상으로는 NginX가 가능 높다. 그러나 NginX는 대용량 HTTP Request에 대해서 아직 제대로 지원하지 않는 부분이 있다. 파일 업다운 로드의 경우 성능이 급격하게 떨어지는 부분이 있다. 위에서 설명한 ZooKeeper연동이나 Routing 기능들은 module을 구현하여 plug in해야 한다.


2. [Optional] Enterprise Service Bus (ESB) Layer - Cross Cutting Concern, Mash up,Routing,MEP (Message Exchange Pattern Converting),Integration, SLA management,Protocol Converting

이 계층은 필요에 따라 넣거나 뺄 수 있는 Optional 한 부분이다. Enterprise Service Bus는 시스템으로 들어오는 메세지에 대해서 좀 더 확장된(진보된) 기능을 제공하는 계층으로, SOA (Service Oriented Architecture)에서 따온 계층이다. 키 포인트는 성능이다. BY PASS의 경우 10~50ms 이내에 통과(IN/OUT 포함), 몬가 작업을 할 경우에는 100ms 이하에 통과되어야 한다.

ESB 계층에서 다루어야 하는 일들은 다음과 같다.

  • Cross Cutting Concern 처리 : Cross Cutting Concern는 횡종단 처리라고 하는데, 모든 메세지에 대해서 뒷단의 비지니스 로직이 공통적으로 처리해야 하는 부분을 이야기 한다. 대표적인 예로, Logging, Authentication & Authorization 등이 있다. 
  • Routing 처리 : Reverse Proxy 보다 향상된 Routing 기능을 제공할 수 있다. 보통 Reverse Proxy에서는 HTTP Header나 URI등의 최소한의 정보를 바탕으로 라우팅을 하는데 반해서, ESB 계층에서는 Message 본문의 Header나 Message 자체의 내용을 가지고 라우팅을 할 수 있다. 예를 들어 VIP 회원에 대해서는 Dedicated 된 서버로 라우팅을 하는지 등의 처리가 가능하다.
  • Protocol Converting : ESB 계층에서는 또한 Protocol 변환을 할 수 있다. 예를 들어 뒷단의 비지니스 컴포넌트가 XML/REST를 지원하는데, 전체 표준을 JSON/REST를 사용한다면, ESB 계층에 프로토콜 변환 기능을 넣어서 JSON to XML 변환을 수행할 수 도 있고, 또 다른 예로는 통신사의 경우 종종 HTTP 메세지를 손을 대는 경우가 있다. Header에 통신사 고유의 헤더를 삽입하는 등의 일이 있는데, 이런 경우 범용으로 디자인 된 시스템은 
  • Mash Up : Mash Up은 뒤의 비지니스 로직 여러개를 합쳐서 하나의 비지니스 로직을 만들어 내는 것을 이야기 한다. 쉬운 예로 기존 서비스가 "구매" 라는 Function이 있었는데, "포인트 적립" 이라는 기능이 새롭게 추가 되었을때, 비지니스 로직 자체를 변경하는 것이 아니라 기존 "구매" 라는 기능에 +"포인트 적립" 이라는 기능을 Mash up으로 더해서 기능을 변경하는 것이다. 이렇게 하면 비지니스 로직 변화 없이 새로운 기능을 구현할 수 가 있다.
  • MEP Converting : MEP란 Message Exchange Pattern의 약자로 메세지의 호출 방식을 이야기 한다. 쉽게 말하면 Sync,Async 와 같은 호출 방식을 정의하는데, 비지니스 로직이 Long Running 하는 Sync 형식의 서비스 였을 때, ESB를 이용하여, Sync 호출을 Async 형태로 변경할 수 있다. (ESB에서 응답을 먼저 보내고, ESB에서 비지니스 컴포넌트로 ASync로 보내는 형태)
  • Integration : 타 시스템과의 통합을 이야기 한다. 일종의 EAI (Enterprise Application Integration) 기능인데, 앞에서 언급된 Mash up + Protocol Conversion + MEP Converting을 합쳐놓은 기능과도 비슷하다. 크게 대내 시스템간의 통합과 대외 시스템과의 통합등으로 나뉘어지며, 대내 시스템과의 통합은 Legacy (SAP와 같은 ERP, Siebel과 같은 CRM과 같은 패키지 형태의 Application)과 통합 하는 경우가 많으며 이런경우 전용 아답터를 사용하는 경우가 많다. 대외 시스템 통합의 경우 예를 들어 전자 결재나 PUSH 서비스 등과  통합하는 경우이며 이 경우 필요에 따라 프로토콜 변환이나 Authentication & Authorization 처리를 하는 경우가 많으며 특히 과금이 연동되는 경우에는 향후 Audit을 위해서 로그를 기록하고 향후 비교하는 경우가 많다.
  • SLA management : SLA (Service Level Agreement)로, Service의 품질을 보장 하는 기능이다. 정확하게는 SLA를 보장한다기 보다는 SLA에 문제가 생겼을때 이를 빠르게 감지하여 후처리를 할 수 있다. ESB는 시스템으로 들어오는 모든 메세지에 대한 관문 역할을 하기 때문에 응답 시간이나 TPS에 대한 변화가 생겼을때 이를 검출할 수 있는 단일 지점으로, 장애 상황에 대한 검출이 있었을때 이에 대한 후처리를 하도록 관리자에게 통보할 수도 있고, 또는 ZooKeeper를 통해서 성능이 떨어지는 노드들에 대한 Scale Out등을 지시할 수 있다.

ESB는 설계시에 적용을 해놓으면 후에 시스템의 변화가 있을 경우에 도움이 많이 되는 계층이다. 시스템 초기 운영시에는 오히려 큰 이득을 보지 못한다. 왜냐하면 처음에는 모든 비지니스 컴포넌트가 초기 요구 사항에 맞춰서 구현이 되었고, 위의 기능들은 시스템을 운영하면서 요구사항이나 환경적인 변화에 따라 발생하는 요구 사항이기 때문이다. 

앞에서도 언급했으나, ESB는 메세지가 지나가는 중간에 위치 하기 때문에 전체 시스템의 성능에 영향을 주게 되기 때문에 성능에 각별한 신경을 써서 디자인을 해야 하며, 특히 메세지의 파싱하는 과정과 메세지 자체 설계에 신경을 많이 써야 한다. 예를 들어 일반적인 경우 메세지의 BODY 부분을 파싱할 일이 없는데 모든 요청에 따라서 BODY 부분을 파싱하게 한다면 이에 대한 오버로드가 상당히 크게된다.


사용 가능한 솔루션으로는 Apache Mule이나 Oracle사의 Oracle Service Bus등이 있고, 재미있는 장비중의 하나는 Oracle Service Bus 제품중에 XML 기반의 메세징을 파싱하는 부분을 Hardware로 구현해놓은 제품이 있다. Oracle Service Bus도 내부적으로 JAXP 기반의 XML Parser를 이용하는데, 이 구현 부분을 ASIC으로 구현해 놓은 제품이 있는데 이 제품의 경우 메세지 처리 속도를 많이 높일 수 있다.


3. WAS Layer - Business Logic

이 계층은 비지니스 로직을 핸들링 하는 계층이다.

Web Application Server (WAS)로 구현이 가능하며, 고속 멀티플렉싱 기반의 고속 처리가 필요한 경우나 대규모 Stateful Connection이 필요한 경우에는 Netty와 같은 네트워크 서버를 사용한다.

이 계층 구현시 중요한점은 Shared Nothing 아키텍쳐를 적용하는 것을 권장한다.

Shared Nothing이랑 WAS 인스턴스끼리 클러스터링등을 통해서 묶지 않고 각각의 WAS를 독립적으로 돌아가게 설계하는 것이다. (대표적으로 Session Clustering을 사용하지 않는것)

이렇게 하는 이유는 특정 인스턴스가 장애가 났을 때 클러스터를 타고 전파되는 현상을 방지하고 또한 횡적인 확장 (Horizontal Scalability )를 보장하기 위해서이다.

참고 자료 

- WAS 기반의 아키텍쳐 http://bcho.tistory.com/373

- J2EE 그리드 아키텍쳐 http://bcho.tistory.com/330


4. Async message Handling

WAS 계층이 Sync 형태의 동기 (Request/Response) 메세지를 처리한다면, 비동기 메세징 처리나 Publish/Subscribe와 같은 1:N 기반의 비동기 메세지 처리를 하는 계층이 필요하다.

예전에는 MQ나 JMS를 많이 사용했으나, 근래에는 좀더 향상된 프로토콜인 AMQP를 기반으로 한 RabbitMQ가 많이 사용된다.


RabbitMQ의 경우에도 수억명의 사용자를 커버하기에는 클러스터의 확장성이 문제가 있기 때문에 이런 경우에는 MySQL등의 DBMS의 테이블을 큐 처럼 사용하고, 메세지를 읽어가는 부분을 Quartz등을 이용해서 주기적으로 읽어가서 처리하는 구조로 만들게 되면 확장성을 보장할 수 는 있으나, 복잡한 비동기 메세징 (에러처리, Pub/Sub)을 구현하기에는 난이도가 높기 때문에, RabbitMQ를 복수의 클러스터로 묶는 Sharding이나 분산큐(Distributed Queue) 개념을 고려할 필요가 있다.


5. Temporary Storage Layer - Temporary space

다음 계층은 Temporary Storage Layer - 작업 공간이다.

이 작업 공간은 4번의 WAS들이 서로 데이타를 공유할 수 있는 "휘발성", 작업 공간이다. 

필수 조건은 높은 성능을 보장해야 하며, 모든 WAS Node가 접근할 수 있어야 한다. 저장 매체가 Memory냐, Disk냐에 따라서 다음과 같이 나눠볼 수 있다.


1) Data Grid (Memory)

데이타 그리드는 쉽게 생각하면 자바의 HashTable 같은 Key/Value Store 기반의 메모리 Store이다. 단.. 이 그리드는 클러스터 구성을 통해서 용량 확장이 가능하고, 별도의 서버 클러스터로 구성되어 여러개의 WAS 노드들이 접근할 수 있다. 일종의 WAS간의 공유 메모리라고 생각하면 된다.

솔루션으로는 Oracle Coherence (예산만 넉넉하다면 이걸 쓰는게 맘편하다), Redis, memecahed, Terracota 등이 있다.

참고 자료 

- Redis 소개 - http://bcho.tistory.com/654

- Coherence를 활용한 아키텍쳐 설계 - http://bcho.tistory.com/327


2) Working Space (DISK)

트렌젝션을 처리하다 보면, 종종 임시적인 작업 공간이 필요할때가 있다. 예를 들어 드롭 박스와 같은 파일 서비스를 이야기 해보자, 드롭박스는 이미지 파일을 하나 올리면, 모바일 디바이스의 화면 해상도에 맞게 5개의 썸네일 이미지를 재 생산한다. 이런 작업을 하기 위해서는 이미지 파일을 저장하기 위해서 임시로 저장해놨다가 썸네일을 추출하는 공간이 필요한데 이를 임시 작업 공간이라고 한다.

데이타 그리드와 마찬가지로, 여러 노드들이 해당 공간을 공유할 수 있어야 한다. 그래서 NFS (Network File System)이 많이 사용되며, Gluster와 같은 소프트웨어 기반의 NFS나 NetApp社의 NFS appliance server (하드웨어) 등이 있다.

참고 자료

- Amazon에서 Gluster 성능 비교 자료 - http://bcho.tistory.com/645


6. Persistence Layer

다음은 영구 저장 공간이다. 영구 저장 공간은 우리가 일반적으로 생각하는 데이타가 저장되는 공간이라고 보면된다.  쉽게 예를 들 수 있는 공간으로는 데이타 베이스와 파일 시스템을 들 수 있다. 이러한 영구 저장소는 대용량 B2C 시스템의 유행과 함께 새로운 DBMS들이 등장하였는데, DBMS 측면에서는 Key Value Store 기반의 NoSQL이나, 대용량 파일을 저장할 수 있는 Object Store등을 그 예로 들 수 있다.


1) Relational Data

개체간의 관계가 있는 경우에 대한 데이타를 관계형 데이타라고 하고, 이를 핸들링 하기 위해서는 관계형 데이타 베이스 RDBMS를 사용한다. 우리가 지금까지 일반적으로 사용해왔던 데이타 베이스가 이 RDBMS이다. RDBMS는 대용량 서비스를 위해서는 태생적인 한계를 가지고 있는데, 예를 들어 MySQL의 경우 하나의 데이타베이스에서 저장할 수 있는 레코드의 수가 10억개 정도가 최적이다. 

이런 문제를 해결하기 위해서는 대용량 시스템에서 몇가지 기법을 추가로 사용하는데 "Sharding" 과 "Query Off Loading"이다.


Sharding이란, 데이타의 저장용량의 한계를 극복하기 위한 방안으로

데이타를 저장할때 데이타를 여러 데이타 베이스에 걸쳐서 나눠 저장하는 방법이다. 예를 들어 "서울","대구","대전"등 지역별로 데이타베이스를 나눠서 저장하거나(이를 횡분할 Sharding) 또는 10대,20대,30대 식으로 데이타를 나눠서 저장하는 방식(이를 수직분할 Sharding)을 사용한다. 이러한 Sharding은 데이타베이스 계층에서 직접적으로 지원하기가 어렵기 때문에, 애플리케이션 레벨에서 구현해야 한다.


다음으로 Query Off Loading이라는 기법으로, 이 기법은 성능의 한계를 높이기 위한 기법이다. 

"Master DB → Staging DB → Slave DB 1,Slave DB 2,....N"

    1. Create/Update/Write/Delete는 Master DB에서 수행하고
    2. Master DB의 데이타를 Staging DB로 고속 복사한후
    3. Staging DB에서 N개의 Slave DB로 데이타를 복사한다.
    4. Read는 Slave DB에서 수행한다.

일반적인 DBMS 트렌젝션은 10~20% 정도가 Update성이고, 나머지 80~90%가 Read성이기 때문에, Read Node를 분산함으로써, 단일 DBMS 클러스터의 임계 처리 성능을 높일 수 있다.


이때 Master/Staging/Slave DB로 데이타를 복제하는 방식이 매우 중요한데, 여기서 일반적으로 사용하는 방식을 CDC (Change Data Capture)라고 한다.

RDBMS는 데이타 베이스 장애에 대한 복구등을 위해서 모든 트렌젝션을 파일 기반의 로그로 남기는 데 이를 Change Log라고 한다. CDC는 이 Change Log를 타겟 DB에 고속으로 복사해서 다시 수행(Replay)하는 형태로 데이타를 복제한다.


MySQL의 경우 Clustering에서 이 CDC 기능을 기본적으로 제공하고 있고, Oracle의 경우 Oracle Golden Gate라는 솔루션을 이용한다. (비싸다..) 중가격의 제품으로는 Quest의 ShareFlex들을 많이 사용한다.


2) Key/Value Data

다음으로 근래에 들어서 "NoSQL"이라는 간판을 달고 가장 유행하는 기술중의 하나가 Key/Value Store이다.

데이타 구조는 간단하게 Key에 대한 데이타(Value)를 가지고 있는 형태이다. RDBMS와 같이 개체간의 관계를 가지지 않는다.

오로지 대용량,고속 데이타 억세스,데이타에 대한 일관성 에만 초점을 맞춘다. (이중에서 보통 2개에만 집중한다. 이를 CAP 이론 - Consistency, Availability, Performance)


이 기술은 태생 자체가 B2C 서비스를 통해서 탄생하였다.

블로그나 트위터, 페이스북 처럼 데이타의 구조 자체가 복잡하지 않으나 용량이 많고 고성능이 필요한 데이타들이다. 태생 자체가 이렇기 때문에 복잡한 관계(Relationship)을 갖는 복잡한 업무 시스템에는 잘 맞지 않는 경우가 많으며, 트렌젝션 처리나 JOIN, SORTING 등이 어렵기 때문에 애플리케이션의 구현 복잡도가 올라간다.


참고 자료

- 사람들은 왜 NoSQL에 열광하는가? - http://bcho.tistory.com/658

- Amazon Dynamo 계열의 NoSQL 장단점 - http://bcho.tistory.com/622

- NoSQL Riak - http://bcho.tistory.com/621

- NoSQL 계보 정리 - http://bcho.tistory.com/610

- Cassandra 소개 - http://bcho.tistory.com/440


3) Object Data

Object Data는 File과 같이 대용량 데이타 파일 저장을 할 수 있는 Storage이다.

10M,1G와 같은 대용량 파일을 저장할 수 있는 저장소로, Amazon의 S3, Openstack SWIFT등이 대표적인 예이며, 하드웨어 어플라이언스 장비로는 애플의 iCloud로 유명해진 EMC의 isilion등이 있다.

Object Data 저장에 있어서 중요하게 생각하는 부분은 대용량의 데이타를 저장할 수 있는 용량에 대한 확장성과 데이타 저장에 대한 안정성이다. 

이러한 Object Data는 Quorum이라는 개념을 적용하여, 원본을 포함하여 N개의 복사본을  유지한다. 일반적으로는 N+3 (3개의 복사본)을 저장하여 데이타에 대한 안정성을 보장한다. 


4) Document Data

Document Data는 Key/Value Store에서 조금 더 발전한 데이타 저장 방식으로

Key 자체는 동일하나 Value에 해당하는 부분이 Document가 저장된다. Document 는 JSON이나 XML 문서와 같이 구조화된 데이타를 저장한다.

RDBMS가 다양한 select, where, group, sorting,index 등 여러가지 데이타에 대한 기능을 제공한다면, Key/Value Store는 이런 기능은 거의 제공하지 않는다. Document Data를 저장하는 제품들은 RDBMS와 Key/Value Store의 중간정도에서 데이타에 대한 핸들링 기능을 제공한다. (부족한 Indexing 기능, 부족한 Group 기능, 부족한 Sorting 기능등)


대표적은 솔루션으로는 MongoDB,CouchDB, Riak등이 있다.


요즘 들어서 자주 사용되는 대표적인 Persistence Store에 대해서 간단하게나마 집고 넘어갔지만, 사실 이 보다 더 많은 형태의 Persistence Store들과 기능들이 있다.


7. Configuration management & Coordinator

대용량, 분산 시스템으로 발전하면서 풀어야되는 문제중의 하나가 "분산되어 있는 노드들에 대한 설정(Configuration)정보를 어떻게 서로 동기화하고 관리할것인가? (이를 Configuration Management라고 한다.) " 인다. 거기에 더해서 클라우드 인프라를 사용하면서 "전체 클러스터내의 서버들의 상태를 모니터링 해서, 서버의 수를 느리고 줄여야 하며 서버들간의 통신을 중재해야 한다. (이를 Coordination 이라고 한다.)"  


여기에 필요한 기능이 작은 량의 데이타(Configuration Data)를 여러 서버가 공유해서 사용할 수 있어야 하며, 이 데이타의 변화는 양방향으로 클러스터 노드내에 전해져야 한다.

즉 Configuration 정보를 각 서버들이 읽어올 수 있어야 하며, 이 Configuration 정보가 바뀌었을 경우 다른 서버들에게 데이타가 변했음을 통지해줄 수 있어야 하며, 중앙 집중화된 Configuration 정보 뿐만 아니라, 서버의 상태가 변했음을 다른 서버들에게 빠르게 알려줄 수 있어야 한다.


이런 역할을 하는 대표적인 솔루션으로는 ZooKeeper 많이 사용된다.


8. Infrastructure

마지막으로 이런 소프트웨어 스택을 구동하기 위한 하드웨어 인프라가 필요한데, 예전에는 일반적인 서버를 Co-Location이나 Hosting 형태로 사용하는 것이 일반적이었으나, 요즘은 가상화 기술을 기반으로 한 클라우드 (Infrastructure as a service)를 사용하는 경우가 많다.

클라우드의 특징은 "Pay-as-you-go" 로 자원을 사용한 만큼에 대해서만 비용을 지불하는 구조이다. CPU를 사용한 만큼, 디스크를 사용한 만큼, 네트워크 대역폭을 사용한 만큼만 비용을 지불한다.


Amazone WebService (AWS), Microsoft Azure, Google App Engine등이 대표적인 예인데, 이러한 클라우드의 장점은 Time To Market (시장 진입 시간)이 매우 짧다는 것이다. 앉아서 신용카드와 PC만 있다면 인터넷에 접속해서 30분내에 서버,디스크,네트워크등을 설정해서 사용할 수 있다.

단 이러한 클라우드 인프라는 Public 한 서비스 형태로 공유되서 서비스 되기 때문에 일반적인 호스팅과는 달리 성능등에 대한 한계를 가지고 있다. 예를 들어 서버와 디스크간의 네트워크 대역폭이 보장되지 않기 때문에 디스크 IO가 많은 애플리케이션 (DBMS와 같은)에 대한 성능을 보장하기가 쉽지 않고, LAN 설정이 자유롭지 않기 때문에 UDP등을 이용해서 클러스터링을 하는 제품의 경우 클러스터링을 사용할 수 없는 경우가 있다.  이런 이유로, 클라우드위에서 구현되는 시스템의 경우에는 해당 클라우드의 기술적인 특징을 제대로 이해하고 구현해야 한다.


또한 클라우드가 "Pay-as-you-go" 형태로 사용한만큼 비용을 지불한다는 것이 어떻게 보면 "싸다"라고 느껴질 수 있지만, 네트워크,IP 등등 모든 자원에 대해서 비용을 지불하기 때문에 실제적으로 계산해보면 싸지 않은 경우도 많고 기술적인 제약 때문에, 초기 시장 진입을 하는 경우에는 클라우드를 사용하는 경우아 많지만 규모가 커진 서비스의 경우에는 다시 자체 데이타 센타를 구축하는 경우가 많다. (예 소셜 게임 서비스인-Zinga, VOD 서비스인-Netflix)


운영 측면에서 인프라에 대한 관리를 클라우드 업체에 대행시킴으로써 얻는 이득도 있지만 불필요한 비용이 낭비되지 않게 클라우드 인프라에 대한 배포 구조를 끊임 없이 최적화 하는 노력도 필요하다.


IV. 결론

지금까지 현재 유행하는 대용량 고성능 시스템에 대한 레퍼런스 아키텍쳐에 대해서 설명하였다. 사실 이 글을 정리한 이유는 글을 쓰는 본인도 기술이 변화함을 느끼고 있었고, 이에 대한 공부와 개념 정리가 필요하다고 느껴서인데, 확실하게 기술 구조는 변했다. 유행하는 기술도 변했다. 대용량 시스템은 이런 구조로 구현하는게 하나의 모범 답안 (정답이 아니라는 이야기)은 될 수 있으나, 대부분의 IT 시스템은 이런 대용량 아키텍쳐 구조 없이도 WAS + RDBMS 구조만으로도 충분히 구현이 가능하다.

그럼에도 불구하고 이러한 레퍼런스 아키텍쳐에 대한 글을 쓴 이유는 레퍼런스 아키텍쳐를 이해하고, 이런 아키텍쳐가 왜 필요한지 어디에 쓰이는지를 이해한 후에 제대로 적용하기를 바라는 마음에서 정리 하였다. 이러한 대용량 기술은 유용한 기술임에는 분명하지만, 닭잡는데 소잡는 칼을 쓸 필요는 없지 않은가?


누락된 부분

※ node.js 를 이용한 Long Running Connection Service : 예-Push 등을 추가 할것.

※ Map & Reduce를 이용한 분산 처리

※ 데이타 분석을 위한 Hadoop 또는 OLAP성의 처리 아키텍쳐


P.S. 요즘 제 포스팅들이 읽이 어려운가요? 내용은 어떤지요? 피드백을 못 받아서 궁금합니다. 요즘 글들이 축약적인 내용이나 추상적인 개념들을 많이 이야기 하는 것 같아서요. 


저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
MongoDB Deployment 아키텍쳐를 간단하게 보면 다음과 같다.
mongos들을 앞단에 쭈욱 늘어놓고, 이는 라우터의 역할을 한다. mongos간의 load balancing은 앞단에 L4등의 로드 밸런서를 사용하고, Cache Hit율등을 높이기 위해서 L4는 Hash 방식등의 Sticky setting을 한다.
뒷단에 mongod를 배치하고, 최소한 3 copy replica 구조로 설정한다.



inter data center에 대한 replication을 설정하고, 이는 DR이나 Back up 용도로 사용한다
inter data center replication은 항상 여러가지 숙제를 주는데, 이 경우 backbone의 속도 차이로 인하여 data의 일관성이 깨질 수 있으니,
1. DR/Back up 용도로만 사용
2. data center간 초고속 백본만 설치
3. data center A에서는 read/write, B에서는 read만 (Query Off Loading 아키텍쳐) 수행하고, 이 경우에는 B 데이타 센터의 data 반영이 늦음을 예상해서 애플리케이션을 설계한다.

저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
 

티스토리 툴바