본문 바로가기

개발

HaProxy 의 역할과 graceful stop 과정

HAProxy는 여러 서버에 대해 요청을 확산시키는 TCP 및 HTTP 기반 애플리케이션들을 위해
고가용성 로드밸런서와 리버스 프록시를 제공하는 자유-오픈 소스 소프트웨어

 

HAProxy의 역할

- a TCP proxy : it can accept a TCP connection from a listening socket

- an HTTP reverse-proxy (called a "gateway" in HTTP terminology)

- a content-based switch
요청의 모든 요소를 고려하여 요청이나 연결을 전달할 서버를 결정할 수 있습니다.
따라서 동일한 포트를 통해 여러 프로토콜(예: HTTP, HTTPS, SSH)을 처리할 수 있습니다.

- a server load balancer
TCP 연결과 HTTP 요청을 로드 밸런싱 할 수 있습니다.
TCP 모드에서는 전체 연결에 대해 로드 밸런싱 결정이 내려집니다.
HTTP 모드에서는 요청별로 결정이 내려집니다.

 

Forward Proxy

  • A: 이것은 사용자의 가정용 컴퓨터입니다
  • B: 이것은 정방향 프록시 서버입니다
  • C: 이것은 웹 사이트의 원본 서버(웹 사이트 데이터가 저장되는 곳)입니다

Forword proxy 쓰는 이유

  1. user device를 Origin server에 숨기고 싶을때
  2. user device에 특정 콘텐츠에 대한 엑세스를 차단하고 싶을때

 

Reverse Proxy

  • D: 사용자의 가정용 컴퓨터 수
  • E: 이것은 역방향 프록시 서버입니다
  • F: 하나 이상의 원본 서버

Reverse proxy 쓰는 이유

  1. 로드 밸런스 : Origin server의 부하분산
  2. 보안성 : Origin 서버에 원본 Ip를 공개 할 필요가 없음.
  3. 캐싱 : 콘텐츠를 캐시하여 클라이언트와 서버 간의 트래픽 흐름을 가속화

 

Forword proxy와 Reverse proxy는 user 기준으로

인터넷이 앞에 있으면 forword, 인터넷이 뒤에 있으면 Reverse 라고 한다. 

 

서버 개발자 입장에서는 서버를 관리하는 입장이니깐

user 입장에서 생각 할 필요없이, server 기준으로 생각해야 한다.

 

forword proxy 는 서버 개발자가 특별히 할게 없고

Reverse proxy 에서 서버와 관련된 역할이 많아서 해당 부분 꼭 알아두자.

출처 : https://www.cloudflare.com/ko-kr/learning/cdn/glossary/reverse-proxy/

 

 

HAProxy 는 Proxy L4 or L7?

- a TCP proxy : it can accept a TCP connection from a listening socket

- an HTTP reverse-proxy (called a "gateway" in HTTP terminology)

L4 & L7 둘다 설정할수 있다.

 

L4 영역

  • TCP 에서는 Transport 영역이므로 IP/PORT 로 구분 지어서 프록시를 할수 있다.
  • mode tcp 설정

L7 영역

  • source and destination IP addresses and ports
  • SSL handshake metadata
  • HTTP metadata including headers, cookies, URL and method
  • mode http 설정

L7 영역은 L4 는 물론 HTTP 스펙까지 확인 할수 있다.

어떤 layer에 적용되었는지 바로는 알수 없고 mode 설정을 확인 해봐야 한다.

 

HAProxy 가 빠른 이유

  • single-threaded
  • event-driven
  • non-blocking engine combining a very fast I/O layer
  • priority-based scheduler.

event-driven 과 non-blocking으로 이렇게 빠른 레이어를 구성할수 있다니…

빠른건 알고 있었는데 webflux를 하면서 흐름도가 동기방식이랑 달라 이게 과연 괜찮은걸까 했는데

아래 성능을 보면 확실하게 좋은것 같다.

 

HAProxy 성능

SSL을 통해 200만 건의 요청/초와 100Gbps의 전송 트래픽에 도달할 수 있음.

 

HAProxy 구성 정보 변경시 무중단 재시작

HAProxy 는 graceful and a hard stop 을 제공

