Java 서버 응용 프로그램이 있습니다.
while(true)
{
serverSocket.receive(receivePacket);
process(receivePacket);
serverSocket.send(sendPacket);
try {
Thread.sleep(10000); // sleep for 10s
} catch (InterruptedException e) {
e.printStackTrace();
}
}
10초당 1개의 UDP 패킷을 수신하고 처리합니다.
10개의 UDP 패킷을 서버로 보내면 1개의 패킷이 처리된 후 10초 동안 Sleep 상태가 됩니다. 그래서 100초 후에 10번째 패킷의 응답을 받습니다.
이렇게 하면 서버 1은 CentOS 버전 6.4(최종)를 실행하게 됩니다.
Server 1: cat /proc/net/udp
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode ref pointer drops
110: 00000000:10AE 00000000:0000 07 00000000:00000000 00:00000000 00000000 0 0 85635445 2 ffff880836e6d100 0
111: 00000000:10AF 00000000:0000 07 00000000:00000000 00:00000000 00000000 0 0 85635446 2 ffff88083913a1c0 0
115: 00000000:15B3 00000000:0000 07 00000000:00004FC8 00:00000000 00000000 0 0 390649369 2 ffff880434ae7440 0
117: 02FE6341:0035 00000000:0000 07 00000000:00000000 00:00000000 00000000 0 0 353480394 2 ffff8808367f9040 0
서버 2에서 동일한 작업을 수행하면 다음과 같습니다.
Server 2: cat /proc/net/udp
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode ref pointer drops
4: FCA9C11F:C36F 8C719AC6:0035 01 00000000:00000000 00:00000000 00000000 0 0 2983494501 2 ffff880169aff4c0 0
5: FCA9C11F:D3F0 8C719AC6:0035 01 00000000:00000000 00:00000000 00000000 0 0 2983494485 2 ffff8801b9bbedc0 0
16: 7A52BB59:007B 00000000:0000 07 00000000:00000000 00:00000000 00000000 38 0 2438608536 2 ffff8807656764c0 0
16: A2EE0D55:007B 00000000:0000 07 00000000:00000000 00:00000000 00000000 38 0 2438608045 2 ffff88077ccdd7c0 0
16: A58F466D:007B 00000000:0000 07 00000000:00000000 00:00000000 00000000 38 0 2438607809 2 ffff8801129f6240 0
둘 다 Centos 서버이며 애플리케이션이 서버로 들어오는 데이터보다 느리게 패킷을 처리하기 때문에 server1의 rx_queue 버퍼가 증가하고 있음을 알 수 있습니다.
나는 server2에서 똑같은 일을 했지만 rx_queue는 server2에서 증가하지 않습니다. 내가 뭔가 잘못했거나 잘못 이해했나요?
답변1
Ubuntu 18.04 LTS(커널 4.15.0-38)에서도 비슷한 문제가 발생합니다. 하지만 내 Debian 9.5(커널 4.9.110-3) 컴퓨터에서는 이런 일이 발생하지 않습니다. 최신 커널의 버그인 것 같나요?
문제를 재현하는 쉬운 방법은 netcat을 사용하는 것입니다. 클라이언트와 서버는 로컬이거나 다른 시스템에 있을 수 있습니다.
- 터미널에서 netcat 서버 실행: nc -u -l 1234
- 다른 터미널에서 netcat 클라이언트 실행: nc -u 127.0.0.1 1234
- 클라이언트에 문자 메시지 "a"를 입력하고 Enter 키를 누릅니다.
- 세 번째 터미널에서 recv -q 길이를 확인하세요. netstat -plan regex 1234
Ubuntu에서는 netcat이 소켓에서 메시지를 읽고 인쇄했더라도 수신 udp 소켓에는 비어 있지 않은 recv-q(2바이트 메시지의 경우 768바이트)가 있습니다. 나는 recv-q가 약 52k까지 계속 증가한 다음 다시 0으로 재설정된다는 것을 발견했습니다.
데비안에서는 UDP 소켓이 패킷을 수신할 수 있는 것보다 빠르게 소진될 때마다 recv-q는 항상 0입니다.
또한 다음 커널 버그 보고서도 발견했습니다./proc/net/udp의 UDP rx_queue가 올바르게 계산되지 않습니다.
답변2
StackExchange의 이 부분을 잘 알지 못하는 점 양해부탁드리며, 댓글보다는 답변을 올려드립니다.
Ubuntu 18.04 LTS
(kernel) 에서 @Neopallium과 동일한 문제가 발생했습니다 4.15.0-36
. 전체 테스트에서 UDP 데이터그램 백로그 없이 UDP 서버 애플리케이션 (별도 )을 수동으로 설정 net.core.rmem_max=26214400
하고 실행하는 테스트에서 카운터가 약 또는 까지 올라가다 가 갑자기 .로 재설정되는 것을 확인했습니다 . 이는 카운터가 재설정되기까지 걸리는 대략적인 시간입니다. 및 의 기본값에 따라 재설정되기 전에 @Neopallium이 자신의 카운터가 약 (대략)까지 올라가는 것을 본 것은 놀라운 일이 아닙니다.net.core.rmem_default=26214400
25MB
rx_queue
00000000:006xxxxx
~6MB+
0
1/4
net.core.rmem_max
Ubuntu 18.04 LTS
net.core.rmem_default
net.core.rmem_max
212992
52k
1/4
212k
/proc/net/udp
다음은 재설정 지점에 접근할 때 애플리케이션의 출력입니다.
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode ref pointer drops
1256: 00000000:7530 00000000:0000 07 00000000:00632240 00:00000000 00000000 0 0 94457826 2 0000000000000000 0
다음은 지난 45분 동안의 Grafana 소켓 그래프 스크린샷입니다.