Linux'ta maksimum TCP / IP bağlantısı sayısını artırma


214

Bir sunucu programlıyorum ve bağlantı sayısını "sınırsız" olarak ayarladığımda bile bant genişliğim doygun olmadığından bağlantı sayım sınırlı görünüyor.

Ubuntu Linux kutumun aynı anda açabileceği maksimum bağlantı sayısını nasıl artırabilir veya kaldırabilirim? İşletim sistemi bunu sınırlıyor mu yoksa yönlendirici mi, ISS mi? Yoksa başka bir şey mi?


2
@Yazılım Maymunu: Bunu yine de yanıtladım çünkü umarım bu gelecekte bir sunucu yazan birine faydalı olabilir.
derobert

1
@derobert: +1 gördüm. Aslında, önceki yorumumdan sonra aynı düşünceye sahiptim, ama yorumun durmasına izin vereceğimi düşündüm.
Lawrence Dol

Yanıtlar:


396

Maksimum bağlantı sayısı, biraz farklı da olsa, hem istemci hem de sunucu tarafında belirli sınırlardan etkilenir.

İstemci tarafında: Ephermal port aralığını artırın vetcp_fin_timeout

Varsayılan değerleri bulmak için:

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

Ephermal bağlantı noktası aralığı, bir ana bilgisayarın belirli bir IP adresinden oluşturabileceği maksimum çıkış soketi sayısını tanımlar. fin_timeoutBu prizler kalacak minimum süreyi tanımlar TIME_WAITdevlet (bir kez kullanıldıktan sonra kullanılmaz hale). Genel sistem varsayılanları:

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

Bu temel olarak sisteminizin (61000 - 32768) / 60 = 470saniyede sürekli olarak soketten fazlasını garanti edemeyeceği anlamına gelir . Eğer bundan memnun değilseniz, artırmakla başlayabilirsiniz port_range. Aralığı ayarlamak 15000 61000bugünlerde oldukça yaygın. Değerini azaltarak kullanılabilirliği daha da artırabilirsiniz fin_timeout. Her ikisini de yaptığınızı varsayalım, saniyede 1500'den fazla giden bağlantı görmelisiniz, daha kolay.

Değerleri değiştirmek için :

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

Yukarıdakiler, saniyede giden bağlantı yapmada sistem kapasitesini etkileyen faktörler olarak yorumlanmamalıdır. Ancak daha ziyade bu faktörler, sistemin eşzamanlı bağlantıları, büyük "faaliyet" dönemleri için sürdürülebilir bir şekilde ele alma yeteneğini etkiler.

İçin tipik bir Linux paketinde Sysctl varsayılan değerlere tcp_tw_recycle& tcp_tw_reuseolurdu

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

Bunlar "kullanılmış" bir soketten (bekleme durumunda) bir bağlantıya izin vermez ve soketleri tam time_waitçevrimi sürdürebilir. Ayarlamanızı tavsiye ederim:

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

Bu, soketlerin hızlı bir şekilde çevrilmesine time_waitve tekrar kullanılmasına olanak tanır . Ancak bu değişikliği yapmadan önce, bu soketlere ihtiyaç duyan uygulama için kullanacağınız protokollerle çelişmediğinden emin olun. Etkilerini anlamak için Vincent Bernat'ın "TCP TIME-WAIT ile Başa Çıkma" yazısını okuduğunuzdan emin olun . Bu net.ipv4.tcp_tw_recycle seçenek, aynı NAT aygıtının arkasındaki iki farklı bilgisayardan gelen bağlantıları işlemeyeceğinden, halka açık sunucular için oldukça sorunludur , bu da algılanması ve ısırmayı beklemesi zor bir sorundur. Not net.ipv4.tcp_tw_recycleolmuştur kaldırıldı Linux 4.12 den.

Sunucu Tarafında:net.core.somaxconn değeri önemli bir role sahiptir. Bir dinleme soketine kuyrukta verilen maksimum istek sayısını sınırlar. Sunucu uygulamanızın yeteneğinden eminseniz, varsayılan 128'den 128 ila 1024 gibi bir şeye yükseltin. Şimdi, uygulamanızın dinleme çağrısındaki dinleme biriktirme değişkenini eşit veya daha yüksek bir tamsayı olarak değiştirerek bu artıştan yararlanabilirsiniz.

sysctl net.core.somaxconn=1024

