본문 바로가기
IT 정보

외부 API호출하는 서버 개발시 주의할 점! [File Descriptor, Too Many Open Files]

by 완기 2023. 12. 14.
728x90
반응형

오늘은 솔루션을 운영하다가 발생한 문제와 그 해결법을 공유하려고 한다.

 

일단 전제를 설명하자면 현재 내가 재직 중인 회사는 B2B를 하는 회사고

도메인 특성상 많은 트래픽을 받을 일이 없었다.

 

그래서 여느떄와 다름없이 비즈니스 로직 개발에 집중을 했고, 늘 같은 개발 -> 테스트 -> 배포 -> 모니터링을 했다.

 

그런데 내가 개발한 이 솔루션을 한 회사가 사용하기로 했는데,

이 솔루션은 서버에서 외부 API를 호출하는 로직이 포함되어 있다.

 

그리고, 그 회사는 수많은 회사들과 게약으로 엄청난 트래픽(내 경험 기준에선...)을 가진 업체였다.

 

업체가 라이브하는 날을 알려줘서 모니터링을 하고 있었는데, 

갑자기 서버가 엄청난 수로 오토스케일링 되는 것을 확인했다.

 

처음에 2대였던 서버는 29대까지 늘었고,

분명히 운영 배포 이전에 서버 스트레스 테스트를 할 때는 충분히 감당 가능한 TPS인데도 서버가 무한 증식 중이었다.

 

급히 로그를 보기 시작했고,

스택 트레이스에 Exception cause가 Too Many Open Files인 에러 트레이스가 상당히 많이 찍혀있음을 발견했다.

 

스택트레이스에서 HttpClient를 호출하다가 에러가 발생했음을 확인했고, 관련된 이유를 찾기 시작했다.

HttpClient에서 대체 왜 파일을 쓰지?라는 의문이 가장 먼저 들었다.

 

당시에 chatGPT에게 물어본 의문에 대한 답은 이러했다.

 

 

File Descriptor라는 키워드가 등장했고 이와 관련된 자료들을 찾아봤다.

참고 : 파일 디스크립터(File Descriptor) 란 무엇인가?

 

chatGPT의 답변과 File Descriptor의 개념으로 보았을 때,

서버가 요청을 받은 순간 HttpClient가 호출되고

이는 네트워크 통신을 위해 네트워크 소켓 파일이 호스트에서 제한한 File Descriptor의 수를 넘었기 때문이었다.

 

그래서 Exception의 이름과 사유가 Too Many Open Files인 것이다.

 

리눅스에서 서버가 떠있다면 

ulimit -n 4096

 

등과 같이 명령어를 입력하여 Open file의 제한을 늘릴 수 있다.

 

그러나 내가 개발한 솔루션은 AWS ECS Fargate로 구동 중인 서버였다.

 

만약 EC2환경에 컨테이너로 서버를 운영 중이라면

docker run --ulimit nofile=65536:65536 {image이름}

--ulimit nofile=4096:4096 옵션을 사용해서 컨테이너 구동 시 ulimit을 설정할 수 있다.

 

* 혹시 권한 에러가 발생한다면 --privileged 옵션을 추가하면 되지만, 보안상 이슈가 있을 수 있으니 사용에 주의해야 한다.

 


 

ECS Fargate , ECS EC2 환경 사용 시 설정방법

AWS 공식문서(태스크 정의 파라미터)를 참고하면 더 많은 설정을 추가할 수 있지만,

공식적으로 지원되는 파라미터 설정 방법 중, Ulimits 항목을 보면 이미지와 같은 설명이 있다.

 

여기서 우리가 필요한 부분은

이 부분이다.

 

설명에서 나와있는 공식문서에도 같은 설명이 있다.

 

즉 최댓값은 1048576이다.

나의 개발 환경에선 인스턴스 1대당 서버가 1대 올라가 있어 최댓값으로 설정했다.

 

TaskDefinition에서 정의할 수 있고, 콘솔상에서 위치는 

위 이미지와 같이 입력하면 된다.

 

이와 같이 입력하고 새 TaskDefinition을 반영하여 컨테이너를 업데이트시켜주면 된다.

적용 후, 서버의 CPU 사용율 최대량 변화(11월 16일 적용, 주황색 지표가 최대 CPU 사용률)

 

적용을 완료하고 80~95%까지 치솟던 CPU 최대 사용률이 4~5%로 안정적으로 변화했다.

저 당시엔 서버가 29대였으니, 4~5%까지 내려갔었다.

 

대상그룹(Target Group) 모니터링 지표에 서버 수 지표.

15~16일 주간에 정상 호스트 수(서버 수)가 29까지 찍힌 모습.

 

적용 전, 하루 트래픽 약 3400만 서버대수 29대.

 

적용 후

하루 트래픽 약 4200만 , 서버대수 점진적으로 감소하여 현재까지 4대로 감소.

 

이후 현재까지 안정성이 훨씬 좋아져서 트래픽이 꾸준히 늘었다.

 

서버 개발자로서 저렇게 많은 서버 수를 가지고도 그 정도양의 트래픽을 못 받는 것이 굉장히 부끄러웠지만 

이런 트러블 슈팅을 해보면서 굉장히 값진 경험을 한 것 같다.

 


 

참고했던 자료들

https://somnusnote.tistory.com/entry/HttpClient-Connection-Pooling

 

HttpClient Connection Pooling

HttpClient로 빈번히 connection을 맺었다가, 사용이 끝나면 끊고 하다 보면 더 이상 connection을 열 수 없는 경우가 발생할 수 있다.그 이유는 connection을 닫는다고 호출을 해도, 실제로는 어느 정도 TIME_W

somnusnote.tistory.com

https://twofootdog.tistory.com/51

 

파일 디스크립터(File Descriptor) 란 무엇인가?

1. 개념 파일 디스크립터(File Descriptor)란 리눅스 혹은 유닉스 계열의 시스템에서 프로세스(process)가 파일(file)을 다룰 때 사용하는 개념으로, 프로세스에서 특정 파일에 접근할 때 사용하는 추상

twofootdog.tistory.com

https://sysops.tistory.com/99

 

[Linux] ulimit 설명 및 설정방법

ulimit 이란? ulimit는 프로세스의 자원 한도를 설정하는 명령, soft한도,hard한도 두가지로 나뉨 soft : 새로운 프로그램을 생성하면 기본으로 적용되는 한도 hard : 소프트한도에서 최대로 늘릴 수 있는

sysops.tistory.com

 

 

728x90
728x90

댓글