[LoadBalancer로 트래픽 분산하기] - LoadBalancing 방법

Hyunjun Kim·2025년 5월 15일
0

Data_Engineering

목록 보기
69/153

2. LoadBalancing 방법

부하를 분산해주려면 미리 어떻게 분산할 것인지 규칙이 필요하다. 웹서비스 트래픽에서 사용할 수 있는 대표적인 로드밸런싱 방법을 알아보자.

이게 전부는 아니고 웹서비스 트래픽에서 사용할 수 있는 대표적인 방법이다.

2.1 Round-Robin

라운드로빈은 말 그대로 순서대로 하나씩 돌아가면서 나눠주는 것이다. 사전 지식이 없더라도 누구나 가장 먼저 생각해볼만한 개념이다. 가장 기초적이기 때문에 라운드로빈 방식은 로드밸런싱뿐만 아니라 컴퓨터 공학 전반에서 많이 사용하는 개념이니 용어는 꼭 알아두는 것이 좋다.

2.2 IP Hashing

2.2.1 같은 IP의 요청을 같은 서버로 연결하고 싶은 use-case

만약 서버에서 고객정보에 대해 캐시가 되어 있어서 같은 유저가 여러 가지 요청을 했을 때 Cache hit를 통해 빠르게 응답할 수 있도록 서버 애플리케이션을 구현했다면, LB는 어떻게 요청을 연결해야 할까?

이 경우, 같은 유저에게 온 요청은 최대한 같은 서버로 연결해줄수록 Cache Hit를 높일 수 있다. Cache Hit가 높아지면 빠른 응답을 통해 고객 경험도 좋아지고, 응답 시간이 빨라질수록 서버는 같은 자원으로 더 많은 요청을 처리할 수 있는 부가가치 또한 생긴다.

같은 유저에게 들어온 요청인지 어떻게 알 수 있을까? Payload를 파싱해보면 알 수 있지만, 이를 LB에서 처리하는 것은 비용이 많이 드는 작업이다. LB는 요청을 분산하는 역할이기 때문에 가장 빠르게 분산할 수 있는 방법을 찾고 역할을 줄여야 안정적으로 사용할 수 있다.

  • Application Layer (OSI 7에서 5~7 영역)까지 열어봐야 하기 때문이다.

Source IP가 같으면 같은 유저에게서 온 것이라고 추정하면 비교적 적은 비용(OSI 3,4 layer만 보고 판단)으로 알 수 있다.

2.2.2 Hashing

Hashing은 어떤 입력 값을 바탕으로 랜덤한 결과(문자, 숫자, 바이트 등)를 출력하지만, 같은 입력에 대해서는 항상 같은 값이 나오도록 보장하는 방법을 말한다.

2.2.3 IP Range 기반 분산의 단점

Hashing을 왜 사용할까?

먼저 IP만을 가지고 다음과 같이 분산한다고 생각해보자:

  • 1.1.x.x → 서버 1
  • 1.2.x.x → 서버 2

이렇게 분산을 하면 어떤 부작용이 있을까?

하필이면 10.1.x.x를 가진 요청이 오후 12시에 몰린다면? 10.1.x.x를 받기로 한 서버 A가 부하가 커서 장애가 생길 수 있다.

예측하고 대응할 수 있을까?

  • 10.1.x.x는 많이 들어오는 prefix이니까 세분화해서 나누고,
  • 10.2.x.x는 적게 들어오니 안 나누면 된다고 해보자.

그런데 하필 10.1.x.x 중에서도 90%가 10.1.1.x에 몰려 있다면 또 문제가 된다.

이러한 트래픽의 패턴은 시시각각 바뀌기 때문에, 인프라 단에서 LoadBalancer 설정을 수시로 바꾸는 것도 현실적으로 어렵다. 게다가 LB는 설정 변경을 즉각 반영하지 못하는 경우도 많다.

2.2.4 IP Hashing을 사용하는 이유

그래서 사용하는 것이 IP 값을 그대로 사용해서 범위를 나누어 분산하는 것이 아니라, Hashing을 통해 나온 랜덤한 결과를 기준으로 범위를 나누어 분산하는 것이다.

이 경우 Hashing 함수가 IP의 특정 패턴에 종속되지 않게 고르게 Random한 결과를 주는 것이 보장된다면, 단순 IP 범위 분산보다 훨씬 고르게 분산할 수 있다.

