lsof에 의해 발견되었지만 netstat에 의해 발견되지 않은 소켓


19

소켓을 열어서 파일 디스크립터가 부족한 응용 프로그램이 있지만이 소켓의 기능을 정확히 찾을 수는 없습니다. 이들은 lsof 출력에 다음과 같이 나타납니다.

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

/ proc / $ PID / fd에서

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]

그러나에 유사한 출력이 없습니다 netstat -a.

이 소켓은 무엇이며 어떻게하는지 알 수 있습니까?

편집 : lsof FAQgrep $SOCKET /proc/net 에서 권장하는대로 $ SOCKET가 263746679 인 실행을 시도했지만 결과도 얻지 못했습니다.


배경으로, 응용 프로그램은 무엇보다도 네트워크 호출을 수행하는 여러 작업을위한 컨테이너입니다. 난처한 사람을 골라 내야하지만, 그 소켓이 누구와 통신하는지 알아낼 때까지 나는 갇혀있다.


최근 .NET Core 웹 앱 (Kestrel이 설치된 우분투 서버) 중 하나에서이 문제에 직면하고 있지만 기록 된 장치의 이름은 "protocol : TCP"인 "0,9"입니다. 어떤 장치 0과 9가 정확한지 알아내는 것은 어려운 것으로 판명되었습니다. 그러나 모든 증상은 소켓을 연결하고 사용하지 않고 소켓을 여는 것과 같은 경우처럼 보입니다.
icelava

답변:


17

소켓을 작성하지만 결코 connect () 또는 bind ()로 연결하지 않으면 발생할 수 있습니다. 가장 좋은 방법은 응용 프로그램을 추적 (-fF) 한 다음 lsof 출력과 상호 참조하여 문제를 일으키는 소켓을 확인하는 것입니다. 디버깅의 보너스 방법으로 : 소켓 호출을 디버깅 정보로 감싸서 / dev / null에 쓰면 엄청나게 큰 로그 파일을 제공하지 않고 strace에 나타납니다.


고마워, 이거 흥미로워 나는 그것이 실제로 우리의 응용 프로그램의 경우인지 알아 내려고 노력할 것입니다.
Robert Munteanu

1
Java이기 때문에 strace를 사용하기가 매우 어려울 수 있기 때문에 같은 줄에 있습니다. 더 나은 방법은 정보를 부모 (실제) JDK 소켓으로 전달하기 전에 로그하는 자체 소켓 서브 클래스를 작성하는 것입니다. strace는 OS에 대한 기본 Java 호출 만 볼 수 있으며 실제로 소켓 호출을 수행하는 스레드에 대한 스레드 내부를 볼 수는 없습니다.
troyengel 2016 년

@troyengel : 나는 이 호출을 추적하는 데 필요한 바이트 코드를 주입 ​​할 수있는 매우 깔끔한 도구 인 Byteman ( jboss.org/byteman )을 다시 발견했습니다 .
Robert Munteanu

가장 유용한 답변이므로 현상금을 얻습니다. 감사!
Robert Munteanu

2

Python을 사용하여 SSL 소켓에서 동일한 문제가 발생했습니다.

  • socket.close ()를 사용하면 소켓이 무한정 CLOSE_WAIT 상태로 유지됩니다.
  • socket.shutdown ()을 사용할 때 lsof는 "프로토콜을 식별 할 수 없습니다"라고 말합니다.

해결책은 SSL 레이어를 풀기 전에 풀었습니다.

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

내 응용 프로그램에서 소켓이 올바르게 닫힙니다.


1

내가 할 첫 번째 일은 파일 설명자가 제한적이라면 과감합니다.

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

다음으로 시스템이 최신 상태인지 확인하십시오. 여기에는 모든 라이브러리와 서버가 포함됩니다. Java 애플리케이션 서버가 오래되었을 수 있습니다 (사용중인 경우). 또한 응용 프로그램 서버가 잘못 구성되었을 가능성이 있으므로 구성 파일을보고 귀하 connectionTimeout및 / 또는 귀하를 낮추 십시오 maxKeepAliveRequests(어떤 응용 프로그램 서버를 사용하고 있는지 또는 전혀 사용하지 않는지 확실하지 않습니다 ...).

