Zoccoli trovati da lsof ma non da netstat


19

Ho un'applicazione che sta esaurendo i descrittori di file, apparentemente aprendo socket, ma non riesco a scoprire esattamente cosa fanno questi socket. Questi appaiono nell'output di lsof come

java    9689 appuser 1010u  sock       0,5          263746675 can't identify protocol
java    9689 appuser 1011u  sock       0,5          263746676 can't identify protocol
java    9689 appuser 1012u  sock       0,5          263746677 can't identify protocol
java    9689 appuser 1014u  sock       0,5          263746678 can't identify protocol
java    9689 appuser 1015u  sock       0,5          263746679 can't identify protocol
java    9689 appuser 1016u  sock       0,5          263746681 can't identify protocol

e in / proc / $ PID / fd come

lrwx------ 1 appuser appuser 64 Jun 23 11:49 990 -> socket:[263732085]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 991 -> socket:[263732086]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 992 -> socket:[263735307]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 993 -> socket:[263732088]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 995 -> socket:[263735308]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 996 -> socket:[263735309]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 997 -> socket:[263745434]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 998 -> socket:[263745435]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 999 -> socket:[263745436]

ma non esiste un output simile in netstat -a.

Cosa sono queste prese e come posso sapere cosa fanno?

Modifica : ho provato a correre grep $SOCKET /proc/net, come raccomandato nelle FAQ di lsof , dove $ SOCKET è ad esempio 263746679, ma anche questo non ha dato risultati.


Come sfondo, l'applicazione è un contenitore per più attività che, tra le altre, eseguono chiamate di rete. Devo individuare quello che impazzisce, ma fino a quando non scopro con chi comunicano quelle prese, sono bloccato.


Di recente stiamo anche affrontando questo problema con una delle nostre app Web .NET Core (server Ubuntu con Kestrel), ma il dispositivo registrato è "0,9" con il nome "protocollo: TCP". Cercare di scoprire esattamente quali sono i dispositivi 0 e 9 si è rivelato difficile. Ma i sintomi sembrano tutti lo stesso caso di aprire le prese senza legarle e usarle.
Icelava,

Risposte:


17

Ciò può verificarsi se si crea un socket, ma non si connette mai () o bind () con esso. La soluzione migliore potrebbe essere quella di rintracciare (-fF) l'applicazione e quindi fare un riferimento incrociato con l'output di lsof per determinare quali socket stanno causando il problema. Come metodo bonus di debug: se si avvolgono le chiamate del socket con le informazioni di debug e le si scrivono in / dev / null, appariranno in sequenza senza darti file di registro esilaranti.


Grazie, sembra interessante. Proverò a scoprire se questo è davvero il caso della nostra applicazione.
Robert Munteanu,

1
Un po 'sulla stessa linea, perché questa è Java potrebbe essere molto difficile usare la traccia; un metodo migliore potrebbe essere quello di creare la propria sottoclasse di socket che registra le informazioni prima di passarle al socket JDK genitore (reale). strace può vedere solo le chiamate Java sottostanti al sistema operativo e non può vedere all'interno dei thread per ciò che sta effettivamente facendo quelle chiamate socket, per stracciare tutto sembra solo una grande palla di Java.
troyengel,

@troyengel: ho (ri) scoperto Byteman ( jboss.org/byteman ) uno strumento molto accurato che mi permette di iniettare il bytecode necessario per tracciare queste chiamate.
Robert Munteanu,

La risposta più utile, quindi questo ottiene la generosità. Grazie!
Robert Munteanu,

2

Usando Python, ho riscontrato lo stesso problema sui socket SSL:

  • Quando uso socket.close (), il socket rimane nello stato CLOSE_WAIT per un tempo indefinito
  • quando uso socket.shutdown (), lsof dice "impossibile identificare il protocollo"

La soluzione era di scartare il livello SSL prima di chiudere:

  • origsock = socket.unwrap ()
  • origsock.close ()

Questo chiude correttamente le prese nella mia app.


1

