caffeine-library/release-everything

[additional] Active StandBy 전환 간 Dangling Connection 수명주기 확인하기

Closed this issue · 4 comments

연관 챕터

#2

조사 내용

Active StandBy 전환 간 Dangling Connection 이슈 재현하기 위한 TF

  • Amazon RDS Active - StandBy 구성
  • SpringBoot + JPA 이용하여 Dangling Connection 수명주기 관찰해 보기
    • Breakpoint를 걸던
    • 관련 텔레메트리를 정의하던

@caffeine-library/readers-release-everything

해당 TF에서 필요한 작업 내역입니다.

어플리케이션

스프링 어플리케이션

  1. JDBC 연결 100개 가량 물고 대기
  2. DB 전환 수행
  3. COMMIT 명령 날려보기
  4. 오류 관측: 간단하게 로그 파일 까는 걸로 생각중

😞 아니 그냥 단순히 MySQL Client로 검증해 보는 걸로 해 보겠습니다.

인프라

RDS MySQL Multi-AZ 구성

  1. 퍼블릭 서브넷에 놓아 저희 로컬에서 접근합니다.

  2. Master 리부트 하여 Failover 프로세스를 시동합니다.

  3. 페일오버 DB 전환은 통상 60-120초 뒤 완료된다고 알려져 있습니다.

  4. 전환 완료된 후 기존 연결로 요청을 시도, 오류를 확인합시다.

참고하기

댕글댕글 커넥션에 대한 우려를 AWS 공식문서 역시 얘기해 주고 있군요 👍🏻

DB와 클라 간 세션이 원활히 종결되지 않았을 수 있기에,
수동 페일오버(리부팅) 전에 트랜잭션을 멈추기 바란다.

클라우드 비용 신경쓰지 마시고 구체적인 구현 방안 의견이나
공수 나누실 분 있다면(?) 적극 협력해주시면 더욱 좋습니다.

PoC결과 공유

  • 일시: 24/01/24 11:48 ~ 11:52
  • 클라이언트: MySQL Workbench
  • 데이터베이스: Amazon RDS for MySQL Multi-AZ

사전 세팅

image

dangle.USER 테이블에 열 하나 (Jaebin Joo)만 준비

DR 전환 테스트

USE dangle;
SET AUTOCOMMIT=0;
INSERT INTO USER(name) VALUES ('Jaebin Joo 2');

-- DR 전환 완료후
COMMIT;

SELECT * FROM USER;
  1. (Jaebin Joo 2) 열을 새로 추가하되 커밋은 넣지 않았습니다.
  2. AWS 콘솔에서 RDS DR을 수행하고 헬스가 뜰 때까지 약 2분 대기했습니다.
  3. 이제 커밋을 시도했습니다. 워크벤치 상에서 로딩 아이콘이 생긴 후 어떠한 응답 반응이 없었습니다!
    image
  4. 한 번 더 커밋을 시도했으며, 조회 쿼리도 한 차례 넣었습니다. 여전히 응답 반응이 없었습니다.
  5. 그러나 잠시 후 뒤 요청이 처리되었다는 로그가 뜨고, 응답이 들어왔습니다.
    image
  6. 조회로 긁은 결과에는 (Jaebin Joo 2)가 없네요.
    결국 빨간 박스 내 3개 쿼리는 DR DB와 맺어진 뒤늦은 연결로 수행된 것입니다!
    image

이상으로 짧은 PoC 결과 보고드렸습니다.

Dive deep 1

DR 전환 후 보낸 쿼리는 수십초가 지나 결국엔 들어갔습니다..?
✔️ 워크벤치에 연결 재시도 로직이 있다고 유추하게 되었습니다. 이 로직을 증명할 수 있을까요?
✔️ 여러분들은 첫 시도에서 Abort 하는 걸 바라시나요? 아니면 재시도 하기를 바라시나요?

image

  • 정확히 30초(read connection timeout)가 지나서 쿼리를 성공했다면요. 연결 타임아웃 이벤트가 발생했다는 확증이 섭니다.
  • 또, 정상 응답 로그가 찍혔으니 DR DB와 연결되었다고도 확증 가능합니다.

MySQL은 쿼리 중 서버가 날라간 현상을 별도 문서로 남겨두어 이런 가이드를 남겼습니다.

You can also get these errors if you send a query to the server that is incorrect or too large. If mysqld receives a packet that is too large or out of order, it assumes that something has gone wrong with the client and closes the connection.
서버에게 부정확하거나, 너무 큰 쿼리를 보내면 해당 오류를 만날 수 있다. mysql가 크거나 처리할 수 없는 쿼리를 받으면, 클라이언트에 이상이 생긴 걸로 알고 연결을 닫는다.

그러니까 DR DB는 기존 연결이 보낸 COMMIT 명령을 이상하게 여겨 쳐냈을 겁니다.

그러므로 워크벤치가 연결 재수립 로직을 구현하고 있는지 알아보기 위해서

✔️ read_conn_timeout에 의한 연결 재시도 확인
✔️ conn timeout에 의한 연결 재시도 확인

첫 번째 사항은 아까전 PoC에서 이미 증명됐구요.

다음 PoC에서는 아래 내용을 진행합니다.

  1. conn keep-alive 20초 / conn timeout 0초 / read conn timeout 30초로 구성하기
  2. 30초(read conn timeout) 보다 빨리 쿼리 성공 로그가 발생하는지 봅니다.
    keep-alive 도중 연결 실패를 확인한 워크벤치가 연결을 재수립 했다는 증거입니다.

Dive deep 2

RDS 페일오버 시 IP가 변경 될까요?

image

  • RDS 연결은 DNS 네임으로 참조합니다.
  • DNS 주소 해결 시 반환되는 IP 주소가 바뀌는 거면, 사실 저희는 책이 소개한 가상 고정 IP DR과는 다른 상황에서 PoC를 진행한 것입니다.

✔️ 우리의 상황이 책과 동일한 것인지도 확인해 보아요.

Nect action item

  • conn keep-alive를 20초, conn timeout을 0초, read conn timeout을 30초 구성하고 DR DB에게 30초 보다 작은 시간 내로 쿼리가 도달하는지 확인합니다. (Workbench 연결 재시도 로직 존재 여부를 이중 검증)
  • DR 전환 후 바라보는 IP가 변하는지 nslookup으로 확인합니다. (책과 동일 상황인지를 검증)

Dove Deep PoC 결과 공유

  • 일시: 24/01/14 20:00 ~ 20:06
  • 클라이언트: MySQL Workbench
  • 데이터베이스: Amazon RDS for MySQL Multi-AZ

✔️ conn timeout에 의한 연결 재시도 확인

  1. conn keep-alive를 20초
  2. conn timeout을 0초
  3. read conn timeout을 30초 구성
  4. COMMIT 라인 실행 시 DR DB에게 30초 보다 작은 시간 내로 쿼리가 도달하는 지 확인

이 가정은 참이었습니다.
Workbench는 timeout 이벤트가 발생하면 연결 수립을 재시도 합니다.

✔️ 우리의 상황의 책과 동일한 것인지도 확인

  1. DR 전환 후 바라보는 IP가 변하는지 nslookup으로 확인합니다. 

네 IP가 변화합니다. 그러므로
RDS DR 직후 연결 이슈가 있으면, DNS 해결 이슈 + 댕글링 연결 이슈를 모두 고려해 보아야 합니다.

(끝.)