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_recycle및 tcp_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.