안녕하세요, Brad입니다. 어제 수업시간에 서버가 여러 대일 경우 성능개선 방안에 대해 배웠는데요. 정리해볼게요.
Scalibility
Scalibility는 우리말로 말하면 '확장성'이죠. 확장성은 트래픽 양에 관계없이 유연하게 처리할 수 있는 능력을 말합니다. scale을 하는 방법은 2가지가 있는데요. scale up과 scale out입니다.
scale up
- 기존 하나의 서버를 더 크고 빠른 서버를 교체하는 것을 말합니다. 이 방법은 보통 scale out 방식에 비해 비용이 비싸다는 점이 좋지 않지만 설계의 복잡도는 크지 않다는 점에서 장점이 있습니다.
scale out
- 서버의 개수를 늘려서 규모를 늘리는 것을 말합니다. 비용이 상대적으로 저렴하지만 설계가 복잡하다는 단점이 있습니다.
- scale out은 여러 개의 서버가 이용되기 때문에 하나의 서버가 다운되어도 큰 문제가 없고, 변경사항이 발생했을 때 무중단 서비스를 사용할 수 있다는 점에서 장점이 있습니다.
SPOF(Single Point Of Failure)
SPOF는 시스템에서의 '급소'를 의미하는데요. 이 급소가 정상적으로 작동하지 않을 때 시스템 전체가 뻗어버리는 곳을 말합니다. 만약 요청이 (브라우저 → DNS → nginx → tomcat → MySQL) 로 지나간다면 SPOF는 이 중 어느곳이 될 수 있습니다. 가장 유심히 봐야될 곳은 1대가 커버하는 곳입니다. 왜냐하면 여러 대수의 장비가 있다면 하나가 고장나도 다른 장비를 이용해서 요청을 처리해줄 수 있는 반면, 1대 밖에 없으면 이 1대가 고장나는 즉시 전체 서비스가 제 역할을 할 수 없기 때문입니다. 그래서 이렇게 1대가 있는 구간은 '이중화'를 통해 예측하지 못하는 상황을 대비하는 것이 좋습니다.
SPOF를 배웠으니 DB에서 이런 SPOF를 줄이는 방법을 알아볼게요.
master / slave
DB에서 master / slave 구조란 master가 죽어도 slave를 통해 정상적으로 DB가 가동할 수 있게끔 하는 것을 말합니다. 그렇게 하기 위해선 slave는 master를 바라보는 관계이며 변동이 생기면 slave도 똑같이 반영해야겠죠.
기본적으로 이 구조에서 일단 CRUD 관련해서 Master에서 다 받고 만약 master에 문제가 생기면 slave로 DB요청이 가는 것입니다. 별도의 설정을 통해 CUD관련해서는 master에서 처리하고 쿼리 중 대부분에 해당하는 R은 slave에서 처리하도록 할 수 있습니다.
failover
- 이 개념이 위에서 살펴본 master / slave 구조와 관련이 있는데요. 마스터 노드가 뭔가 잘못되면 슬레이브 노드가 마스터 노드에 있던 내용을 그대로 복사하여 마스터 노드가 되도록 한다는 것입니다.
failback
- 만약 마스터노드가 정상적으로 복구가 된다면 전에 슬레이브 노드였던 노드는 마스터노드에게 그 자리를 넘겨줘야겠죠. 이를 failback 이라고 합니다.
Sharding
sharding이란 데이터를 여러 개의 동일한 스키마를 가진 테이블에 나누어 저장하는 것을 말합니다. 한 마디로 똑같은 바구니 나누어 담는 것이죠. 그럼 이런 의문이 있습니다.
- 어떻게 나눌 것인가?
- 어떻게 나눈 데이터를 찾을 것인가?
나누는 방법에는 2가지가 있는데요. '의미 단위', 또는 '모듈러 연산' 을 이용하는 방법입니다. '의미 단위'는 또 하나로 몰릴 수 있기 때문에 두번째 모듈러 연산을 주로 사용한다고 하네요. 데이터가 많아지면 이렇게 나누어서 보관할 수 밖에 없을 것입니다. 특히 포터사의 '블로그'나 '카페'가 이렇게 관리되고 있을 것입니다. 그 개수가 엄청나기 때문이죠.
단점을 뭐가 있을까요?
- 우선 전체 탐색이 힘듭니다. 나눠있으니까요.
- 하지만 뭐니뭐니해도 이렇게 나누었는데 하나의 DB에 트래픽과 데이터가 몰리면 감당하기 힘들지도 모릅니다. 네이버 카페 중에는 '중고나라'가 아무래도 다른 카페에 비해 데이터나 트래픽이 압도적으로 높겠죠. 그럴때는 sharding을 '중고나라'를 위한 DB가 필요할지도 모릅니다.
Load Balancing
서버가 여러 대가 있다면 어떻게 트래픽을 나누어 각각의 서버로 보낼 수 있을까요? DNS에서 한다고요? 음.. DNS는 하나의 서버에만 매핑될 수 있는걸요?! 답은 일단 어느 서버에 트래픽이 간 후 그곳에서 각각의 서버로 분산시킵니다. 이렇게 분배처리 하는 것을 Load Banlancing이라고 합니다.
위 그림에서 VIP(Virtual IP)가 그 역할을 하고 있는 것입니다. 이러한 로드밸런싱 해주는 것을 '로드밸런서'라고 하는데요. 그 종류에는 대표적으로 L4, L7, HAProxy가 있습니다.
L4
- OSI레이어 3~4에 해당하는 IP주소, TCP/UDP 포트 정보를 보고 어느 서버로 연결시킬지 스위칭합니다.
L7
- OSI레이어 3~7까지 커버해서 IP주소, 포트 정보 뿐만 아니라 해당 패킷의 실제 내용까지 파악하여 적절한 서버로 연결시킵니다.
- L4에 비해 커버하는 범위가 넓고 더 많은 기능이 있기 때문에 L7이 훨씬 비싸다고 하네요.
HAProxy
L4, L7은 하드웨어 스위치인 반면 HAProxy는 소프트웨어의 스위치입니다.
기본적으로 reverse proxy형태로 동작하는데요. 두 가지 형태에 대해 알아보도록 하겠습니다.
reverse proxy
- 클라이언트가 요청을 보내면 프록시가 실제 서버로부터 데이터를 가져옵니다.
- 실제 어디에서 처리되는 것인지 알 수 없기 때문에 보안 측면에서 좋습니다.
forward proxy
- 클라이언트가 실제 서버 주소를 프록시에게 보내면 프록시가 요청받은 그대로 데이터를 가져옵니다.
- 캐싱 기능이 있고 빠르고, 특정 사이트만 접속 가능하도록 하는 회사에서 사용될 수 있습니다.
Session
로드밸런서를 사용할 때 주의해야할 점이 '세션관리'입니다. 세션은 서버에서 관리하는 '상태값'이죠. 보통 WAS에서 관리하는데요. 만약 여러 대의 서버가 있다면 해당 세션은 어디서 관리하는 것이 좋을까요? 3가지 방법이 있습니다.
sticky session
- 한번 응답을 받았으면 응답 받은 서버로만 요청이 가도록 하는 것입니다.
- 이 방법이 코드를 바꾸지 않고 조금이 설정을 통해 사용할 수 있으므로 가장 많이 사용된다고 합니다. L7 스위치에서 제공하는 기능이라고 하네요.
session clustering
- 여러 대의 서버에 세션을 복사하는 방법입니다.
- 만약 100대가 있다면 서로간 계속 싱크를 맞춰줘야할텐데요. 엄청 비효율적일 것 같네요.
별도의 session 서버를 두는 방법
- 대형기업에서 주로 사용하는 방법이라고 합니다.
- 절대 주의가 필요합니다. 왜냐하면 이 세션 서버는 하나이기 때문입니다. 결국 서버가 여러대라 세션을 하나로 관리하는 것인데 또 다시 여러 대의 세션서버를 둘 순 없겠죠. 이곳은 SPOF입니다. 절대 다운되서는 안되게 해야합니다.
- 이 세션 서버는 key : value 에 특화된 NoSQL을 주로 사용한다고 합니다. 그 종류로는 Redis등이 있죠.
Cache
여기서 말하는 캐시는 WAS에서의 캐시를 말하는데요. 서버가 여러대가 되면 세션과 마찬가지로 캐시도 분산되어 있겠죠. 이러한 상황을 해결하기 위한 두가지 방법이 있습니다.
전역 캐시(Global Cache)
캐시 서버를 독립적으로 두는 것을 말합니다. 이전에 Session을 별도의 두는 것과 비슷한데요. 캐시도 그와 비슷한 성격의 key:value 구조의 DB를 사용합니다.
캐시는 성격상 메모리 DB를 사용하는데요. 그렇기 때문에 다른 성격의 서버와 달리 Memory 크게 설계된다고 합니다.
그럼 DB를 사용한 것과 뭐가 다를까요?
위와 같은 의문이 들지도 모릅니다. 다른 점이 있다면 캐시DB가 속도가 훨씬 빠르다는 점입니다. 그 이유는 Memory DB를 사용한다는 점, 그리고 쿼리를 날릴 필요없이 바로 key : value에 따른 결과값을 찾을 수 있기 때문입니다.
분산 캐시(Distributed Cache)
- 각각의 노드에 캐시를 분산해서 가지고 있는데 요청이 들어왔을 때 각각의 노드를 탐색해가면서 요청된 값이 있는지 탐색해본 후 없으면 원본을 요청하는 것을 말합니다.
- 아무래도 100개의 서버가 있고 제일 마지막 서버에 해당 캐시값이 있었다면 차라리 처음부터 원본을 가져오는게 빠를 수도 있겠다는 생각이 드네요.
무턱대고 캐시를 사용하는 것은 오히려 부작용을 불러일으킬 수 있습니다. 불필요한 탐색이 추가되기 때문이죠. 그렇기 때문에 캐시는 보통 '자주 바뀌지 않는', 또 '자주 사용되는' 데이터에 한해 Hit(요청자원이 캐시에 있을 확률)가 70%이상인 데이터에 한해서 사용하는 것이 좋다고 합니다. 이와 관련한 오픈소스 솔류션으로 Memcached와 Redis등이 있습니다.
모든 곳엔 trade off가 있습니다. 절대적으로 좋은 것은 없습니다. 캐시도 마찬가지 입니다. trade off를 고려하여 캐시 성격에 맞는 데이터에 한해서 사용되어야 합니다.
'TIL' 카테고리의 다른 글
Today's Dev Notes(2019-02-07) (0) | 2019.02.07 |
---|---|
Today's Dev Notes(2019-01-23) (0) | 2019.01.23 |
Today's Dev Notes(2019-01-20) (0) | 2019.01.20 |
Today's Dev Notes(2019-01-17) (0) | 2019.01.17 |
Today's Dev Notes(2019-01-16) (0) | 2019.01.16 |