一个Java UDP套接字可以处理多少个请求? [英] How many requests can a java UDP socket handle?

查看:186
本文介绍了一个Java UDP套接字可以处理多少个请求?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要构建一个UDP服务器,该服务器每秒可以处理约10_000个请求.从下面的代码开始,以测试Java套接字是否可以处理这些数量的请求.

我正在向服务器轰炸一分钟,发出约9000个请求,

Total number of requests sent from the client : 596951

在tcp转储中,我看到了

90640 packets captured
175182 packets received by filter
84542 packets dropped by kernel

UDP服务器代码:

try (DatagramSocket socket = new DatagramSocket(port)) {
            System.out.println("Udp Server started at port :" + port);


            while (true) {
                byte[] buffer = new byte[1024];
                DatagramPacket incomingDatagramPacket = new DatagramPacket(buffer, buffer.length);
                try {
                    socket.receive(incomingDatagramPacket);
                    LinkedTransferQueue.add(incomingDatagramPacket);
                } catch (IOException e) {
                    e.printStackTrace();
                    continue;

                }


            }

        } catch (SocketException e) {
            e.printStackTrace();
        }

内核在程序中丢弃数据包的可能原因是什么? 这个简单吗?

如何减少呢?还有其他实现吗?

通过此链接,从注释,即使在网络与Java socket.recieve方法之间,UDP协议的数据包丢失也总是会发生.

注意:必须弄清楚捕获到的tcpdump数据包中的异常情况,但是丢弃的数据包数量还是很多.

tcpdump中的异常是缺少缓冲区空间,为了知道接收到的数据包数量,我正在使用 iptraf-ng 给出每个端口接收到的数据包数量:)

解决方案

多线程

您的代码示例在接收到数据包后不执行任何操作.如果真是这样,多线程无法为您提供帮助.

但是,如果这仅仅是为了进行测试,而您的实际应用程序需要对接收到的数据包执行某些操作,则需要将数据包推送到另一个Thread(或其中的一个池),然后立即返回侦听下一个数据包

基本上,您需要最小化两次调用socket.receive()的时间.

注意:这不是此情况下唯一可用的多线程模型.

缓冲区大小

使用socket.setReceiveBufferSize增大缓冲区大小,该大小映射到SO_RCVBUF:

增加SO_RCVBUF可能允许网络实现在数据包到达速度比使用receive(DatagramPacket)接收数据包时快的情况下缓冲多个数据包.

但是,这只是提示:

网络实现使用SO_RCVBUF选项作为提示来调整基础网络I/O缓冲区的大小.

如果设置允许,您也可以直接进入操作系统并更改缓冲区的大小.

Irelevant

注意:仅在不确定数据包大小小于1024字节时,才阅读此内容.

对于普通数据包,您的数据包缓冲区大小似乎较小,这可能会导致错误,原因是:如果数据包大于缓冲区,则不会出现错误,它将忽略溢出字节.

其他多线程模型

注意:这是个主意,我不知道它是否真的有效.

3个线程:

  • 线程A:处理数据包
  • 线程B1:接收数据包
  • 线程B2:接收数据包

初始化:

  • 原子计数器设置为0
  • B1正在接收,B2正在等待.

B1循环时:

  • 计数器> 0等待
  • 计数器+ = 1
  • 收到数据包
  • 计数器-= 1
  • 唤醒B2
  • 将数据包推送到A的队列

与B2相同.

这是线程图(已接收到数据包的线):

B1 [--------|---]    [--------|---]
B2          [--------|---]    [--------|---]

I need to build a UDP server which can handle ~10_000 requests/sec. Started with below code, to test whether a java socket can handle those number of requests.

I am bombarding the server for a minute with ~9000 requests,

Total number of requests sent from the client : 596951

and in the tcp dump I see

90640 packets captured
175182 packets received by filter
84542 packets dropped by kernel

UDP Server code :

try (DatagramSocket socket = new DatagramSocket(port)) {
            System.out.println("Udp Server started at port :" + port);


            while (true) {
                byte[] buffer = new byte[1024];
                DatagramPacket incomingDatagramPacket = new DatagramPacket(buffer, buffer.length);
                try {
                    socket.receive(incomingDatagramPacket);
                    LinkedTransferQueue.add(incomingDatagramPacket);
                } catch (IOException e) {
                    e.printStackTrace();
                    continue;

                }


            }

        } catch (SocketException e) {
            e.printStackTrace();
        }

What is the the probable cause kernel dropping the packets in program this simple ?

How to reduce it ? Any other implementation ?

From this link, reading from the comments,lose of packets for UDP protocol can always happen even between network to java socket.recieve method.

Note: Have to figure out regarding anomalies in the tcpdump packets captured, but there is quite number of packets dropped.

The anomalies in the tcpdump is the lack of buffer space, In order to know the number of packets received , I am using the iptraf-ng which gives the number of packets received per port :)

解决方案

Mutli-threading

Your code sample does nothing after the a packet is received. If that is the case, multi-threading cant help you.

However if that's just for testing and your actual application needs to do something with the received packet, you need to push the packet to another Thread (or a pool of them) and go immediately back to listening for the next packet.

Basically you need to minimize the time between two calls of the socket.receive().

Note: this is not the only mutli-threading model available for this case.

Buffer size

Increase the buffer size with socket.setReceiveBufferSize which maps to the SO_RCVBUF:

Increasing SO_RCVBUF may allow the network implementation to buffer multiple packets when packets arrive faster than are being received using receive(DatagramPacket).

However, this is just a hint:

The SO_RCVBUF option is used by the the network implementation as a hint to size the underlying network I/O buffers.

You could also, if your setup allows it, go directly to the OS and change the size of the buffer.

Irrelevant

Note: Read this only if you are not sure that the packet size is less than 1024 bytes.

Your packet buffer size seems low for generic packets, which can lead to bugs because: If a packet is larger than your buffer there will be no error, it will just ignore the overflowing bytes.

EDIT:

Other Multi-threading model

Note: This is an idea, I don't know if it actually works.

3 Threads:

  • Thread A: handling packets
  • Thread B1: receive packets
  • Thread B2: receive packets

Init:

  • Atomic counter set to 0
  • B1 is receiving, B2 is waiting.

While loop of the B1:

  • while counter > 0 wait
  • counter += 1
  • received the packet
  • counter -= 1
  • wake up the B2
  • push the packet to A's queue

Same for B2.

This the threads diagram (line where the packet has been received):

B1 [--------|---]    [--------|---]
B2          [--------|---]    [--------|---]

这篇关于一个Java UDP套接字可以处理多少个请求?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