2017-09-03 167 views
8

我需要建立一个UDP服务器,它可以处理〜10_000个请求/秒。从下面的代码开始,测试一个java套接字是否可以处理这些数量的请求。java UDP套接字可以处理多少个请求?

我轰击服务器在〜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(); 
     } 

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

如何减少?任何其他实现?

从这个link,从评论阅读,失去UDP协议到Java socket.recieve方法甚至网络之间可以随时发生的数据包。

注意:必须弄清楚捕获到的tcpdump数据包中的异常情况,但丢弃的数据包数量相当多。

了tcpdump的异常是lack of buffer space,为了知道数据包的数量收到,我现在用的是iptraf-ng这给每个端口:)

+4

可能的原因是套接字接收缓冲区填满了,因为没有足够快地读取它。尝试减少'println()'调用,例如每百个数据报一个。 – EJP

+0

@EJP我已经做到了,但仍然有丢包 –

+0

使用多线程来同时处理多个数据包。您也可以在您的以太网接口和交换机上相应的端口上激活流量控制(但丢失数据包是一种被告知拥塞的方式,因此激活流量控制可能会产生不良的副作用)。 –

回答

2

辑阵线程接收的数据包的数量

收到数据包后,您的代码示例不执行任何操作。如果是这样,多线程不能帮助你。但是,如果这仅仅用于测试,并且实际应用程序需要对接收到的数据包执行某些操作,则需要将数据包推送到另一个Thread(或其中的一个池),然后立即返回以侦听下一个数据包。

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

注意:这是而不是这种情况下唯一可用的多线程模型。

缓冲区大小

增加与socket.setReceiveBufferSize缓冲区大小将映射到SO_RCVBUF:

增加SO_RCVBUF可以允许网络实现,以缓冲多个数据包时,包到达比正在接收更快使用receive(DatagramPacket)。

然而,这仅仅是一个暗示

的SO_RCVBUF选项用于通过网络实现为暗示尺寸底层网络I/O缓冲区。

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

无关

注:阅读本只有当你不能确定包的大小小于1024个字节。

对于通用数据包,您的数据包缓冲区大小似乎很低,这可能会导致错误,因为:如果数据包大于缓冲区,则不会有错误,它将忽略溢出字节。

编辑:

等多线程模型

注:这是一个想法,我不知道它的实际工作。

3个线程:

  • 线程A:在处理分组
  • 螺纹B1:接收分组
  • 螺纹B2:接收分组

初始化:

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

虽然B1的环:

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

相同的B2。

这线程图(线在数据包已经收到):

B1 [--------|---] [--------|---] 
B2   [--------|---] [--------|---] 
+0

我已经更新了代码,我已经按照注释中的建议更改了os缓冲区大小,仍然有10%的数据包丢失:( –

+0

你有没有尝试其他机器?也有可能是网卡是瓶颈,你不能改善它... – MaanooAk

+0

如果你有兴趣,我添加了其他多线程模型,它只是一个想法,我你绝望,你可以测试它...没有承诺 – MaanooAk

0

而不是使用线程,您可以点击这里使用的API NIO2使用AsynchronousDatagramChannel的可能性。

帮助链接: https://www.ibm.com/developerworks/library/j-nio2-1/index.html

+1

AsynchronousDatagramChannel类已从java中删除8 http://bugs.java.com/view_bug.do?bug_id=6993126 –

+0

@ forum.test17这是不正确的,这不是bug报告所说的。它在Java 7发布之前已经从Java 7中撤销了,现在它已经存在于Java 8中了。请参阅Javadoc。 – EJP

0

一个缺点是它不与TCP UDP协议的mcast_recv_buf_sizeucast_recv_buf_size提供了可靠的传输保证配置属性用于指定接收缓冲区的数量。

它取决于您用来运行程序的操作系统。缓冲区大小不同的操作系统有:

<table sytle="width:100% border:1px solid black"> 
 
<tr> 
 
<th><b>Operating System</b></th> \t 
 
<th><b>Default Max UDP Buffer (in bytes)</b></th> 
 
</tr> 
 
<tr><td>Linux</td> \t      <td>131071</td></tr> 
 
<tr><td>Windows</td> \t   <td>No known limit</td></tr> 
 
<tr><td>Solaris</td> \t      <td>262144</td></tr> 
 
<tr><td>FreeBSD</td> \t    <td>262144</td></tr> 
 
<tr><td>AIX</td>      <td>1048576</td></tr> 
 
</table>

所以UDP负载处理以及取决于机器的操作系统配置。