txqueuelenEthernet kartlarınızın parametresinin de oynayacağı bir rol vardır. Varsayılan değerler 1000'dir, bu nedenle sisteminiz işleyebilirse bunları 5000 veya daha fazla çarpın.

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

Benzer şekilde değerlerini yükseltmek net.core.netdev_max_backlogve net.ipv4.tcp_max_syn_backlog. Varsayılan değerleri sırasıyla 1000 ve 1024'tür.

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

Şimdi hem istemci hem de sunucu tarafı uygulamalarınızı kabuktaki FD ulimt'lerini artırarak başlatmayı unutmayın.

Ayrıca, programcılar tarafından kullanılan bir diğer popüler teknik, tcp yazma çağrılarının sayısını azaltmaktır . Kendi tercihim, istemciye göndermek istediğim verileri ittiğim bir tampon kullanmak ve daha sonra uygun noktalarda tamponlanmış verileri gerçek sokete yazıyorum. Bu teknik, büyük veri paketleri kullanmamı, parçalanmayı azaltmamı, hem kullanıcı arazisinde hem de çekirdek düzeyinde CPU kullanımını azaltmamı sağlıyor.


4
Mükemmel cevap! Benim sorunum biraz farklıydı, yani bir uygulama düzeyinde oturum depolama oturum bilgileri PHP üzerinden redis taşımak için çalışıyordu. Nedense, bir seferde çok fazla uyku eklemeden 28230 oturumdan fazlasını ekleyemedim, php veya redis günlüklerinde herhangi bir hata görülmedi. Ben belki php / redis ile sorun değil ama iki bağlayan tcp / ip katmanı ve bu cevaba geldi düşündüm kadar bütün bir gün boyunca bu kafaları kırdı. Bundan sonra hiçbir zaman sorunu düzeltmeyi başardı :) Çok teşekkürler!
s1d

27
Her zaman IP + portundan bahsettiğimizi unutmayın. Birçok farklı IP'den XY bağlantı noktasına açık "sınırsız" soketlere sahip olabilirsiniz. 470 sınırı, yalnızca aynı IP'ye eşzamanlı açılan soketler için geçerlidir. Başka bir IP'nin aynı portlara kendi 470 bağlantısı olabilir.
Marki555

6
@ Marki555: Yorumunuz ÇOK DOĞRU. Çok sayıda giden bağlantı oluşturmak ve sürdürmek için geliştirilen uygulamalar, giden bağlantılar oluşturmak için kullanılabilir IP'lerin "farkındalığına" sahip olmalı ve daha sonra bir tür "yuvarlak döngü algoritması" kullanarak bu IP adreslerine uygun şekilde bağlanmalı ve bir "çetele".
MDK

8
Bu cevapta hatalar var. Birincisi, net.ipv4.tcp_fin_timeout yalnızca FIN_WAIT_2 durumu içindir ( cs.uwaterloo.ca/~brecht/servers/ip-sysctl.txt ). İkinci olarak, @Eric'in dediği gibi, "herhangi bir zamanda 470 soket" doğru değildir.
Sharvanath

3
@mdk: Bu hesaplama kısmında net değilim (61000 - 32768) / 60 = 470 sockets per second. Lütfen bunu biraz açıklayabilir misiniz?
Tom Taylor

64

Maksimum bağlantı sayısını ayarlamak için birkaç değişken vardır. Büyük olasılıkla, önce dosya numaralarınız bitiyor. Ulimit -n'yi kontrol edin. Bundan sonra, / proc'da ayarlar var, ancak onbinlerce varsayılan ayar var.

Daha da önemlisi, yanlış bir şey yapıyormuşsunuz gibi geliyor. Tek bir TCP bağlantısı, iki taraf arasındaki tüm bant genişliğini kullanabilmelidir; değilse:

  • TCP pencere ayarınızın yeterince büyük olup olmadığını kontrol edin. Linux varsayılanları, gerçekten hızlı inet bağlantısı (yüzlerce mbps) veya hızlı uydu bağlantıları hariç her şey için iyidir. Bant genişliği * gecikme ürününüz nedir?
  • Büyük paketlerle ping kullanarak paket kaybını kontrol edin ( ping -s 1472...)
  • Hız sınırını kontrol edin. Linux'ta bu,tc
  • Var olduğunu düşündüğünüz bant genişliğinin gerçekte var olduğunu doğrulayın, örn. iperf
  • Protokolünüzün aklı başında olduğunu doğrulayın. Gecikmeyi hatırla.
  • Bu bir gigabit + LAN ise, jumbo paketleri kullanabilir misiniz? Sen?

