Web 서버에서의 Thundering Herd

원문 WebサーバでのThundering Herdは過去の話?


Thundering Herd란 하나의 소켓에 대해서 select나 epoll 같이 통신 가능하게 되는 것을 기다리는 시스템 콜을 이용하여 복수의 프로세스(또는 스레드)가 대기하고 있다면, 통신 가능하게 되었을 때 원래 하나의 프로세스만 일어나기를 원했는데 대기하던 모든 프로세스가 일어나는 문제이다.

이 경우 실제로 통신할 수 있는 것은 가장 빠르게 통신을 시작한 프로세스뿐이므로 다른 프로세스가 일어나는 것은 소용없다.

SO_REUSEPORT를 사용하면 하나의 소켓에 대해서 하나의 프로세스만 통신 가능하게 되는 것을 기다릴 수 있고, 커널은 같은 포트를 보는 소켓 중 하나만 선택하도록 한다.
이것에 의해 쓸데없이 프로세스가 일어나는 것은 일체 사라져서 성능 향상을 기대 할 수 있다는 것이다.
상당히 좋은 것인데 사실 Thundering Herd기 말하는 만큼 성능을 약화시키고 있느냐는 것은 개인적으로 의문이다.

만약 1 프로세스가 1 요청만 다루는 모델이라면 대량의 프로세스 손실을 일으키므로 CPU 시간이 아까워질 것이다.
그러나 nginx처럼 1 프로세스가 대량의 요청을 다루는 모델이면 프로세스 수는 겨우 코어 개수이며, 프로세스를 일으키는 부하는 그만큼 커지 않을 것이다.
더구나 어느 정도 서버에 대한 접속이 집중해서 일어나는 프로세스 수가 큐에 쌓인 접속 요구 수를 웃돌고 있다면 비록 Thundering Herd의 문제에서 말하는 쓸데 없이 일어난 프로세스라 해도 accept에 성공해서 결과적으로 제기된 낭비는 없을 수도 있다.
그래서 이 글(http://nginx.com/blog/socket-sharding-nginx-release-1-9-1/)에서는 Tundering Herd에 언급하고 있지만 Thundering Herd 해소로 성능이 2배가 된다는 것은 별로 납득할 수 없다.

SO_REUSEPORT가 해결해 주는 문제 중 기사에서 언급되지 않은 점을 더 생각한다.
커널 내에서 소켓의 표현이 하나라서 lock 쟁탈이 일어나는 것을 각 프로세스가 서로 다른 소켓을 다루어서 다툼이 없고 다른 코어에 배치되는 것이다.
복수의 프로세스가 같은 주소에 접속해서 CPU의 캐시가 효과적으로 일하지 않는 문제를 막을 수 있다는 이점이 있다.


이 글은 2017-12-12에 작성되었습니다.