2010-02-18 2 views
37

나는 리눅스에서 UDP 소켓을 열고 메시지를 기다리는 자바 애플리케이션을 가지고있다.Linux UDP 버퍼 사용 가능한 공간을 모니터링하는 방법은 무엇입니까?

과부하로 몇 시간이 지나면 패킷 손실이 발생합니다. 즉, 패킷은 커널에서 수신하지만 내 응용 프로그램에서는 수신하지 않습니다 (스니퍼에서 손실 된 패킷을 볼 수 있습니다. netstat에서 UDP 패킷이 손실 된 것을 볼 수 있습니다. 앱 로그에서 해당 패킷을 볼 수 없음).

우리는 소켓 버퍼를 확대하려고 시도했지만이 방법은 도움이되지 않았습니다. 이전에 패킷을 잃어 버렸지 만 그게 전부입니다.

디버깅을 위해 주어진 시간에 OS udp 버퍼가 얼마나 충만했는지 알고 싶습니다. 봤지만 아무 것도 못 찾았 어. 나 좀 도와 줄 수있어?

P. 얘들 아, 나는 UDP가 신뢰할 수 없다는 것을 알고있다. 그러나 - 내 컴퓨터는 모든 UDP 메시지를 수신하지만 내 앱은 그 중 일부를 사용할 수 없습니다. 내 애플 리케이션을 최대로 최적화하고 싶다. 그것이 그 질문의 이유이다. 감사.

답변

27

리눅스는 열려있는 모든 UDP 소켓 (각각 IPv4 및 IPv6)을 나열하는 /proc/net/udp/proc/net/udp6 파일을 제공합니다. 두 경우 모두 tx_queuerx_queue 열은 발신 및 수신 대기열을 바이트로 표시합니다.

모든 것이 예상대로 작동하면 일반적으로 두 열에서 0 이외의 값이 표시되지 않습니다. 응용 프로그램이 네트워크를 통해 전송 된 패킷을 생성하고 네트워크에서 패킷이 도착하자마자 응용 프로그램이 깨어나 그들을받을 것입니다 (recv 호출 즉시 반환). 응용 프로그램이 소켓을 열었지만 recv을 호출하지 않거나 데이터를 충분히 빠르게 처리하지 않는 경우 rx_queue이 표시 될 수 있습니다.

+2

감사합니다 rx_queue, 나머지는 - 업데이트 참조) –

+1

@ Julia 누가 사용할 프로토콜을 선택할 수 있다고 말합니까? 어쩌면 그는 기존 클라이언트를 지원하기 위해 UDP 기반 프로토콜을 구현하고있을 수도 있습니다. – steffen

+2

Poster는 UDP 통계 모니터링에 대해 알고 싶어하며 어떤 프로토콜을 사용할 지에 대해서는 의견이 없습니다. 먼저 레이어에서 손실이 발생하는 곳을 확인함으로써 수정 작업을 수행 할 수 있습니다. – RickS

-1

과정은 간단하다

원한다면
  1. 애플리케이션 프로세스를 일시 중지.

  2. UDP 소켓을 엽니 다. 필요한 경우 /proc/<PID>/fd을 사용하여 실행중인 프로세스에서 문제를 일으킬 수 있습니다. 또는이 코드를 응용 프로그램 자체에 추가하고 신호를 보낼 수 있습니다. 물론 이미 소켓이 열려있을 것입니다.

  3. 을 가능한 한 신속하게 호출하십시오.

  4. 얼마나 많은 패킷/바이트가 있는지 계산하십시오.

이 현재 버퍼 데이터 그램을 폐기하지만, 그 응용 프로그램을 중단하는 경우, 응용 프로그램이 이미 깨진했다.

+0

나는이 대답을 downvote하려고했지만, 두 번째 생각에 그것은 재미있다. 난 아무도 이것을 구현하려하지 않았 으면 좋겠어 :) – Navin

4

rx_queue는 주어진 순간의 대기열 길이를 알려주지 만 대기열이 얼마나 가득 찼는 지, 즉 최고점을 알려주지 않습니다. 이 값을 지속적으로 모니터링 할 방법이 없으며이를 프로그래밍 방식으로 얻을 방법이 없습니다 (How do I get amount of queued data for UDP socket? 참조).

대기열 길이를 모니터링하는 것이 상상할 수있는 유일한 방법은 대기열을 자신의 프로그램으로 이동하는 것입니다. 즉, 두 개의 스레드를 시작하십시오. 하나는 가능한 빨리 소켓을 읽고 데이터 그램을 대기열로 덤프합니다. 다른 하나는이 큐에서 당겨서 패킷을 처리하는 프로그램입니다. 이것은 물론 각 스레드가 별도의 CPU에 있음을 보장 할 수 있다고 가정합니다. 이제 자신의 큐의 길이를 모니터하고 하이 워터 마크를 추적 할 수 있습니다.

46

UDP는 완벽하게 실행 가능한 프로토콜입니다. 올바른 작업에 적합한 도구와 동일한 예입니다!

UDP 데이터 그램을 기다리는 프로그램이 있고 다른 프로그램을 기다리기 위해 반환하기 전에 처리하기 위해 프로그램을 종료 한 경우 경과 된 처리 시간은 항상 최악의 데이터 그램 도착 속도보다 빠를 필요가 있습니다. 그렇지 않으면 UDP 소켓 수신 대기열이 채우기 시작합니다.

이것은 짧은 버스트에 대해 허용 될 수 있습니다. 대기열은 수행 할 작업을 완료 할 때까지 데이터 그램 대기열을 만듭니다. 그러나 평균 도착률로 인해 정기적으로 대기열에 백 로그가 발생하면 프로그램을 다시 설계해야합니다. 여기에는 두 가지 주요 선택 사항이 있습니다 : 숙련 된 프로그래밍 기술을 통해 경과 된 처리 시간 줄이기 및/또는 프로그램을 멀티 스레드하십시오. 프로그램의 여러 인스턴스에서로드 균형 조정을 사용할 수도 있습니다.

앞서 언급 한 것처럼 Linux에서는 proc 파일 시스템을 검사하여 UDP가 무엇인지에 대한 상태를 얻을 수 있습니다. 나는 /proc/net/udp 노드를 cat 예를 들어, 나는 이런 식으로 뭔가 얻을 :

$ 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   

이에서를, I는 사용자 ID 1006가 소유 한 소켓, 포트 0x231D (8989)를 수신하는 것을 볼 수 있고,받을 수 대기열은 약 128KB입니다. 128KB가 시스템의 최대 크기이기 때문에 도착하는 데이터 그램을 따라 잡을 때 내 프로그램이 약해진다는 것을 알 수 있습니다. 지금까지 2237 개의 드롭이 있었는데, 이는 UDP 레이어가 소켓 큐에 더 이상 데이터 그램을 넣을 수 없으며 드롭해야 함을 의미합니다.

시간이 지남에 따라 프로그램의 동작을 볼 수 있습니다. 사용 : netstat 명령이 같은 일에 대해 않는 것이

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

참고 : 내 위니 프로그램 netstat -c --udp -an

내 솔루션은 멀티 스레드 될 것입니다.

건배!

+0

시스템의 최대 udp 대기열 크기가 128KB임을 어떻게 알았습니까? – Chinaxing

+2

@Chinaxing'cat/proc/sys/net/core/rmem_max' – wakjah

관련 문제