Muhtemelen yanlış anladım. Belki çok fazla bağlantıya ihtiyacınız olan Bittorrent gibi bir şey yapıyorsunuzdur. Öyleyse, gerçekte kaç bağlantı kullandığınızı bulmanız gerekir ( netstatveya deneyin lsof). Bu sayı önemliyse şunları yapabilirsiniz:

  • Çok fazla bant genişliğiniz var, örn. 100mbps +. Bu durumda, aslında ulimit -n. Yine de, ~ 1000 bağlantı (sistemimde varsayılan) oldukça azdır.
  • Bağlantılarınızı yavaşlatan ağ sorunlarınız var (örn. Paket kaybı)
  • Sizi yavaşlatan başka bir şey, örneğin, IO bant genişliği, özellikle de arıyorsanız. Kontrol ettin iostat -xmi?

Ayrıca, tüketici sınıfı bir NAT yönlendiricisi (Linksys, Netgear, DLink, vb.) Kullanıyorsanız, binlerce bağlantıyla yeteneklerini aşabileceğinize dikkat edin.

Umarım bu biraz yardımcı olur. Gerçekten bir ağ sorusu soruyorsun.


16

Derobert tarafından verilen cevabı geliştirmek için,

İşletim sistemi bağlantı sınırınızın ne olduğunu nf_conntrack_max dizinine bakarak belirleyebilirsiniz.

Örneğin: cat / proc / sys / net / netfilter / nf_conntrack_max

Belirli bir tcp bağlantı noktası aralığına tcp bağlantılarının sayısını saymak için aşağıdaki komut dosyasını kullanabilirsiniz. Varsayılan olarak 1-65535.

Bu, işletim sistemi bağlantı sınırınızı maksimize edip etmediğinizi doğrular.

İşte senaryo.

#!/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 yolu belirlemek için arkadaşın, SunOS da bir bağlantı var :)
Panagiotis Moustafellos

2
@PanagiotisM. whichProgramın olması gereken programa dayanır, PATHbu durumda awktam yol sağlamak yerine kullanabilirsiniz . (bu, koddaki çözümün mükemmellik için daha yakın olup olmadığından emin değilim, ancak komut dosyası hakkında değildir).
Michael Krelin - hacker

5
Bu komut dosyasının awkkonumu belirlemek için balistik gittiğini seviyorum , ancak kabuğun her zaman olduğunu varsayar /bin/bash (pro tip: AIX5 / 6 varsayılan olarak bash bile yoktur).
kubanczyk

Mi awktespit edilmesinin yararlı? Şahsen ben sadece doğru olduğunu varsayıyorum PATHama makul bir alternatif olabilir /usr/bin/env awkve /usr/bin/env bashsırasıyla. Değeri ne olursa olsun, Linux sistemimdeki konumu yanlış anladı. O öyle /usr/bin/awkdeğil/bin/awk
Wolph

1
Bu komut dosyasını çalıştırdığımda 798 olsun, bu ne anlama geliyor?

10

Uygulama düzeyinde, geliştiricinin yapabileceği bir şey:

Sunucu tarafından:

  1. Yük dengeleyicinin (varsa) doğru çalışıp çalışmadığını kontrol edin.

  2. Yavaş TCP zaman aşımlarını 503 Hızlı Anında yanıt haline getirin, dengeleyici çalışmasını doğru yüklerseniz, hizmet vermek için çalışma kaynağını seçmelidir ve beklenmedik hata masajlarıyla orada asılı kalmaktan daha iyidir.

Örn: Düğüm sunucusu kullanıyorsanız, npm'den çok fazla veri kullanabilirsiniz. Uygulama gibi bir şey:

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

Neden 503? Aşırı yük için bazı iyi bilgiler: http://ferd.ca/queues-don-t-fix-overload.html

Müşteri tarafında da bazı işler yapabiliriz:

  1. Çağrıları toplu olarak gruplandırmayı, trafiği ve toplam istek sayısını s / b istemci ve sunucuyu azaltmaya çalışın.

  2. Gereksiz yinelenen istekleri işlemek için bir ön katman orta katmanı oluşturmaya çalışın.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.