오류발생과 해결

뜬금없이 발생한 Too Many Connection

지팡구 2025. 2. 22. 21:12
  • 문제 상황 :
    • k8s에 의해 N개의 파드, previw 서버, 레플리카, 오토 스케일링 등등의 운영 환경 배포 상황에서 관리자 모듈을 빌드 및 오케스트레이션 하는 과정에서 커넥션이 다수 발생해서 설정된 DB 커넥션의 한계치를 넘어버리는 상황
      • 추가 설명 : (멀티 모듈의 상위 모듈은 하위 모듈이 가지고 있는 의존성들의 커넥션의 총 합을 갖게 됨..)
    • 어플리케이션의 actuator가 헬스체크도 제대로 못할 뿐더러 rds에서 생성한 db 의 max_connection의 임계치까지 도달해버려 로컬에서 DB 접속이 불가해지고, 물론 파드에 문제가 발생하는 현상 식별
  • 멀티 모듈 형태의 아키텍처를 가지고 있는 어플리케이션에서 **관리자 모듈(**Admin)을 운영 환경에 배포해야하는 상황에서 발생한 문제

  • 고민한 내용 그리고 문제 식별과 해결 포인트 :
    • 고민 1)
      • pods는 정상으로 떴다는 신호를 받아서 원하는 페이지에는 접근이 가능할 것이라는 생각
      • thymeleaf의 LoginPage에 접근하지 못하는 현상 발생
      • 이 시점까지 커넥션이 문제가 될 것이라 생각 x
          • security 설정 점검 및 변경문제 없음
            • 마이그레이션 이전 버전의 security 설정파일 재점검 및 오탈자,누락된 부분 있는지 확인 → 없음
          • fabicon.ico 이미지 문제일까 추가 후 재시도(경로 및 실제 이미지 문제)실패
          • **외부 폰트를 가지고 오는 html 의 링크에서 해당 부분에서 접근에 관한 보안 정잭으로 인해 문제가 생긴 것인지 주석 후 시도 (외부에서 접근에 관련내용의 문제)**→ 실패
          • k8s 내부의 포트 문제일까 싶어 포트 변경 후 재시도실패
          • 기존에 설정해놓은 Mybatis의 설정때문인가 싶어 일부 설정 변경 및 비교문제 없음
          • SSL 인증서 점검문제 없음
            • openenssl s_client -connect 웹서버 주소:443
          • 혹시나 helm chart에 http 관련 설정이 문제가 있는 것일까 싶어 helm-chart에 아래의 설정 추가(쿠버 네티스 자체적인 문제)실패
            • data: server.insecure: "true"
          • 사내 서비스의 관리자도 동일하게 thymeleaf로 되어 있음을 알고 설정 추가(엔진엑스 관련 ingress.yaml 설정 추가) → 실패 (
nginx.ingress.kubernetes.io/proxy-body-size: 50m  
nginx.ingress.kubernetes.io/proxy-connect-timeout: "300" 
nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
nginx.ingress.kubernetes.io/proxy-read-timeout: "300" 
nginx.ingress.kubernetes.io/from-to-www-redirect: "true"

 

  • 각 설정 별 부가 설명
    • nginx.ingress.kubernetes.io/proxy-body-size
      • Client에서 업로드 할 수 있는 최대 요청 본문 크기 제한
        • 파일 업로드와 같은 요청에서 큰 데이터 전송 시, 기본 값보다 큰 값으로 조정할 때 사용
      • 기본값 1MB → 늘리지 않으면 413 Error 발생
    • nginx.ingress.kubernetes.io/proxy-connect-timeout
      • BE 서버와 연결을 설정하는 데 최대 대기 시간
      • 기본값 60s → 타겟 서버가 느리면 사용
    • nginx.ingress.kubernetes.io/proxy-send-timeout
      • nginx가 BE 서버로 요청 보낼 때의 타임아웃
    • nginx.ingress.kubernetes.io/proxy-read-timeout
      • nginx가 BE 서버의 응답을 읽을 때 대기 설정
      • 대용량 데이터 처리 혹은 수행이 오래 걸리는 작업애 대해 적절한 타임 고려
    • nginx.ingress.kubernetes.io/from-to-www-redirect
        • www가 없는 도메인을 www가 포함된 도메인으로 자동 리다이렉션


        • 고민 2)
          • 왜 커넥션이 계속해서 튈까? 혹시나 문제가 되지 않을까?를 고민 타 회사 동료들과 의견을 나누고 문제 포인트를 식별하기 위해 해당 RDS의 정보들을 확인 및 문제 식별
          /* 현재 서버에 연결된 커넥션 조회*/ 
          show status like '%used_connection%';
          
          /* 현재 실행중인 mysql 프로세스 조회 */ 
          SHOW PROCESSLIST;
          
          /* 현재의 DB에 Max Connection */ 
          show variables like 'max_connections';
          

  • 문제 포인트 :
    • 최대치로 설정된 값에 대한 현재 수행중인 커넥션이 이미 넘어버린 상황
      • aws rds db.t3.medium + mariaDB 기준 Max connection 152
      • 이미 수행중인 프로세스가 152 connection
        • 할당중인 버퍼 사이즈 및 데이터 관련 계산 :
