Linux에서 최대 TCP / IP 연결 수 늘리기


214

서버를 프로그래밍 중이며 연결 수를 "무제한"으로 설정 한 경우에도 대역폭이 포화되지 않으므로 연결 수가 제한되는 것 같습니다.

Ubuntu Linux 상자가 한 번에 열 수있는 최대 연결 수를 어떻게 늘리거나 제거 할 수 있습니까? OS가 이것을 제한합니까, 아니면 라우터 또는 ISP입니까? 아니면 다른 것입니까?


2
@ Software Monkey : 실제로 서버를 작성하는 사람에게 유용 할 수 있기를 바랍니다.
derobert

1
@derobert : 나는 그 +1을 보았다. 사실, 나는 이전의 의견 후에도 같은 생각을했지만, 그 의견을지지한다고 생각했습니다.
로렌스 돌

답변:


396

최대 연결 수는 약간 다르지만 클라이언트 및 서버 측의 특정 제한에 의해 영향을받습니다.

클라이언트 쪽에서 : ephermal 포트 범위를 늘리고tcp_fin_timeout

기본값을 찾으려면 다음을 수행하십시오.

sysctl net.ipv4.ip_local_port_range
sysctl net.ipv4.tcp_fin_timeout

ephermal 포트 범위는 호스트가 특정 IP 주소에서 작성할 수있는 최대 아웃 바운드 소켓 수를 정의합니다. 는 fin_timeout이 소켓에 남아있을 것입니다 최소 시간을 정의 TIME_WAIT상태 (한 번 사용 후 사용할 수 없게를). 일반적인 시스템 기본값은 다음과 같습니다.

  • net.ipv4.ip_local_port_range = 32768 61000
  • net.ipv4.tcp_fin_timeout = 60

이것은 기본적으로 시스템이 (61000 - 32768) / 60 = 470초당 소켓 이상을 일관되게 보장 할 수 없음을 의미합니다 . 당신이 그것에 만족하지 않으면, 당신은를 증가로 시작할 수 port_range있습니다. 15000 61000요즘 에는 범위를 설정하는 것이 일반적입니다. 을 줄이면 가용성을 더 높일 수 fin_timeout있습니다. 두 가지를 모두 수행한다고 가정하면 초당 1500 개가 넘는 아웃 바운드 연결을보다 쉽게 ​​볼 수 있습니다.

값을 변경하려면 :

sysctl net.ipv4.ip_local_port_range="15000 61000"
sysctl net.ipv4.tcp_fin_timeout=30

위의 내용은 초당 아웃 바운드 연결을위한 시스템 기능에 영향을주는 요소로 해석되어서는 안됩니다. 그러나 이러한 요소는 시스템의 동시 연결을 장기간 "활동"에 대해 지속 가능한 방식으로 처리하는 데 영향을줍니다.

에 대한 일반적인 리눅스 박스에 sysctl을 값을 기본 tcp_tw_recycletcp_tw_reuse

net.ipv4.tcp_tw_recycle=0
net.ipv4.tcp_tw_reuse=0

"사용 된"소켓 (대기 상태)에서의 연결을 허용하지 않고 소켓이 완전한 time_wait주기 를 지속하도록 강제합니다 . 설정하는 것이 좋습니다.

sysctl net.ipv4.tcp_tw_recycle=1
sysctl net.ipv4.tcp_tw_reuse=1 

이를 통해 소켓의 time_wait상태를 빠르게 순환 하고 재사용 할 수 있습니다. 그러나이 변경을 수행하기 전에 이러한 소켓이 필요한 응용 프로그램에 사용할 프로토콜과 충돌하지 않는지 확인하십시오. Vincent Bernat의 "TCP TIME-WAIT 대처" 게시물을 읽고 그 의미를 이해하십시오. 이 net.ipv4.tcp_tw_recycle 옵션은 동일한 NAT 장치 뒤에있는 두 대의 다른 컴퓨터로부터의 연결을 처리하지 않기 때문에 공개 서버에 매우 문제가 있습니다. 참고 net.ipv4.tcp_tw_recycle되었습니다 제거 리눅스 4.12에서.

서버 측면에서 :net.core.somaxconn 값은 중요한 역할을한다. 청취 소켓에 대기중인 최대 요청 수를 제한합니다. 서버 응용 프로그램의 기능이 확실하면 기본 128에서 128에서 1024와 같은 수준으로 올립니다. 이제 응용 프로그램의 청취 호출에서 청취 백 로그 변수를 같거나 높은 정수로 수정하여이 증가를 활용할 수 있습니다.

sysctl net.core.somaxconn=1024

txqueuelen이더넷 카드의 매개 변수도 역할을합니다. 기본값은 1000이므로 시스템에서 처리 할 수있는 경우 최대 5000 이상으로 높이십시오.

