W systemie Linux, w jaki sposób mogę stwierdzić, ile efemerycznych portów pozostało dostępnych?

17

Czy w Linuksie jest metoda sprawdzenia, ile portów efemerycznych pozostało dostępnych? Czasami widzę błędy „Adres już używany” w wyniku wyczerpania się efemerycznych portów. Ponowne uruchomienie komputera rozwiązuje ten problem, ale lepiej byłoby go złapać, zanim to nastąpi.

JMc
źródło
Jeśli napotykasz takie błędy, sugeruję, że albo nadużywasz systemu, że nie używasz odpowiedniego oprogramowania lub architektury do pracy, albo twoje oprogramowanie jest niewłaściwe lub źle skonfigurowane. Być może twoje limity czasu są zbyt długie dla twojej aplikacji lub coś pozostawia otwarte połączenia bez ich użycia?
Caleb
1
Istnieje wiele prawidłowych aplikacji, które wymagają dodatkowych efemerycznych portów wykraczających poza ustawienia domyślne systemu operacyjnego.
GregB

Odpowiedzi:

26

Zakres portów efermalnych jest określony w /proc/sys/net/ipv4/ip_local_port_range. Prawdopodobnie możesz go rozszerzyć, aby działał z 16k do 64k.

Możesz zobaczyć liczbę otwartych połączeń za pomocą netstat -an. Gniazda mogą utknąć w stanie TIME_WAIT, jeśli otwierasz i zamykasz wiele połączeń. W niektórych miejscach jest to nieuniknione, ale w takim przypadku może być konieczne rozważenie, czy potrzebujesz puli połączeń.

Jeśli problemem jest TIME_WAIT, możesz ustawić net.ipv4.tcp_tw_reuse/, net.ipv4.tcp_tw_recycleaby przyspieszyć rotację połączenia.

Sean
źródło
+1, dziękuję za poświęcenie czasu na podanie temu facetowi dokładnych szczegółów.
Caleb
Mamy zakres od 32800 do 61000. Po prostu okazało się, że po ich użyciu system operacyjny nie będzie ich używał ponownie. Jest to oczekiwane zachowanie, ale oczekiwałbym, że system operacyjny uruchomi się ponownie na początku, gdy osiągnie ostatni dostępny port. Wydaje się, że tak się nie dzieje. Należy również zauważyć, że nie jest to niezwykle regularne zjawisko. Jest sporadyczne, ale mamy dużą liczbę serwerów.
JMc
1
Aby zachować zgodność z RFC 6335, /proc/sys/net/ipv4/ip_local_port_range musi być podzbiór 49152-65535. Zatem zmniejszenie dolnej granicy zakresu do wartości mniejszej niż 49152 wiąże się z pewnym ryzykiem.
kasperd
nigdy nie używaj net.ipv4.tcp_tw_recycle ani net.ipv4.tcp_tw_reuse, chyba że jesteś zdesperowany i wiesz dokładnie, co robisz. Narażasz swoją usługę na potencjalny problem ekstremalny.
Kiwy,
3

Pamiętaj, że ten limit dotyczy pojedynczej krotki (źródłowy adres IP, równorzędny adres IP, port równorzędny). Dlatego musisz zgrupować dane wyjściowe netstat/ sswedług każdej z tych krotek i sprawdzić, jak blisko każdej grupy jest limit połączenia.

W tym poście wyjaśniono bardziej szczegółowo, w jaki sposób można to zrobić. Aby sprawdzić, jak blisko każdej grupy jest limit w Ruby, możesz przetwarzać ssdane wyjściowe, takie jak:

#!/usr/bin/ruby

first_port, last_port = IO.read('/proc/sys/net/ipv4/ip_local_port_range').split.map(&:to_i)
ephemeral_port_max = last_port - first_port + 1
ephemeral_port_warning = ephemeral_port_max / 3 * 2

conns = `ss --numeric --tcp state connected "( sport >= :#{first_port} and sport <= :#{last_port} )"`

groups = Hash.new(0)
conns.lines.each do |conn|
  state, recvq, sendq, local, peer = conn.split
  local_ip, local_port = local.split(':')
  group = [local_ip, peer]
  groups[group] += 1
end

groups_requiring_warning =
  groups.select { |k, v| v > ephemeral_port_warning }
  .to_a
  .sort_by { |v1, v2| v1[1] <=> v2[1] } # Sort groups in descending order of number of connections

groups_requiring_warning.each do |group, used_port_count|
  puts "Connections from #{group[0]} to #{group[1]} "\
    "have used #{used_port_count} ephemeral ports out of #{ephemeral_port_max} max"\
    "(#{((used_port_count.to_f / ephemeral_port_max) * 100).round(2)}% used)"
end
Will Sewell
źródło