232 deview2013...
description
Transcript of 232 deview2013...
DAY2%/%Track%3%/
11:00~11:45
��������
���� ������
김요한���������� ����������
����
CONTENTS
����� � �������
����������������������������
����������������������
���#$%"�����!- Consistent Hashing- 분산 코드네이터
5. 더 고민해야 할 부분- 공유 데이터 관리- 모듈 기반 어플리케이션- 대용량 Connection 관리
1. Scalability
1 Scalability
When you add twice as many servers, are you twice as fast(or have twice the capacity)?
- LiveJournalhttps://www.usenix.org/legacy/events/usenix07/tech/slides/fitzpatrick.pdf
Replacing all components of a car while driving it at100mph.
- Instagramhttps://www.unboundid.com/blog/2012/06/27/scaling-at-100mph
������������������ ����������������������������������������������������������������������������������������������������������������
1 Scalability
1 Scalability
<script type="text/javascript" src="http://www.stalk.io/stalk.js" charset="utf-8" ></script><script language="javascript"> STALK.init();</script>
http://stalk.io
2. Async Event Looping Server
Single'Thread'로'Event'Looping'처리'하는'비동기'서버
/'WebSocket'추상화
2 Async Event Looping Server
cf.'DB'연결'Transaction'관리'/'좀'더'오래'걸리는'작업'/'일반적인'업무'시스템
core'당'하나의'thread'/'저사양'/'고성능
2 Async Event Looping Server
http://www.techempower.com/benchmarks/
2 Async Event Looping Server
서버만$많다면$될까?
3. Reverse Proxy Server
3 Reverse Proxy Server
L4#/#L7#Switch
?
Reverse&Proxy
3 Reverse Proxy Server
Reverse&Proxy
L4&Switch
3 Reverse Proxy Server
3 Reverse Proxy Server
HAProxy + Varnish
HaProxy Varnish
Fully Dynamic Contents
3 Reverse Proxy Server
참고로, Job Queueing
Job$Worker
Job$Worker
Job$Worker
Job$Worker
Job$Queue$Server
Gearman, RabbitMQ + Celery (instagram, pinterest)
비동기 처리
병렬 프로세싱
public!class!ReverseProxyServer!extends!Verticle!{
!!public!void!start()!!{
!!!!HttpClient!clients[]!=
!!{vertx.createHttpClient().setHost("10.21.32.01").setPort(8282),:::vertx.createHttpClient().setHost("10.21.32.02").setPort(8282),:::vertx.createHttpClient().setHost("10.21.32.03").setPort(8282),:.:.:.};
!!!!vertx.createHttpServer().requestHandler(new!Handler()!{!!!!!!public!void!handle(final!HttpServerRequest!req)!{!!!!!!!!final!HttpClientRequest!cReq!=!clients.get().request(req,!!!!!!!!!new!Handler<HttpClientResponse>()!{!!!!!!!!!!public!void!handle(HttpClientResponse!cRes)!{!!!!!!!!!!!!cRes.dataHandler(new!Handler<Buffer>()!{!!!!!!!!!!!!!!req.response.write(data);!!!!!!!!!!!!});!!!!!!!!!!!!cRes.endHandler(new!SimpleHandler()!{!!!!!!!!!!!!!req.response.end();!!!!!!!!!!!!});!!!!!!!!!!}!!!!!!!!});!!!!!!}!!!!}).listen(8080);!!} vert.x 로 Reverse Proxy 서버 구현하기.
Reverse&Proxy&서버는&“&부하&분산&”&은&어떻게?
“&무중단&서버&추가&”&는&어떻게?신규서버&추가&/&장애&서버&처리&.&.&.&.&Auto&Scale&Out&?
3 Reverse Proxy Server
4. 분산서버 노드 관리- Consistent Hashing- 분산 코드네이터
4.1 Consistent Hashing
부하 분산 방법 ?
��������������.760'�
� ����������������4�" �3#�+!�
Consistent(Hashing��9�2��0)��1�-*/-�8(;$���������������� ��������������� �������%2:�+,�54�8(�&
4.1 Consistent Hashing
A
B
C
D
value&=&HASH(���)
Service&Server
Token&Ring
4.1 Consistent Hashing
A
B
C
D 장애#발생#!!
value#=#HASH(���)
A#-#C#구간이#넓어서#C#에#부하가#많을#수#있다#!
4.1 Consistent Hashing
A
B
C
D
value&=&HASH(���)B C D
ABCD
D
ABCD
ABCABCDABCA
ABCD A
B C D
value&=&HASH(����)
4.1 Consistent Hashing
A
B
C
D
B C DABCD
D
ABCD
ABCABCDABCA
ABCD A
B C D
value&=&HASH(����)
value&=&HASH(���)
4.1 Consistent Hashing
public!class!ConsistentHash<T>{
!!!!!!!!private!final!HashFunction!hashFunction!=!Hashing.md5();!!!!!!!!private!final!SortedMap<Long,!T>!circle!=!newTreeMap<Long,!T>();
}
!!!!!!!!public!void!add(String!name,!T!node)!{
!!!!!!!!!!!!!!!!!!!!!!!circle.put(hashFunction.hashString(name).asLong(),node);
!!!!!!!!}!!!!!!!!public!void!remove(String!name)!{
!!!!!!!!!!!!!!!!!!!!!!!circle.remove(hashFunction.hashString(name).asLong());
!!!!!!!!}!!!!!!!!public!T!get(String!value)!{!!!!!!!!!!!!!!!!long!hash!=!hashFunction.hashString(value).asLong();!!!!!!!!!!!!!!!!if!(!circle.containsKey(hash))!{!!!!!!!!!!!!!!!!!!!!!!!!SortedMap<Long,!T>!tailMap!=!circle.tailMap(hash);!!!!!!!!!!!!!!!!!!!!!!!!hash!=tailMap.isEmpty()?circle.firstKey():tailMap.firstKey();!!!!!!!!!!!!!!!!}!!!!!!!!!!!!!!!!return!circle.get(hash);!!!!!!!!}
ConsistentHash.add(‘nodeA’,...);
ConsistentHash.add(‘nodeB’,...);
ConsistentHash.add(‘nodeC’,...);
ConsistentHash.add(‘nodeD’,...);
4.1 Consistent Hashing
public!class!ConsistentHash<T>{
!!!!!!!!private!final!HashFunction!hashFunction!=!Hashing.md5();!!!!!!!!private!final!SortedMap<Long,!T>!circle!=!new!TreeMap<Long,!T>();!!!!!!!!private!final!int!numberOfReplicas!=!100;
!!!!!!!!public!void!add(String!name,!T!node)!{!!!!!!!!!!!!!!!!for!(int!i!=!0;!i!<!numberOfReplicas;!i++)!{!!!!!!!!!!!!!!!!!!!!!!!!circle.put(hashFunction.hashString(name!+i).asLong(),node);!!!!!!!!!!!!!!!!}!!!!!!!!}!!!!!!!!public!void!remove(String!name)!{!!!!!!!!!!!!!!!!for!(int!i!=!0;!i!<!numberOfReplicas;!i++)!{!!!!!!!!!!!!!!!!!!!!!!!!circle.remove(hashFunction.hashString(name!+i).asLong());!!!!!!!!!!!!!!!!}!!!!!!!!}!!!!!!!!public!T!get(String!value)!{!!!!!!!!!!!!!!!!long!hash!=!hashFunction.hashString(value).asLong();!!!!!!!!!!!!!!!!if!(!circle.containsKey(hash))!{!!!!!!!!!!!!!!!!!!!!!!!!SortedMap<Long,!T>!tailMap!=!circle.tailMap(hash);!!!!!!!!!!!!!!!!!!!!!!!!hash!=tailMap.isEmpty()?circle.firstKey():tailMap.firstKey();!!!!!!!!!!!!!!!!}!!!!!!!!!!!!!!!!return!circle.get(hash);
public!class!ConsistentHash<T>{
!!!!!!!!private!final!HashFunction!hashFunction!=!Hashing.md5();!!!!!!!!private!final!SortedMap<Long,!T>!circle!=!new!TreeMap<Long,!T>();!!!!!!!!private!final!int!numberOfReplicas!=!100;
!!!!!!!!public!void!add(String!name,!T!node)!{!!!!!!!!!!!!!!!!for!(int!i!=!0;!i!<!numberOfReplicas;!i++)!{!!!!!!!!!!!!!!!!!!!!!!!!circle.put(hashFunction.hashString(name!+i).asLong(),node);!!!!!!!!!!!!!!!!}!!!!!!!!}!!!!!!!!public!void!remove(String!name)!{!!!!!!!!!!!!!!!!for!(int!i!=!0;!i!<!numberOfReplicas;!i++)!{!!!!!!!!!!!!!!!!!!!!!!!!circle.remove(hashFunction.hashString(name!+i).asLong());!!!!!!!!!!!!!!!!}!!!!!!!!}!!!!!!!!public!T!get(String!value)!{!!!!!!!!!!!!!!!!long!hash!=!hashFunction.hashString(value).asLong();!!!!!!!!!!!!!!!!if!(!circle.containsKey(hash))!{!!!!!!!!!!!!!!!!!!!!!!!!SortedMap<Long,!T>!tailMap!=!circle.tailMap(hash);!!!!!!!!!!!!!!!!!!!!!!!!hash!=tailMap.isEmpty()?circle.firstKey():tailMap.firstKey();!!!!!!!!!!!!!!!!}!!!!!!!!!!!!!!!!return!circle.get(hash);
private!final!int!numberOfReplicas!=100;
모두#똑같이#해야#하나?서버의#CPU#Core#수#나#네트워크#구간#등#고려
4.1 Consistent Hashing
4.1 Consistent Hashing
replics �� �� ����(standard deviation)
https://weblogs.java.net/blog/tomwhite/archive/2007/11/consistent_hash.html
서버#노드#10#개를#1#부터#500#개#까지#relicas#로#배치#10,000#번의#consistent#Hashing#결과
4.2 분산 코디네이터
zkClient.get().create("/serviceServers/nodeA",%%%//%서버정보를%가지고%있는%zNode%Path555555555555555555555555555555555"1.1.1.1:8080".getBytes(),5//%zNode%의%데이터,%서버%상세정보%(Null%이어도됨)55555555555555555555555555555555CreateMode.EPHEMERAL);%%%%%//%zNode%타입%(EPHEMERAL%:%임시노드%/PERSISTENT%:%영구생성)
zkClient.get().create("/serviceServers/nodeB",%.%.%.%..zkClient.get().create("/serviceServers/nodeC",%.%.%.%..zkClient.get().create("/serviceServers/nodeD",%.%.%.%..
EPHEMERAL(타입은(Zookeeper(서버에(접속이(끊어지면,(자동으로(삭제(!!
서비스(서버(장애로(Shutdown(되면(Zookeeper(목록에서(자동으로(삭제(가능
Apache ZooKeeper™
/serviceServers/nodeA55555555555555/nodeB55555555555555/nodeC55555555555555/nodeD
4.2 분산 코디네이터
Apache ZooKeeper™
<"service"servers">
reverse"proxy"server
서비스"서버가"startup"될때"zookeeper"Server"에"연
결해서"EPHEMERAL"노드"생성
장애"발생""
zookeeper"와"연결이"자동으로"끊어짐!!
서버"목록을"watching"하면서"
Proxy"서버의"서비스"서버"목록을"동기화"!! watching
create"node
서비스"서버"목록을"Ring"에"추가
Consistent"Hashing
12
3
/serviceServers/nodeA--------------/nodeB--------------/nodeC--------------/nodeD-----------------:-----------------:
노드"삭제
4.2 분산 코디네이터
장애#발생시#자동#삭제#될#수#있도록!CreateMode.EPHEMERAL!로#Znode#생성?
하지만,#또#다른#문제들.
-#네트워크#문제로#znode#가#삭제
-#Disk#Full,#Memory,#CPU#.#.#.#.#?
CreateMode.PERSISTENT!로#Znode#생성#후#데몬으로#서버들의#상태#관리.
Auto#Scaling#이#가능하도록#해야#할#것.
5. 더 고민해야 할 부분- 공유데이터관리- 모듈 기반 어플리케이션- 대용량 Connection 관리
5.1 공유 데이터 관리
WAS$의$Cluster$는$장애$/$성능$저하의$주된$원인$!
Tomcat$의$session$replication$:$DeltaManager$or$BackupManager
해결책$중$하나$-$NAVER$의$TripleS$(Shared$Session$System)
? http://helloworld.naver.com/helloworld/233847
5.1 공유 데이터 관리
<"servers">
Reverse"Proxyserver
shard 1
ZooKeeper™ Redis Cluster Manager
shard 2
shard 3
watching
create/deleteredis"node
Consistent"Hashing
redis"서버"목록을"Ring"에주가하고"동기화"한다.
heartbeat
redis"상태"체크!!
를"활용한"공유"데이터"(session)"공유하기
get"/"set"session"datas
.".".
.".".
.".".
5.1 공유 데이터 관리
공유하지%않는%것%(shared%nothing)%이%가장%좋은%방법
!!
<%servers%>
Reverse%Proxyserver
HASH%(“체팅방%A”)
Consistent%Hashing
체팅방명(키)이%hash%key
HASH%(“체팅방%B”)
이%서비스%서버에%“체팅방%A”%에%입장한
모든%접속자%목록은%Local%메모리에%저
장하고%있다.
5.2 모듈 기반 어플리케이션
var!http!!!!!=!require('http');
var!sender!!!=!require('./lib/messageSenderMod');
var!receiver!=!require('./lib/messageReceiverMod');
var!auth!!!!!=!require('./lib/userAuthMod');
var!buddy!!!!=!require('./lib/buddyMgrMod');
.&.&.&.&.&.&.&.&.&.&.
vertx.deployModule("webCserverCv1.2",!config,!1);
vertx.deployModule("modCmessageSenderCv0.1",!config,!1);
vertx.deployModule("modCmessageReceiverCv0.1",!config,!1);
vertx.deployModule("modCuserAuthCv0.1",!config,!1);
vertx.deployModule("modCbuddyMgsCv0.1",!config,!1);
.&.&.&.&.&.&.&.&.&.&.
서버의$기능들을$분리해$구현한$모듈들