it-swarm.com.de

Wie wird der verfügbare Speicherplatz des Linux UDP-Puffers überwacht?

Ich habe eine Java App unter Linux, die den UDP-Socket öffnet und auf Nachrichten wartet.

Nach ein paar Stunden unter hoher Last kommt es zu einem Paketverlust, dh die Pakete werden vom Kernel empfangen, aber nicht von meiner App in unseren App-Protokollen).

Wir haben versucht, die Socket-Puffer zu vergrößern, aber das hat nicht geholfen - wir haben später als zuvor angefangen, Pakete zu verlieren, aber das war's.

Zum Debuggen möchte ich wissen, wie voll der OS-UDP-Puffer zu einem bestimmten Zeitpunkt ist. Gegoogelt, aber nichts gefunden. Können Sie mir helfen?

P.S. Leute, mir ist bewusst, dass UDP unzuverlässig ist. Allerdings empfängt mein Computer alle UDP-Nachrichten, während meine App einige davon nicht verarbeiten kann. Ich möchte meine App maximal optimieren, das ist der Grund für die Frage. Vielen Dank.

46
Yoni Roit

Linux stellt die Dateien /proc/net/udp und /proc/net/udp6, das alle offenen UDP-Sockets auflistet (für IPv4 bzw. IPv6). In beiden Spalten tx_queue und rx_queue zeigt die ausgehenden und eingehenden Warteschlangen in Bytes.

Wenn alles wie erwartet funktioniert, wird in diesen beiden Spalten normalerweise kein anderer Wert als Null angezeigt: Sobald Ihre Anwendung Pakete generiert, werden diese über das Netzwerk gesendet, und sobald diese Pakete vom Netzwerk eingehen, wird Ihre Anwendung aktiviert und empfangen Sie sie (der Aufruf von recv kehrt sofort zurück). Möglicherweise sehen Sie das rx_queue nach oben gehen, wenn Ihre Anwendung den Socket geöffnet hat, aber nicht recv aufruft, um die Daten zu empfangen, oder wenn sie solche Daten nicht schnell genug verarbeitet.

39
Juliano

UDP ist ein perfekt funktionierendes Protokoll. Es ist der gleiche alte Fall des richtigen Werkzeugs für den richtigen Job!

Wenn Sie ein Programm haben, das auf UDP-Datagramme wartet und diese dann verarbeitet, bevor Sie zum Warten auf ein anderes Programm zurückkehren, muss die verstrichene Verarbeitungszeit immer schneller sein als die Ankunftsrate von Datagrammen im ungünstigsten Fall. Ist dies nicht der Fall, fängt die UDP-Socket-Empfangswarteschlange an, sich zu füllen.

Dies kann für kurze Bursts toleriert werden. Die Warteschlange macht genau das, was sie tun soll - sie stellt Datagramme in die Warteschlange, bis Sie fertig sind. Wenn die durchschnittliche Ankunftsrate jedoch regelmäßig zu einem Rückstand in der Warteschlange führt, ist es an der Zeit, Ihr Programm neu zu gestalten. Hier gibt es zwei Hauptoptionen: Reduzieren Sie die verstrichene Verarbeitungszeit durch geschickte Programmiertechniken und/oder Multithreading Ihres Programms. Es kann auch ein Lastenausgleich für mehrere Instanzen Ihres Programms verwendet werden.

Wie bereits erwähnt, können Sie unter Linux das proc-Dateisystem untersuchen, um den Status der Aktivitäten von UDP abzurufen. Zum Beispiel, wenn ich cat das /proc/net/udp Node, ich bekomme so etwas:

$ cat /proc/net/udp   
  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode ref pointer drops             
  40: 00000000:0202 00000000:0000 07 00000000:00000000 00:00000000 00000000     0        0 3466 2 ffff88013abc8340 0           
  67: 00000000:231D 00000000:0000 07 00000000:0001E4C8 00:00000000 00000000  1006        0 16940862 2 ffff88013abc9040 2237    
 122: 00000000:30D4 00000000:0000 07 00000000:00000000 00:00000000 00000000  1006        0 912865 2 ffff88013abc8d00 0         

Daran kann ich erkennen, dass ein Socket mit der Benutzer-ID 1006 den Port 0x231D (8989) abhört und die Empfangswarteschlange ungefähr 128 KB groß ist. Da die maximale Größe meines Systems 128 KB beträgt, kann mein Programm mit den ankommenden Datagrammen leider nicht mithalten. Bisher wurden 2237 Daten gelöscht, was bedeutet, dass die UDP-Schicht keine weiteren Datagramme in die Socket-Warteschlange stellen kann und diese löschen muss.

Sie können das Verhalten Ihres Programms im Laufe der Zeit beobachten, z. mit:

watch -d 'cat /proc/net/udp|grep 00000000:231D'

Beachten Sie auch, dass der Befehl netstat ungefähr dasselbe ausführt: netstat -c --udp -an

Meine Lösung für mein kleines Programm wird Multi-Thread sein.

Prost!

59
RickS

rx_queue gibt Ihnen zu jedem Zeitpunkt die Länge der Warteschlange an, aber nicht, wie voll die Warteschlange war, d. h. die Hochwassermarke. Es gibt keine Möglichkeit, diesen Wert ständig zu überwachen, und es gibt keine Möglichkeit, ihn programmgesteuert abzurufen (siehe Wie erhalte ich die Datenmenge in der Warteschlange für den UDP-Socket? ).

Die einzige Möglichkeit, die Länge der Warteschlange zu überwachen, besteht darin, die Warteschlange in Ihr eigenes Programm zu verschieben. Mit anderen Worten, starten Sie zwei Threads. Einer liest den Socket so schnell wie möglich und speichert die Datagramme in Ihrer Warteschlange. und das andere ist Ihr Programm, das aus dieser Warteschlange zieht und die Pakete verarbeitet. Dies setzt natürlich voraus, dass Sie sicherstellen können, dass sich jeder Thread auf einer separaten CPU befindet. Jetzt können Sie die Länge Ihrer eigenen Warteschlange überwachen und die Highwater-Marke verfolgen.

4
Anne

Der Prozess ist einfach:

  1. Falls gewünscht, pausieren Sie den Bewerbungsprozess.

  2. Öffnen Sie den UDP-Socket. Sie können es bei Bedarf mit /proc/<PID>/fd Aus dem laufenden Prozess entfernen. Oder Sie fügen diesen Code der Anwendung selbst hinzu und senden ihm ein Signal - der Socket ist natürlich bereits offen.

  3. Rufen Sie recvmsg so schnell wie möglich in einer engen Schleife auf.

  4. Zählen Sie, wie viele Pakete/Bytes Sie haben.

Dadurch werden alle aktuell gepufferten Datagramme verworfen. Wenn dies jedoch zu Problemen mit Ihrer Anwendung führt, war Ihre Anwendung bereits beschädigt.

0
David Schwartz