본문 바로가기
컴퓨터공학/네트워크

How Netflix tunes network kernel

by 딩코딩코 2019. 12. 12.

먼저 넷플릭스는 우분투 리눅스를 바탕으로 한다.

넷플릭스에서 네트워크 부분에서 수정하는 것들은 아래와 같다.

net.core.somaxconn = 1024
net.core.netdev_max_backlog = 5000
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_wmem = 4096 12582912 16777216
net.ipv4.tcp_rmem = 4096 12582912 16777216
net.ipv4.tcp_max_syn_backlog = 8096
net.ipv4.tcp_slow_starter_after_idle = 0
net.ipv4.tcp_tw_reuse = 1
net.ipv4.ip_local_port_range = 10240 65535

1. backlog

먼저, backlog와 관련한 것들을 살펴보면 다음이 있다.

net.core.somaxconn = 1024
net.core.netdev_max_backlog = 5000
net.ipv4.tcp_max_syn_backlog = 8096

네트워크에서 패킷을 주고 받는 것과 관련해 송신자와 수신자는 패킷을 손실하지 않기 위한 대책이 있어야 하는데,
backlog는 수신자 측에서 데이터 queue를 만들고 그 크기를 설정하는 것과 관련한 것이다.
이때, 데이터가 queue가 감당할 수 있는 양을 초과하여 전달될 경우, 해당 데이터는 손실되는 것이다.
때문에 대규모 패킷 처리가 필요한 서버의 경우, 데이터 손실을 줄이기 위해 이 backlog의 크기를 적당히 늘려주는 것이 필요하다.
이와 관련한 명령어는 다음과 같다.

net.core.netdev_max_backlog = 5000

한편, listen backlog, 즉 listen()으로 바인딩 된 소켓들 중 accept()를 기다리는 소켓 개수에 관한 명령어는 다음과 같다.

net.core.somaxconn = 1024

이때, net.core.somaxconn은 accept()를 기다리는 connection completed를 위한 queue를 설정하는 명령어라면,
connection incompleted을 위한 queue를 설정하는 명령어는 다음과 같다.

net.ipv4.tcp_max_syn_backlog=1024

2. port range

클라이언트 소켓이 서버와 연결을 맺을 때는 포트라는 자원을 하나 소비해야하는데, 포트는 그 개수가 한정되어있다.
이때, proxy 서버 ( 사용자의 요청을 받아 다른 백엔드 서버로 연결해주는 서버 )의 경우, 다른 백엔드 서버에 연결하기 위한
클라이언트 소켓이 필요하다.

net.ipv4.ip_local_port_range = 10240 65535

두 값은 각각 포트 범위의 시작 값과 끝 값을 의미하는데, 위와 같이 설정할 경우, '최대한 넓은 값으로 잡아 달라'라는 의미다.

3. TCP socket buffer size

소켓을 주고 받을 때, receiver window size를 증가시켜, 한 번에 더 많은 소켓을 받으려고 하는데,
이 값을 아무리 증가시키더라도 실제 커널에 설정된 소켓의 버퍼 크기보다 커질 수는 없다.
따라서, 실제 커널의 소켓 버퍼 크기를 조절해줄 필요가 있는데, 이 와 관련한 명령어가 다음이다.

net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_wmem = 4096 12582912 16777216
net.ipv4.tcp_rmem = 4096 12582912 16777216

rmem은 receive 버퍼의 크기를 의미하고 wmem은 send 버퍼의 크기를 의미한다.
net.core로 시작하는 명령어는 tcp를 포함한 모든 종류의 소켓에 해당하는 값이고
net.ipv4는 tcp 소켓에 해당하는 명령어다.
(위 값은 적당히 보수적으로 최대한의 값을 넣은 경우라고 볼 수 있다.)

4. slow start

tcp에서 네트워크 상황으로 인한 소켓의 손실을 막기 위해, 한 번에 보내는 소켓의 양을 상황에 맞게 조절하기도 하는데, 이때 보내는 소켓의 양을 congestion window size라고 한다. 이와 관련해 그 크기를 지정하는 리눅스 커널 명령어는 다음과 같다.

net.ipv4.tcp_slow_starter_after_idle = 0

위 값을 1로 설정할 경우, idle(통신이 없는) 상태에 빠질 경우, initial congestion window size에서 시작해 다시 점점 그 값을 키우지만,
이 값을 0으로 설정할 경우, 위의 경우와 달리 항상 일정 congestion window size를 유지한다.

5. TIME_WAIT

앞에서 얘기했던 proxy 서버의 경우, TIME_WAIT 상태의 소켓이 서버의 성능에 영향을 끼친다.
TIME_WAIT상태의 소켓 수가 로컬 포트를 선점해버리면, 생성 가능한 클라이언트 소켓 개수가 제한되며, 이는 다른 서버에 동시 질의 할 수 있는 연결 수를 줄이는 것이다. 때문에 이러한 문제를 해결하는 방법 중 하나가 다음 명령어이다.

net.ipv4.tcp_tw_reuse = 1

이 명령어는 로컬 포트 개수가 부족할 경우, 현재 TIME_WAIT 상태의 소켓 중, 프로토콜을 고려하여 사용해도 무방한 소켓을 재사용하는 것이다.

위와 같이 튜닝하는 목적은 결국
1.대용량 서버에서 TCP 대역폭을 증가시키겠다.
2.네트워크 패킷 유실을 최소화 하겠다.

인 듯 하다.