트래픽 분산처리 기술

0

원본 : https://d2.naver.com/helloworld/6070967

D2 네이버 기술블로그에 정리된 내용 중 일부를 별도로 뽑아 정리하고자 합니다.


GCDN (Global CDN)

CSS와 JavaScript, 이미지와 같이 공통으로 호출되는 리소스는 한 번 업로드되면 잘 변하지 않습니다.
이런 리소스를 웹 서버에서 직접 제공하면 트래픽 부하가 가중됩니다.
예를 들어 100KB 용량의 이미지를 10만명이 조회하면 대략 10GB의 트래픽이 발생합니다.
그래서 공통적으로 호출되는 리소스의 부하 분산을 위해 GCDN을 사용합니다.
리소스를 GCDN으로 분산하면 트래픽을 상당히 절감할 수 있습니다.
또한, GCDN에서 지원하는 GSLB(Global Server LB) 기능은 접속한 IP 주소에서 가장 가까운 CDN 서버를 자동으로 선정해 연결하기 때문에 사용자가 빠른 서비스 속도를 체감할 수 있습니다.


SSI (Server Side Includes)

SSI는 웹 서버(Apache, NGINX 등)에서 지원하는 서버사이드 스크립트 언어입니다.
서버에 있는 특정 파일을 읽어오거나 특정 쿠키 유무의 판별 등 간단한 기능을 실행하 수 있다.
이런 기능을 WAS에서만 실행할 수 있다고 생각하고 WAS에 요청을 보내는 경우가 많습니다.
하지만 SSI를 사용해 웹 서버에서 기능을 처리하면 WAS의 부담을 줄여 WAS의 성능에 여유를 줄 수 있게 되고, 웹 서버의 활용도도 높여 서버의 자원을 더 효율적으로 사용할 수 있습니다.