LB에 연결된 대상이 많아지더라도 같은 규칙(mod 연산 등)으로 동일한 비율로 분배해줄 수 있다.

단, 이 경우에도 실제 트래픽은 예측할 수 없고 사용자 요청에 특정한 패턴이 존재하기 때문에 Hashing을 했더라도 어느 정도의 편차나 편향이 있을 수 있다.

2.3 Hashing

2.2 IP Hashing과 같은 방식이지만, Hash의 기준이 되는 값이 IP 외의 다른 대상이며 이를 설정할 수 있다. Hashing의 대상이 Payload에 있다면 L4까지만 보고 분산할 수 있는 LB(Network Load Balancer)로는 불가능하고, L7까지 보는 LB(Application Load Balancer)에서만 가능하다.

L7까지 봐야 한다면, L4 기반 LB보다는 지연이 조금 더 발생할 수 있다 (몇 마이크로초 또는 나노초 수준). 단, Payload가 크다면 사용하지 않는 것이 좋다.

2.4 Least Connections

Client의 요청을 받은 시점에 가장 연결이 적은 서버로 보내준다.

요청을 처리하기 위해 Connection을 오래 유지하는 서버 애플리케이션인 경우(CPU 사용 작업이 많은 경우 등)에 이 방법이 적합하다.

2.5 Least Time

가장 빨리 응답을 줄 것으로 기대되는 서버로 연결한다. 그동안의 response time의 평균 또는 추정치와 현재 연결된 connection 수 등을 조합해서 계산한다. 공식은 구현체마다 다르다.

2.6 Random

Random 하게 대상에게 연결한다. Least Connections 또는 Least Time 알고리즘과 함께 사용되기도 한다.


예제 설명

자기 로컬에 메모리 캐시가 있다.
로컬 1 캐시에 유저 1번 정보, 로컬 2 캐시에 유저 2번 정보, 로컬 3 캐시에 유저 3번 정보가 있다고 해보자.

유저 1이 접속하면 맨 처음에 로컬 1로 유저의 정보가 갔다고 가정하자.
그러면 로컬 1에서 요청을 처리하고 캐시를 해놨다.

우리가 앱을 사용할 때 버튼 한 번만 누르는 것이 아니라 이 탭도 가고 저 탭도 간다.
즉, 클라이언트와 서버 사이에 API 요청이 빈번하게 발생한다.

매번 중앙 DB에서 데이터를 가져오면 비효율적이다.
항상 사용되는 변함없는 정보(닉네임, 이름 등)는 캐시하는 것이 좋다.

이왕 캐시를 했다면 로컬마다 각각 하는 것보다, 같은 유저의 요청이 같은 서버로 가서 캐시 Hit율을 높이는 것이 좋다.

어떻게 같은 유저의 요청인지 추론할까?

  • 우리가 쓰는 프로토콜(TCP, HTTP)을 보면 레이어가 낮은 TCP에 source IP와 포트 정보가 있다.
  • destination IP, 포트 정보도 있다.
  • 한 번 접속하면 동일한 IP 주소로 일정 시간 안에는 계속 접속한다.

따라서 같은 IP 주소로 들어오면 같은 유저라고 판단할 수 있다.

두 번째 문제:
IP를 기준으로 다음과 같이 나눴다고 해보자.

  • IP 1~10 → 서버 1
  • IP 11~20 → 서버 2
  • IP 21~30 → 서버 3

그런데 IP 1번으로 트래픽이 10,000개, 11~20은 0개, 21~30은 1,000개면?
서버 1만 트래픽을 과도하게 받아 장애가 생길 수 있다.

해결 방법?
Round-Robin 아이디어를 따와서 전체적으로 Random하게 지정해주면 된다.

이때 사용하는 것이 해싱이다.
해시는 무엇인가?

  • 같은 Input에 대해 항상 같은 Output을 주지만,
  • Output은 고르게, 랜덤하게 분포되는 것이 특징이다.

그래서 해시 결과에 Range를 정하고, 그에 따라 트래픽을 분산한다.

물론 해시가 완벽하진 않지만, 특정 IP 패턴에 의존하지 않고 고르게 분산하려는 목적에는 유효하다.

profile
Data Analytics Engineer 가 되

0개의 댓글