SHOW VARIABLES LIKE 'sort_buffer_size'; # 2097152 
SHOW VARIABLES LIKE 'join_buffer_size'; # 262144
SHOW VARIABLES LIKE 'read_buffer_size'; # 262144
SHOW VARIABLES LIKE 'read_rnd_buffer_size';  # 524288 
SHOW VARIABLES LIKE 'thread_stack'; #262144
SHOW VARIABLES LIKE 'net_buffer_length'; #16384

sort_buffer_size = 2097152 / 1024 = 2048KB
join_buffer_size = 262144 / 1024 = 256KB
read_buffer_size = 262144 / 1024 = 256KB
read_rnd_buffer_size = 524288 / 1024 = 512KB
thread_stack = 16384 / 1024 = 16KB

2048KB + 256KB + 256KB + 512KB + 16KB = 3088KB (약 3.02MB)

 

    • HiKariCP와 같은 커넥션 풀은 미리 일정 수의 커넥션을 생성하고 유지함 (사용하지 않더라도)
    • 설정된 최소 커넥션 값이 높으면 사용하지 않는 커넥션도 계속해서 유지


 

 

  • 해결 포인트 :
    • 커넥션을 어떤 방식으로 늘릴 것인가?
      • 강제적으로 커넥션 수를 조정하거나..
        • (set global max_connection= xxx or 파라미터 그룹 에서 설정)
      • 기존에 제로카라는 전체 서비스는 모두 다 한 곳의 RDS를 바라보고 있는 상황인데, 이를 좀 분리하는 방식 (새로운 RDS 생성) → (추후 작업 예정 확정)
        • ERP 모듈이 바라보고 있는 RDS 와 서비스 운영을 위한 API 서버들이 바라보고 있는 RDS
      • 그러는 과정에서 알게 된 사실
        • MariaDB 는 보수적으로 약 24MB의 메모리를 커넥션에 할당하게 된다 → 이걸 통해서 max_connection을 계산할 수 있음 (mysql =24MB)
          • ai 답변 (아래)
      • mysql처럼MariaDB도 할당하는 메모리의 사이즈를 줄여 최대 커넥션 개수 증진으로 max_connection 증가로 이전에 발생한 문제인 To many Connection 해결(해결)
        • maximun-pool-size 설정 ⇒ 해당 모듈은 커넥션이 많이 필요 없음
        • 그러나 근본적으로 관리자 로그인 화면인 타임리프에 접근하지 못하는 이슈는 그대로 존 빌드 시 k8s가 새로운 파드를 띄우면서 커넥션을 잡게 되는데, 여기서 더 넘을 수 없어 빌드 로그에선 Too Many Connection 에러 발생
네, MariaDB는 기본 공식이 조금 다릅니다. RDS MariaDB의 경우:`LEAST({DBInstanceClassMemory/25165760},12000)`이 공식을 사용합니다. 여기서 차이점을 보면:MySQL:

- 연결당 약 12MB (12,582,880 바이트) 계산
- 상한값 제한 없음

MariaDB:

- 연결당 약 24MB (25,165,760 바이트) 계산
- 최대 12,000개로 상한값 제한

이런 차이가 있는 이유는:

1. MariaDB가 연결당 더 보수적으로 메모리를 할당 (약 24MB)
2. 과도한 연결로 인한 서버 부하를 방지하기 위해 절대적인 상한선(12000) 설정

따라서 같은 인스턴스 타입이라도 MariaDB는 MySQL보다 기본적으로 더 적은 최대 연결 수를 허용하게 됩니다.