ifconfig eth0 txqueuelen 5000
echo "/sbin/ifconfig eth0 txqueuelen 5000" >> /etc/rc.local

마찬가지로 net.core.netdev_max_backlog및 의 값을 높이십시오 net.ipv4.tcp_max_syn_backlog. 기본값은 각각 1000과 1024입니다.

sysctl net.core.netdev_max_backlog=2000
sysctl net.ipv4.tcp_max_syn_backlog=2048

이제 쉘에서 FD ulimts를 늘려서 클라이언트 및 서버 측 응용 프로그램을 모두 시작하십시오.

위의 프로그래머 외에도 프로그래머가 사용하는 하나 이상의 인기있는 기술은 tcp 쓰기 호출 수를 줄이는 것 입니다. 내가 선호하는 것은 클라이언트에 보내려는 데이터를 푸시하는 버퍼를 사용하는 것입니다. 그런 다음 적절한 지점에서 버퍼링 된 데이터를 실제 소켓에 씁니다. 이 기술을 사용하면 대용량 데이터 패킷을 사용하고, 조각화를 줄이고, 사용자 영역과 커널 수준에서 CPU 사용률을 줄일 수 있습니다.


4
훌륭한 답변! 내 문제는 조금 달랐습니다. 즉, 세션 정보를 응용 프로그램 수준 세션 저장소에서 PHP를 통해 redis로 옮기려고했습니다. 어떤 이유로 든 한 번에 많은 수면을 추가하지 않고 28230 세션을 추가 할 수 없었습니다 .php 또는 redis 로그에 오류가 표시되지 않았습니다. 우리는 문제가 PHP / redis가 아니라 tcp / ip 레이어에서 두 가지를 연결 하고이 답변에 도달했다고 생각할 때까지 하루 종일 머리를 아프게했습니다. 그 후 즉시 문제를 해결하기 위해 관리 :) 감사합니다!
s1d

27
우리는 항상 IP + 포트에 대해 이야기하고 있다는 것을 잊지 마십시오. "무제한"소켓을 여러 다른 IP에서 XY 포트로 열 수 있습니다. 470의 제한은 동시에 열린 소켓에 동일한 IP에만 적용됩니다. 다른 IP는 동일한 포트에 대한 자체 470 연결을 가질 수 있습니다.
Marki555

6
@ Marki555 : 귀하의 의견은 매우 정확합니다. 많은 수의 아웃 바운드 연결을 생성하고 유지하기 위해 개발 된 응용 프로그램은 아웃 바운드 연결을 생성하기 위해 사용 가능한 IP에 대한 "인식"이 있어야하며, 그런 다음 일종의 "라운드 로빈 알고리즘"을 사용하여 이러한 IP 주소에 적절하게 바인딩해야합니다. "스코어 보드".
mdk

8
이 답변에는 실수가 있습니다. 먼저 net.ipv4.tcp_fin_timeout은 FIN_WAIT_2 상태 ( cs.uwaterloo.ca/~brecht/servers/ip-sysctl.txt ) 에만 해당됩니다 . 둘째, @Eric이 말했듯이 "언제든지 470 개의 소켓"이 올바르지 않습니다.
Sharvanath

3
@mdk :이 계산 부분이 명확하지 않습니다 (61000 - 32768) / 60 = 470 sockets per second. 좀 더 자세히 설명해 주시겠습니까?
Tom Taylor

64

최대 연결 수를 설정하는 두 가지 변수가 있습니다. 아마도 파일 번호가 먼저 부족한 것 같습니다. ulimit -n을 확인하십시오. 그 후 / proc에 설정이 있지만 기본값은 수만입니다.

더 중요한 것은 뭔가 잘못하고있는 것 같습니다. 단일 TCP 연결은 두 당사자 간의 모든 대역폭을 사용할 수 있어야합니다. 그렇지 않은 경우 :

  • TCP 창 설정이 충분히 큰지 확인하십시오. Linux 기본값은 실제로 빠른 inet 링크 (수백 메가 바이트) 또는 빠른 위성 링크를 제외한 모든 것에 적합합니다. 대역폭 * 지연 제품은 무엇입니까?
  • 큰 패킷으로 핑을 사용하여 패킷 손실 확인 ( ping -s 1472...)
  • 속도 제한을 확인하십시오. Linux에서이 구성은tc
  • 다음과 같은 방법으로 실제로 존재한다고 생각되는 대역폭이 존재하는지 확인하십시오. iperf
  • 프로토콜이 정상인지 확인하십시오. 대기 시간을 기억하십시오.
  • 이것이 기가비트 + LAN 인 경우 점보 패킷을 사용할 수 있습니까? 당신은?

