我有一个第三方组件,它试图在特定情况下发送太多的UDP消息到太多的独立地址。 这是在软件启动并且情况是暂时的情况下发生的。 实际上,我不确定这是消息的简单数量,还是每个消息到单独的IP地址的事实。
无论如何,更改底层协议或有问题的组件不是一个选项,所以我正在寻找一个解决方法。 StackTrace看起来像这样:
java.io.IOException: No buffer space available at java.net.PlainDatagramSocketImpl.send(Native Method) at java.net.DatagramSocket.send(DatagramSocket.java:612)
Java版本1.6.0_13和1.6.0_10以及linux版本Ubuntu 9.04和RHEL 4.6出现此问题(至less)。
是否有任何Java系统属性或linuxconfiguration调整可能有帮助?
如何在java中获取目录的最后修改date和时间
以编程方式确定我的盒子上安装了哪些JDK / JRE
redirectpipe道和java的input
正确的方式来build立“生活”的目录结构后maven构build?
致命错误在windows 10机器上最新版本的Java上崩溃
检测由于名称不正确而无法创build文件的情况
飞路3.1迁移校验和不匹配。 校验和的计算取决于平台
限制JVM使用的线程数
使用bash脚本/ grep / sed来replace文件名本身的类名
jenkins发现无法findssh密钥
我终于确定了这个问题。 由于Java IOException是“没有可用的缓冲区空间”,所以Java IOException会引起误解,但根本问题是本地ARP表已被填充。 在linux上,默认的ARP表查找是1024(files / proc / sys / net / ipv4 / neigh / default / gc_thresh1,/ proc / sys / net / ipv4 / neigh / default / gc_thresh2,/ proc / sys / net / ipv4 /嘶/默认/ gc_thresh3)。
在我的情况(我假设你的情况)发生了什么事情是,你的Java代码是从一个IP地址发出的UDP数据包在同一个子网作为您的目标地址。 在这种情况下,linux机器将执行ARP查找以将IP地址转换为硬件MAC地址。 由于您正在将数据包爆炸到许多不同的IP,所以本地ARP表快速填充,命中1024,这是抛出Java异常的时候。
解决方法很简单,可以通过编辑前面提到的文件来增加限制,也可以将服务器移动到与目标地址不同的子网中,这会导致linux机器不再执行邻居ARP查找(取而代之的是由路由器在网络上)。
在发送大量消息时,特别是在linux中的千兆以太网上,内核的参数通常不是最优的。 您可以通过以下方式增加linux内核缓冲区大小:
echo 1048576 > /proc/sys/net/core/wmem_max echo 1048576 > /proc/sys/net/core/wmem_default echo 1048576 > /proc/sys/net/core/rmem_max echo 1048576 > /proc/sys/net/core/rmem_default
作为根。
或者使用sysctl
sysctl -w net.core.rmem_max=8388608
有大量的网络选项
请参阅IBM提供的linux网络调整和更多调整信息
可能有点复杂,但据我所知,Java使用SPI 1模式的网络子库。 这使您可以更改用于各种网络 *** 作的实现。 如果你使用OpenJDK,那么你可以获得一些提示,如何以及如何包装你的实现。 然后,在你的实现中,你可以减慢一些睡眠的I / O。
或者,只是为了好玩,您可以使用您的修改实现覆盖默认的DatagramSocket。 拥有相同的软件包名称,正如我所知 – 它将优先于默认的JRE类。 至少这个方法在我的一些错误的第三方库上工作。
编辑:
1服务提供者接口是一种在API中分离客户端和服务代码的方法。 这种分离允许不同的客户和不同的提供者实现 通常可以从名称以Impl结尾来识别,就像在你的栈跟踪中一样java.net.PlainDatagramSocketImpl是DatagramSocket是客户端API的提供者实现。
你评论说你不想让整个过程变慢。 有几种方法可以避免这种情况,例如,测量代码中的时间,并在第一个传入方法调用开始的1-2分钟内减慢通信速度。 那么你可以跳过睡觉。
另一个选择是识别图书馆中的行为不端行为,JAD并修复它。 然后替换库中的原始类文件。
我目前也看到这个问题以及Debian和RHEL。 在这一点上,我相信我已经把它隔离到NIC和/或NIC驱动程序。 你有什么硬件配置也会出现这个问题? 这似乎只发生在我们最近收购的拥有broadcom公司NetXtreme II BCM5708千兆以太网NIC的新Dell PowerEdge服务器上。
我也可以确认,这是在短时间内快速生成出站UDP数据包到许多不同的IP地址。 我试图写一个简单的Java应用程序,可以重现它(因为我们正在与snmp4j发生)。
编辑
看看我的答案: Java IOException:在linux上发送UDP数据包时没有可用的缓冲区空间
我有这个错误,当我试图在两个本地JVM使用WIFI连接到数据库运行一致性集群。如果我运行它使用以太网 – 它运行良好。
总结以上是内存溢出为你收集整理的Java IOException:在Linux上发送UDP数据包时没有可用的缓冲区空间全部内容,希望文章能够帮你解决Java IOException:在Linux上发送UDP数据包时没有可用的缓冲区空间所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)