丢消息怎么办?

这得从 java 的 java.net.SocketException 异常说起。简单点说就是当网络发送方发送一堆数据,然后调用 close 关闭连接之后。这些发送的数据都在接收者的缓存里,接收者如果调用 read 方法仍旧能从缓存中读取这些数据,尽管对方已经关闭了连接。但是当接收者尝试发送数据时,由于此时连接已关闭,所以会发生异常,这个很好理解。不过需要注意的是,当发生 SocketException 后,原本缓存区中数据也作废了,此时接收者再次调用 read 方法去读取缓存中的数据,就会报 Software caused connection abort: recv failed 错误。

通过抓包得知,ActiveMQ 会每隔10秒发送一个心跳包,这个心跳包是服务器发送给客户端的,用来判断客户端死没死。如果你看过上面第一条,就会知道非持久化消息堆积到一定程度会写到文件里,这个写的过程会阻塞所有动作,而且会持续20到30秒,并且随着内存的增大而增大。当客户端发完消息调用 connection.close()时,会期待服务器对于关闭连接的回答,如果超过15秒没回答就直接调用 socket 层的 close 关闭 tcp 连接了。这时客户端发出的消息其实还在服务器的缓存里等待处理,不过由于服务器心跳包的设置,导致发生了 java.net.SocketException 异常,把缓存里的数据作废了,没处理的消息全部丢失。

解决方案:用持久化消息,或者非持久化消息及时处理不要堆积,或者启动事务,启动事务后, commit()方法会负责任的等待服务器的返回,也就不会关闭连接导致消息丢失了。

回复

我来回复
  • 暂无回复内容

免费咨询
免费咨询
扫码关注
扫码关注
联系站长

站长Johngo!

大数据和算法重度研究者!

持续产出大数据、算法、LeetCode干货,以及业界好资源!

2022012703491714

微信来撩,免费咨询:xiaozhu_tec

分享本页
返回顶部