아마도 나는 오해했을 것입니다. 어쩌면 당신은 많은 연결이 필요한 Bittorrent와 같은 일을하고있을 것입니다. 그렇다면 실제로 사용중인 연결 수를 확인해야합니다 (try netstat또는 lsof). 해당 숫자가 상당하면 다음을 수행 할 수 있습니다.

  • 예를 들어 100mbps +와 같은 많은 대역폭이 있어야합니다. 이 경우 실제로 ulimit -n. 여전히 ~ 1000 개의 연결 (시스템의 기본값)은 상당히 적습니다.
  • 네트워크 속도가 느려서 연결 속도가 느려질 수 있습니다 (예 : 패킷 손실)
  • 특히 원하는 경우 IO 대역폭을 늦추는 등 무언가를 줄이십시오. 확인 했습니까 iostat -x?

또한 소비자 급 NAT 라우터 (Linksys, Netgear, DLink 등)를 사용하는 경우 수천 개의 연결에서 능력을 초과 할 수 있습니다.

이것이 도움이되기를 바랍니다. 당신은 정말로 네트워킹 질문을하고 있습니다.


16

derobert의 답변을 개선하기 위해

nf_conntrack_max를 지정하여 OS 연결 제한을 확인할 수 있습니다.

예를 들면 다음과 같습니다. cat / proc / sys / net / netfilter / nf_conntrack_max

다음 스크립트를 사용하여 지정된 범위의 tcp 포트에 대한 tcp 연결 수를 계산할 수 있습니다. 기본적으로 1-65535입니다.

OS 연결 제한을 초과했는지 여부를 확인합니다.

여기 스크립트가 있습니다.

#!/bin/bash
OS=$(uname)

case "$OS" in
    'SunOS')
            AWK=/usr/bin/nawk
            ;;
    'Linux')
            AWK=/bin/awk
            ;;
    'AIX')
            AWK=/usr/bin/awk
            ;;
esac

netstat -an | $AWK -v start=1 -v end=65535 ' $NF ~ /TIME_WAIT|ESTABLISHED/ && $4 !~ /127\.0\.0\.1/ {
    if ($1 ~ /\./)
            {sip=$1}
    else {sip=$4}

    if ( sip ~ /:/ )
            {d=2}
    else {d=5}

    split( sip, a, /:|\./ )

    if ( a[d] >= start && a[d] <= end ) {
            ++connections;
            }
    }
    END {print connections}'

3
which awkAWK 경로를 결정하는 친구는, SunOS의이 :)뿐만 아니라에 대한 링크를 가지고있다
파나지오티스 Moustafellos

2
@PanagiotisM. which이 경우 프로그램에 의존 하여 전체 경로를 제공하는 대신 PATH사용할 수 있습니다 awk. (즉, 스크립트의 솔루션이 완벽에 더 가까운 지 확실하지 않지만 스크립트와 관련이 없습니다.)
Michael Krelin-해커

5
필자는이 스크립트가 탄도 적으로 awk위치 를 결정하는 방법을 좋아 하지만 쉘이 항상 있다고 가정합니다 /bin/bash (프로 팁 : AIX5 / 6에는 기본적으로 bash가 없습니다).
kubanczyk

는 IS awk탐지에 유용? 개인적으로 나는 단순히 올바른을 가지고 가정 것이 PATH아니라 합리적인 대안이 될 수 /usr/bin/env awk/usr/bin/env bash각각. 그만한 가치가 있기 때문에 Linux 시스템에서 위치가 잘못되었습니다. 그것은 /usr/bin/awk아닙니다/bin/awk
Wolph

1
이 스크립트를 실행할 때 798이 표시됩니다. 무슨 뜻입니까?

10

응용 프로그램 수준에서 개발자가 수행 할 수있는 작업은 다음과 같습니다.

서버 측에서 :

  1. 로드 밸런서 (있는 경우)가 올바르게 작동하는지 확인하십시오.

  2. 느린 TCP 시간 초과를 503 빠른 즉시 응답으로 전환하십시오.로드 밸런서가 올바르게 작동하면 서비스 할 작업 리소스를 선택해야하며 예기치 않은 오류 마사지로 걸려있는 것보다 낫습니다.

예 : 노드 서버를 사용하는 경우 u는 npm에서 toobusy를 사용할 수 있습니다. 다음과 같은 구현 :

var toobusy = require('toobusy');
app.use(function(req, res, next) {
  if (toobusy()) res.send(503, "I'm busy right now, sorry.");
  else next();
});

왜 503입니까? 과부하에 대한 좋은 통찰력은 다음과 같습니다. http://ferd.ca/queues-don-t-fix-overload.html

클라이언트 측에서도 몇 가지 작업을 수행 할 수 있습니다.

  1. 통화를 일괄 그룹화하고 트래픽과 총 요청 수를 클라이언트와 서버에 줄이십시오.

  2. 불필요한 중복 요청을 처리하기 위해 캐시 중간 계층을 구축하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.