이 응용 프로그램의 기능을 잘 모르겠지만 수만 개의 소켓이 필요하다고 생각하지 않으면 Java 응용 프로그램 의 "파일 설명자 누출" 이 거의 확실합니다 . 공급 업체에 버그 보고서를 보내야 할 수도 있습니다. 이 버그 보고서에는 문제를 재현하는 방법에 대한 정보가 포함되어야합니다.

문제를 디버깅하는 방법은 다음과 같습니다.

Wireshark (또는 CLI의 twireshark)는 이러한 소켓이 어떻게 사용되는지 확인하는 가장 좋은 도구입니다. Wireshark는 와이어에 발생하는 트래픽 유형을 분석합니다. 처음 몇 개의 연결이 성공한 후 파일 디스크립터 한계에 도달 할 수 있습니다. 파일 디스크립터 한계에 도달하면 Wireshark는 어떤 것도 포착하지 못하고 (그리고 그 문제에 대해 깔끔한 것은 netstat입니다), 이것은 문제를 좁히는 데 도움이됩니다. 발신 SYN이 많이 전송되는 경우가 있지만 SYN / ACK가 수신되지 않아서 많은 TCP 연결이 SYN_WAIT 상태에 멈춰 있습니다.

소스 코드에 액세스 할 수 있고 생성 된 소켓 유형 (예 : strace 사용 또는 코드 검색)을 알고있는 경우 Eclipse (또는 다른 IDE)에서 프로젝트를 열고 해당 기능에서 중단 점을 설정할 수 있습니다 이 소켓을 만들고 있습니다. 중단 점에 도달하면 스택 추적을 볼 수 있습니다. 이 파일 디스크립터 누출은 단순한 무한 루프이거나 소켓 시간 종료 값이 너무 큽니다. 또 다른 가능성은 Java 앱이 socket.close()연결 정리를 수행하지 않는 것 입니다. 닫기는 일반적으로 finely블록 에서 수행됩니다 try/catch(예 : 소켓에는 항상 try / catch가 있어야합니다. 그렇지 않으면 빌드되지 않습니다). 하루가 끝나면 Java 앱이 IOException을 올바르게 처리하지 못할 수 있습니다.


답변 해주셔서 감사합니다. 실제로 컨테이너 응용 프로그램을 관리하는 것이 아니라 컨테이너 응용 프로그램을 개발 중이며 소켓이 닫히지 않는 것과 관련된 문제를 찾을 수 없었습니다. 그러나 wireshark / twireshark 힌트가 좋습니다.
Robert Munteanu

@Robert Munteanu이 응용 프로그램을 빌드하는 경우 이것은 stackoverflow에 대한 질문입니다. 소켓을 너무 많이 열지 마십시오.
Rook

Rook : 나는 이것을 코드 단위로 찾는 것을 포기하고 그것을 sysadmin으로 추적하려고했습니다. 그래서 SF에 게시했습니다. 그리고 네, 어떻게 든 너무 많은 소켓이 열려 있다는 것을 알고 있습니다. 그러나 어디로 가는지에 대한 단서가 없습니다 ...
Robert Munteanu

@Robert Munteanu 소켓 생성시 중단 점을 설정하고 해당 지점의 스택 추적 및 메모리를 확인해야합니다. 나는 당신이 무한 루프에 빠지고 있다고 생각합니다. 코드가 이와 같은 복잡한 문제에 대한 최선의 접근 방법이 될지라도 모든 변수와 단계를 볼 수 있습니다.
Rook

불행히도 이것은 항상 같은 것은 아니지만 20 대의 서버 중 하나에서 프로덕션 환경에서만, 일주일에 두 번 무작위로 발생합니다. 그렇지 않으면 손가락을 대는 것이 다소 간단했을 것입니다. 현재 Byteman ( jboss.org/byteman )을 사용하여 소켓 생성 / 바인드 / 연결 / 닫기 호출을 추적하고 있습니다. 바라건대 무언가가 나올 것입니다.
Robert Munteanu
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.