La prima cosa che vorrei fare è annullare se il limite del descrittore di file:

~# vi /etc/sysctl.conf
fs.file-max = 331287

Quindi mi assicurerò che il tuo sistema sia aggiornato, questo include tutte le librerie e i server. È possibile che il server delle applicazioni Java non sia aggiornato (se ne usi uno). È anche possibile che il tuo server delle applicazioni sia configurato in modo errato, dovresti guardare il tuo file di configurazione e abbassare il tuo connectionTimeoute / o il tuo maxKeepAliveRequests(non sono sicuro di quale server applicazioni stai usando o se ne stai usando uno ...).

Non sono sicuro di cosa faccia questa applicazione, ma se non pensi che richieda decine di migliaia di socket, questa è quasi certamente una "perdita di descrittore di file" nella tua applicazione Java. Potrebbe essere necessario inviare una segnalazione di bug al fornitore. In questa segnalazione di bug è necessario includere informazioni su come ricreare il problema.

Ecco alcuni modi per eseguire il debug del problema.

Wireshark (o twireshark per il cli) è lo strumento migliore per vedere come vengono utilizzati questi socket. Wireshark ti darà una panoramica del tipo di traffico che viene lanciato sul filo. È probabile che le prime connessioni abbiano esito positivo e quindi colpirà il limite del descrittore di file. Una volta raggiunto il limite del descrittore di file, Wireshark non raccoglierà nulla (e neat è netstat per quella materia), ma ciò contribuirà a restringere il problema. In alcuni casi è possibile che vengano inviati molti SYN in uscita, tuttavia non vengono ricevuti SYN / ACK, pertanto molte connessioni tcp sono bloccate nello stato SYN_WAIT.

Se si ha accesso al codice sorgente e si conosce il tipo di socket in fase di creazione (come l'utilizzo di strace o la ricerca del codice), è possibile aprire il progetto in Eclipse (o un altro IDE) e impostare un punto di interruzione nella funzione che sta creando questi socket. Quando il punto di interruzione viene colpito, puoi guardare la traccia dello stack. Questo descrittore di file perde forse un semplice ciclo infinito o forse il valore di timeout del socket è troppo grande. Un'altra possibilità è che l'app java non stia eseguendo un'operazione socket.close()di pulizia delle connessioni. Fare una chiusura è comunemente fatto nel finelyblocco di un try/catch(Sì, un socket deve sempre avere un tentativo / cattura in Java o non si costruirà :). Alla fine della giornata è probabile che l'app Java non gestisca correttamente le sue IOException.


Grazie per la risposta. In realtà sto sviluppando questa applicazione - la parte del contenitore - piuttosto che gestirla, e non sono riuscito a trovare alcun problema relativo alla chiusura dei socket. Ma il suggerimento di WireShark / Twireshark è buono, lo userò.
Robert Munteanu,

@Robert Munteanu Se stai creando questa app, questa è una domanda per StackOverflow. Tuttavia non stai aprendo troppe prese.
Rook

Rook: ho rinunciato a scoprire questo in codice e ho cercato di rintracciarlo come amministratore di sistema. Ecco perché ho pubblicato su SF. E sì, so che in qualche modo troppe prese sono aperte. Ma ci sono zero indizi su dove ...
Robert Munteanu,

@Robert Munteanu Devi impostare i punti di interruzione alla creazione del socket e guardare la traccia dello stack e la memoria in quel punto. Sospetto che stai cadendo in un ciclo infinito. Essere in grado di esaminare qualsiasi variabile e passo attraverso il codice sarà l'approccio migliore per problemi complessi come questo.
Rook,

Purtroppo, ciò accade apparentemente in modo casuale su uno dei 20 server, non sempre gli stessi, solo negli ambienti di produzione e forse due volte a settimana. Altrimenti sarebbe stato piuttosto semplice estirpare. Attualmente sto usando Byteman ( jboss.org/byteman ) per tracciare la creazione di socket / bind / connect / close. Speriamo che ne uscirà qualcosa.
Robert Munteanu,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.