(SSI 적용 예, https://d2.naver.com/helloworld/6070967)

Apache 커스텀 모듈

APR(Apache Portable Runtime)
APR은 프레임워크와 비슷하게 운영체제에 독립적으로 HTTP 기반 통신을 처리할 수 있도록 하는 라이브러리입니다.
메모리 할당, 메모리 폴링, 파일 입출력, 멀티스레드 관련 처리 등에 필요한 기능이 포함되어 있습니다. Apache HTTP 서버도 APR 기반으로 작성되어 있습니다.

커스텀 모듈을 사용하면 SSI를 사용할 때와 마찬가지로 WAS에서 처리할 기능을 웹 서버에서 처리할 수 있어 WAS의 부담을 줄일 수 있습니다.
또한 SSI에서는 불가능한 고급 기능을 사용할 수 있어서 활용도가 높습니다. C언어 기반이라 실행 성능도 좋습니다.

대표적인 커스텀 기능은 아래와 같습니다.

  • 간단한 외부 시스템 연동 : 단순히 API를 호출하거나 결과값을 그대로 사용할 수 있을 때에는 WAS를 거치지 않고 커스텀 모듈을 통해 외부 시스템을 호출합니다.
  • WAS 연동 시 AJP(Apache JServ Protocol), 리버스 프록시(reverse proxy) 대신 커스텀 모듈 사용 : 모든 WAS가 다운되더라도 웹 서버만 정상이라면 서비스를 제공할 수 있게 커스텀 모듈을 사용해 WAS와 통신합니다.
    • AJP나 HTTP를 사용해 WAS와 통신하면 WAS와 통신이 실패했을 때 오류로 처리됩니다.
    • 커스텀 모듈을 사용하면 WAS와 통신이 실패했을 때 동일한 IDC에 있는 다른 WAS와 통신을 시도합니다.
    • 다른 WAS와 통신도 실패하면 오류로 처리하는 대신 특정한 경로에 있는 파일을 읽어서 반환합니다. 반환할 파일은 정적 파일을 배포하는 Data Publisher가 특정 시간 주기에 따라 웹 서버에 생성해 놓은 파일입니다.

서킷 브레이커

서킷 브레이커는 외부 서비스의 장애로 인한 연쇄적 장애 전파를 막기 위해 자동으로 외부 서비스와 연결을 차단 및 복구하는 역할을 합니다.
서킷 브레이커를 사용하는 목적은 애플리케이션의 안정성과 장애 저항력을 높이는 데 있습니다. 분산 환경에서는 네트워크 일시 단절 또는 트래픽 폭증으로 인한 간헐적 시간 초과 등의 상황이 종종 발생합니다. 이로 인해 연쇄 장애가 발생할 가능성이 있습니다.

  1. 트래픽 폭증으로 인해 API 서버 등 외부 서비스의 응답이 느려진다.
  2. 외부 서비스의 응답이 타임아웃 시간을 초과하면 데이터를 받아오기 위해 외부 서비스를 다시 호출한다.
  3. 이전에 들어온 트래픽을 다 처리하지 못한 상태에서 재시도 트래픽이 추가로 적체되어 외부 서비스에 장애가 발생한다.
  4. 외부 서비스의 장애로 인하여 데이터를 수신하지 못해 네이버 메인 서비스에도 장애가 발생한다.

일시적인 경우라면 2, 3회 재시도로 정상 데이터를 수신할 수 있습니다.
하지만 장애 상황이라면 계속 재시도하는 것이 의미도 없을 뿐 아니라 외부 서비스의 장애 복구에 악영향을 미칠 수 있습니다.
이럴 때는 외부 서비스에서 데이터를 받아오는 것을 포기하고 미리 준비된 응답을 사용자에게 전달하는 것이 시스템 안정성 및 사용 편의성 측면에서 옳다고 할 수 있습니다.

(서킷 브레이커에서 서킷의 상태 변화, 출처 : https://docs.microsoft.com/en-us/azure/architecture/patterns/circuit-breaker)

서킷은 아래와 같은 세 가지 상태를 가집니다. (회로이므로 닫힌 것이 정상, 열린 것이 비정상)

  • Closed 상태 : 메소드가 정상적으로 작동해 서킷이 닫힌 상태
  • Open 상태 : 메소드에 문제가 생겨서 서킷이 열린 상태
  • Half-Open 상태 : Open 상태와 Closed 상태의 중간 상태, 메소드를 주기적으로 확인해 정상이라고 판단되면 Closed 상태로 상태를 전환하고, 정상이 아니라면 Open 상태를 유지

서킷이 Closed 상태에서 잘 작동하고 있다가 오류가 발생하기 시작해서 일정 횟수에 도달하면 일단 서킷을 Open 상태로 전환합니다.
이때에는 메소드를 호출해도 실제로 메소드가 실행되는 대신 서킷 브레이커가 개입해 미리 지정된 응답(단순 실패를 반환할 수도 있고 특정한 값을 반환할 수 도 있음)을 반환합니다.

특정 주기 동안 Open 상태로 유지하고 있다가 서킷이 자체적으로 메소드가 정상으로 작동하는지 확인하는데, 이 상태가 Half-Open 상태입니다.
Half-Open 상태에서 멧도르르 몇 번 호출해서 정상 응답이 돌아온다면 서킷은 다시 Closed 상태로 전환되어 요청을 처리합니다. 몇 번 호출했는데 게속 실패가 반환된다면 서킷은 Open 상태로 유지합니다.

네이버 메인페이지에서 사용하는 서킷 브레이커 활용 예시

  • 정적 파일을 배포하는 Data Publisher를 통해 사전에 정상 응답 결과값을 주기적으로 저장
  • 외부 시스템에 이상이 있다고 판단되면(open 상태) 서킷 브레이커가 개입해 바로 연결 시도를 포기하고 미리 준비해 둔 정상 응답 결과값을 사용해 HTML 화면을 렌더링
  • 이후 계속 상태를 지켜보다(Half-Open 상태) 외부 시스템이 정상으로 돌아오면 서킷 브레이커가 다시 연결을 시도

서비스 디스커버리

서비스 디스커버리는 동적으로 생성, 삭제되는 서버 인스턴스에 대한 IP 주소와 포트를 자동으로 찾아 설정할 수 있게 하는 기능입니다.
다음은 서비스 디스커버리를 사용하지 않는 서버군의 환경을 나타낸 그림입니다.
서버군 1과 서버군 2가 서로 다른 기능을 실행하는 서버군이라고 가정합니다.

(서비스 디스커버리를 사용하지 않는 환경, 출처 : https://d2.naver.com/helloworld/6070967)

서버군 2에서 10.0.0.5 서버가 신규로 생성됐지만, 서버군 1에서는 10.0.0.5 서버로 연결을 맺을 수 없다. 서버군 1이 최초에 실행 됐을 때에는 10.0.0.5 서버가 없었기 때문에 서버 목록에 10.0.0.5 서버가 없기 때문입니다. 서버 목록을 갱신하려면 서버군 1에 있ㄴ는 서버를 다시 실행해야 합니다.
하지만 롤링 리스타트를 한다고 해도 서비스를 운영하는 도중에 서버를 다시 실행하는 것은 매우 위험합니다.

아래는 서비스 디스커버리를 도입한 환경을 나타내는 그림입니다.

(서비스 디스커버리를 사용하는 환경, 출처 : https://d2.naver.com/helloworld/6070967)

서비스 디스커버리 서버는 각 서버군의 서버 목록을 관리합니다. 서버는 시작할 때 자신의 정보(IP 주소, 포트)를 서비스 디스커버리 서버로 보내고, 서비스 디스커버리 서버는 이 정보를 받아 서버군의 서버 목록을 최신으로 갱신합니다.
각 서버군에 있는 서버는 주기적으로 서비스 디스커버리 서버로 목록을 요청해 서버 목록을 최신으로 유지합니다.
이러한 방법으로 서버는 재시작 등 외부의 개입이 없어도 자동으로 항상 최신 서버 목록을 확보할 수 있습니다.

예를 들어 10.0.0.5 서버가 추가되면 서버군 2의 서버 목록이 갱신되고 이 목록을 받아서 서버군 1의 서버가 자신의 서버 목록을 갱신하면 외부의 개입 없이 10.0.0.5 서버에 연결할 수 있게 됩니다.

서비스 디스커버리는 특히 클라우드 환경에서 빛을 발합니다.
기존 온프레미스 환경에서는 서버를 추가, 삭제하는 일이 많지 않았습니다.
서버를 추가, 삭제하는 경우에도 통제된 환경에서 주로 작업하므로 갱ㅅ니 문제가 크지 않습니다.
하지만 클라우드 환경에서는 수시로 서버가 추가, 삭제됩니다. (특히 오토 스케일링 등의 기능을 사용한다면 더욱 더)
이를 사람이 일일이 확인해 서버를 다시 실행하는 것은 불가능 합니다.

profile
컴퓨터공학과 + 실무 = 4 + N = 모르는거 ∞ ...

0개의 댓글