극히 개인적이고 극히 대단하지 않은

다수 클라이언트 환경에서의 서버 소켓의 listen 본문

20년차 개발자

다수 클라이언트 환경에서의 서버 소켓의 listen

회색싼타 2022. 12. 8. 12:00

언젠가는 좀 상세하게 정리해야 겠지만, 그렇게 할 시간을 내기 전에 간단히, 잊어버리지 않을 정도로 기록을 남길 필요가 있어서 정리해둔다.

 

다수의 클라이언트에서 주기적으로 같은 시간 대에 데이터를 받아 처리하는 서버를 구현중이다. 클라이언트가 120대 정도 예상하고 있으니 최대 동시에 120 커넥션을 처리해야한다. 이러한 환경에서는 특정 커넥션에서 행이 발생한다던가 그로 인하여 다른 커넥션 및 시스템 전반에도 영향을 준다던가 하는 상황을 만들지 않기 위해, nonblock 소켓을 epoll 로 정확하게 제어하는 것에 매우 신경을 쓰게된다.

 

기본적인 시험을 통해서는 nonblock 소켓과 epoll 구현이 정확하게 예상대로 잘 동작함을 확인하였고, 120개의 클라이언트를 시뮬레이션할 시뮬레이터를 작성하여 10초마다 동시에 burst로 커넥션을 맺고 데이터를 보내고 커넥션을 정리하는 상황을 만들었을 때, 뜻 밖의 난관에 봉착하게 되었다.

 

시뮬레이터에서는 120개의 커넥션을 열고 120개의 데이터패킷을 보냈고, 서버에서도 120개의 데이터패킷을 받은 것 까지는 확인이 되나 이 중에서 실제로 accept되고 처리된 것은 약 80%만 처리가 된 것이다. 나머지 약 20%의 커넥션에 대해서는 서버가 tcpdump상 RST로 강제 종료한 것이 확인되었다. 어플리케에션에서는 accept된 80%의 커넥션에 대해서는 정상적으로 데이터를 받고 데이터가공 및 데이터베이스 처리까지 정상적으로 처리되었다.

 

우선 서버 어플리케이션으로 올라온 것에 대해서는 정상적으로 처리되는 것으로 봐서 어플리케이션의 문제라기 보다는 TCP단의 어떤 설정에 의해서 영향을 받는 것이라고 판단하고 약 이틀간을 이 문제의 해결에 매달렸지만, 문제의 원인은 습관적으로 코딩에 써 온 다음의 코드 때문이었다.

listen (nSocket, 5)

listen의 두 번째 파라미터는 backlog로 불리는데, 무의식적으로 5의 값을 쓴다. 대부분의 샘플코드에서도 그렇게 예시되어있고 그에 대한 별다른 설명이 없어서, 그리고 별다른 문제가 없었기에 관행적으로 그래왔던 것이다.

 

나중에 자세히 파봐야 겠지만, backlog는 동시에 처리하는 커넥션의 수와 관련이 있다. 완전한 큐의 형태는 아니지만, 대기열의 의미와 비슷하다. 따라서 동시에 다수의 커넥션이 발생하는 경우라면 backlog의 값을 넘어서는 동시 커넥션은 서버에 의해 거부(RST)될 수 있다. 

 

시험삼아 backlog의 값을 1024로 변경하여 시험을 하였는데, 커넥션에 대한 거부나 예외없이 모두 정상적으로 잘 처리되는 것을 확인했다. backlog의 값은 커널 파라미터 net.core.somaxconn의 값을 넘을 수는 없다. 

 

시험환경 : Ubuntu 20.04, 개발언어 : C

Comments