graceful stop 과정

  • 아래에서 프로세스는 HAProxy 프로세스다
  • haproxy reload 시 어떤일이 일어나는지에 대한 과정이다.
  1. 서비스 스크립트는 먼저 구성 파일 검사 (haproxy -c)를 수행
  2. 구성 파일 검사는 다음과 같은 목적을 가지고 있다.
    기본 설정 검사 
    • 구문 오류: 설정 파일의 문법 오류 및 괄호 짝 맞춤 오류를 검사합니다.
    • 지시문 오류: 존재하지 않는 지시문 또는 잘못된 지시문 형식을 검사합니다.
    • 필수 항목 누락: 리스닝 포트, 백엔드 서버 정보 등 필수 설정 항목 누락 여부를 검사합니다.
    구성 문제 검사
    • 포트 충돌: 동일한 포트를 사용하는 다른 프런트엔드 또는 백엔드 서버가 있는지 검사합니다.
    • 백엔드 서버 연결: 백엔드 서버의 IP 주소 및 포트 연결 가능 여부를 검사합니다.
    • 권한 설정: HAProxy 프로세스가 설정 파일 및 소켓에 대한 권한을 가지고 있는지 검사합니다.
    부가 기능 검사
    • 인증 설정: 사용자 정의 인증 설정의 오류 여부를 검사합니다.
    • 헬스 체크 설정: 헬스 체크 설정의 오류 여부를 검사합니다.
    • 네트워크 설정: 네트워크 인터페이스 및 바인딩 설정의 오류 여부를 검사합니다.
  3. 구성 파일 검사 후 파라미터에 따라 Stop 스톱방식이 결정된다.
    • 하드 스톱: -st, 그레이스풀 스톱: -sf
    • haproxy reload -sf
    • SIGUSR1 신호를 받으면 리스닝 포트 연결만 해제하고 기존 연결은 처리를 완료할 때까지 유지
    • 새로운 구성 파일을 적용하는 "reload" 명령에 사용
  4. 새로운 프로세스는 모든 리스닝 포트 bind를 시도한다
    • 실패 시 (예: 권한 부족) 프로세스는 종료됩니다.
    • 포트가 이미 사용 중인 경우, 새로운 프로세스는 기존 프로세스에게 SIGTTOU 신호를 보내 중지하도록 요청합니다.
    • 이것을 "pause" signal 이라고 함
  5. 기존 old 는 연결을 계속 처리
  6. if - bind가 실패
    • new 프로세스는 old 프로세스 에게 SIGTTIN 신호를 보낸다.
    • 신호를 받은 old 는 다시 리스닝을 시작한다.
    • 새 프로세스가 포트 연결에 성공하면 종료
  7. if - 새로운 프로세스가 모든 포트 연결에 성공
    • 아래 명령어를 old 에게 전송한다
    • SIGTERM (hard stop in case of "-st")
    • SIGUSR1 (graceful stop in case of "-sf")
    • 이 명령어를 받으면 Old는 하던 작업 마무리 하고 떠나야 한다 ㅠ
  8. 이렇게 reload 하면 10,000개에 커넥션중 하나정도 에러가 발생할수 있다.

그 에러가 발생하는 경우는 아래 두가지일 경우인데 해석하기가 너무 힘들어서 원문을 첨부한다

  - if the new process fails to bind due to the presence of the old process,
    it will first have to go through the SIGTTOU+SIGTTIN sequence, which
    typically lasts about one millisecond for a few tens of frontends, and
    during which some ports will not be bound to the old process and not yet
    bound to the new one. HAProxy works around this on systems that support the
    SO_REUSEPORT socket options, as it allows the new process to bind without
    first asking the old one to unbind. Most BSD systems have been supporting
    this almost forever. Linux has been supporting this in version 2.0 and
    dropped it around 2.2, but some patches were floating around by then. It
    was reintroduced in kernel 3.9, so if you are observing a connection
    failure rate above the one mentioned above, please ensure that your kernel
    is 3.9 or newer, or that relevant patches were backported to your kernel
    (less likely).

  - when the old processes close the listening ports, the kernel may not always
    redistribute any pending connection that was remaining in the socket's
    backlog. Under high loads, a SYN packet may happen just before the socket
    is closed, and will lead to an RST packet being sent to the client. In some
    critical environments where even one drop is not acceptable, these ones are
    sometimes dealt with using firewall rules to block SYN packets during the
    reload, forcing the client to retransmit. This is totally system-dependent,
    as some systems might be able to visit other listening queues and avoid
    this RST. A second case concerns the ACK from the client on a local socket
    that was in SYN_RECV state just before the close. This ACK will lead to an
    RST packet while the haproxy process is still not aware of it. This one is
    harder to get rid of, though the firewall filtering rules mentioned above
    will work well if applied one second or so before restarting the process.

HAProxy 상태 Monitoring

haProxy 설정에서 stats 을 열어두면 해당 부분을 확인 할 수 있다.

session 의 상태를 보면 응답값에 대한 %를 알수도 있고

각종 통계 수치도 볼수 있다.

아래 보면 신기하게 redis 에 로드밸런스 목적으로 haproxy를 사용했다.

https://co-de.tistory.com/22

아래 사이트를 보면 HaProxy에 대한 basic 컬럼들을 볼 수 있는데

하나하나 시간 들여서 읽으면 좋은것들이 많다… 몰라서 그렇지..

https://www.haproxy.com/blog/category/basics

사용중인 HA-Proxy version 1.7.11

반응형