사용자의 요청을 여러 서버로 분배해주는 하드웨어/소프트웨어 장비
요청하는 입자에서는 LoadBalancer 뒤의 목록은 알지 못한다.
Nginx, HAProxy 등의 유명한 소프트웨어 LoadBalancer가 존재
LoadBalancer의 Failover
LB1 장애 시, LB1이 가진 ip주소를 LB2가 가져가는 방식으로 동작
우리는 특정 서비스를 어떻게 찾을 수 있을까?" 하는 질문에 가장 먼저 떠오를만한 대답은 일반적으로 'DNS'.
DNS (Domain Name Service) 란?
- IP를 기억하기 힘들기 때문에 이를 좀 더 기억하기 쉬운 문자 형태로 제공하는 것
- 클라이언트들은 외부DNS를 이용해서 접속해야할 API 서버를 알아내고, 이 API 서버들은 내부DNS를 이용해서 접속해야할 DB를 알아낸다.
DNS로 서버 목록을 제공한다면, 외부에서 DNS 목록을 통해 우리 서버의 주소를 알 수 있다.
그러나 서버가 죽었을 때 DNS TTL에 의하여 클라이언트는 TTL 시간동안 잘못 된 정보를 가지고 있게 된다.
DNS TTL로 인해 발생 가능한 문제를 회피하고자 나타난게 바로 서비스 디스커버리.
* DNS TTL : DNS 서버의 부하를 줄이기 위하여 한번 가져간 데이터는 일정 시간동안 다시 요청하지 않도록 하는 값
서비스의 주소, 포트, 프로토콜 등을 알려주는 방법
서비스에 속한 서버를 DNS 통하지 않고, 어떻게 찾을 것인지에 대한 솔루션
서비스 디스커버리를 구현하기 위해 사용하는 둘로는 Zookeeper
Etcd
Consul
Eureka
등이 있으며,
통상적으로 Coordinator라고 칭한다.
Cluster Membership으로 인해 서비스 간의 등록/해제 등의 과정이 자동화 된다.
* Cluster Membership : 서비스 디스커버리의 서비스 자동 동기화 기능
※ 왜 서비스 디스커버리를 사용해야할까?
LB가 없는 Client Side Balancing에서 서버1이 서버2의 주소를 어떻게 알 수 있을까?
통상적으로 설정 파일을 통해서, DNS를 통해서일 것이다.
그러나 이 두 방법은 각각 문제의 소지가 있다.
- 설정 파일
- 서버 주소목록을 설정 파일에 넣어두고 관리
- 서버 주소가 바뀌면 설정 파일 수정 후 재배포
- 장애가 났을 때 사람이 수동으로 배포하게 된다
- DNS
- DNS를 이용해 동적으로 바꾸자
- DNS 질의를 이용해 서버의 목록을 가져오자
- DNS는 누가 업데이트해주나? TTL 문제는?
- 서버가 추가삭제 될 때 LB를 쓸 수 없다면?
위 에서 언급된 방법들의 문제를 서비스 디스커버리는 모두 해소할 수 있다.
- Server Side Load Balancing에서는 LoadBalancer의 주소와 Port
- Client Side Load Balancing에서는 해당 서버 목록과 Port
헬스체크를 수행해야 하는 방법에 대해 고민해본다면,
- 서버를 체크하기 위한 헬스체크 체이닝(헬스체크1, 헬스체크1을 감시하기 위한 헬스체크2...)
- 서버를 체크하기 위한 패러럴 헬스체크(헬스체크1,2,3이 서버를 체크)
이런 구조는 비효율적일 수 있다.
불필요한 헬스체크로 인한 리소스낭비가 심한 구조이기 때문이다.
1번의 경우에는 저러한 체이닝이 계속해서 늘어나게 될 것이고,
2번의 경우에는 한번의 장애로 인해 N개의 알림이 올 수 있고, 이는 정확한 문제 파악에 방해가 될 수 있다.
이런 상황에 대한 솔루션이 바로 Leader Election !
Leader Election은 Leader로 설정 된 '단 하나'의 헬스체크만 동작하게 하는 방식이다.
쉽게말해 헬스체크1이 실패했을 때, 헬스체크2가 동작하고, 헬스체크2가 실패했을 때, 헬스체크3이 동작하는 방식
Leader 선정은 어떤 Coordinator tool을 사용하는지에 따라 다르다.
Zookeeper
: 목록의 서버군들 중 가장 위 서버가 LeaderEtcd
: 특정 key를 쓰는데 성공한 서버가 Leader가 된다강의 출처
The RED : 백엔드 에센셜 : 대용량 서비스를 위한 아키텍처 with Redis by 강대명 https://github.com/charsyam/the_red_infra/blob/main/install_pyenv.sh