lev*_*ver 10 epoll stomp netty spring-websocket reactor-netty
所以我们在后端使用Spring websocket STOMP + RabbitMQ,我们遇到了打开文件描述符的麻烦.经过一段时间后,我们达到了服务器的限制,服务器不接受任何连接,包括websockets和API端点.
2018-09-14 18:04:13.605  INFO 1288 --- [MessageBroker-1] 
o.s.w.s.c.WebSocketMessageBrokerStats    : WebSocketSession[2 current WS(2)- 
HttpStream(0)-HttpPoll(0), 1159 total, 0 closed abnormally (0 connect 
failure, 0 send limit, 63 transport error)], stompSubProtocol[processed 
CONNECT(1014)-CONNECTED(1004)-DISCONNECT(0)], stompBrokerRelay[9 sessions, 
127.0.0.1:61613 (available), processed CONNECT(1015)-CONNECTED(1005)- 
DISCONNECT(1011)], inboundChannel[pool size = 2, active threads = 2, queued 
tasks = 2, completed tasks = 12287], outboundChannelpool size = 0, active 
threads = 0, queued tasks = 0, completed tasks = 4225], sockJsScheduler[pool 
size = 1, active threads = 1, queued tasks = 3, completed tasks = 683]
我们得到以下例外情况:
2018-09-14 18:04:13.761 ERROR 1288 --- [http-nio-127.0.0.1-8443-Acceptor-0] 
org.apache.tomcat.util.net.NioEndpoint   : Socket accept failed
java.io.IOException: Too many open files
    at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method)
    at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:422)
    at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:250)
    at org.apache.tomcat.util.net.NioEndpoint$Acceptor.run(NioEndpoint.java:455)
    at java.lang.Thread.run(Thread.java:748)
linux的默认文件描述符限制是1024,即使我们将其增加到65000,它也会在某个时刻达到极限,无论如何.
我们希望从后端方面解决这个问题,最好是在没有任何解决方法的情况下解决这个问题.有任何想法吗?
UPDATE
RabbitMQ和应用程序驻留在不同的服务器上.实际上,RabbitMQ适用于Compose.我们可以通过不从客户端发送DISCONNECT消息来重现此问题.
更新2
今天我意识到无论发生什么,所有的文件描述符和java线程都会一直存在.我已经实现了一个解决方法,包括从Spring 发送DISCONNECT消息并关闭WebSocketSession对象而没有更改.我通过检查以下链接实现了这些:
作为旁注,服务器端发送如下消息:
 simpMessagingTemplate.convertAndSend("/queue/" + sessionId, payload).通过这种方式,我们确保每个客户端都获得相关的相应消息sessionId.
这是某种错误吗?为什么不关闭文件描述符?之前没有人遇到过这个问题吗?
更新3
每次关闭套接字时,我都会看到以下异常.无论是如何关闭它,无论是来自客户端的DISCONNECT消息还是webSocketSession.close()来自服务器的代码.
[reactor-tcp-io-66] o.s.m.s.s.StompBrokerRelayMessageHandler : TCP connection failure in session 45r7i9u3: Transport failure: epoll_ctl(..) failed: No such file or directory
io.netty.channel.unix.Errors$NativeIoException: epoll_ctl(..) failed: No such file or directory
at io.netty.channel.unix.Errors.newIOException(Errors.java:122)
at io.netty.channel.epoll.Native.epollCtlMod(Native.java:134)
at io.netty.channel.epoll.EpollEventLoop.modify(EpollEventLoop.java:186)
at io.netty.channel.epoll.AbstractEpollChannel.modifyEvents(AbstractEpollChannel.java:272)
at io.netty.channel.epoll.AbstractEpollChannel.clearFlag(AbstractEpollChannel.java:125)
at io.netty.channel.epoll.AbstractEpollChannel$AbstractEpollUnsafe.clearEpollRdHup(AbstractEpollChannel.java:450)
at io.netty.channel.epoll.AbstractEpollChannel$AbstractEpollUnsafe.epollRdHupReady(AbstractEpollChannel.java:442)
at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:417)
at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:310)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884)
at java.lang.Thread.run(Thread.java:748)
所以我将日志级别更改为,TRACE并且我看到websockets确实正在关闭,但是立即抛出这些异常.所以在这一点上,我对这个例外非常怀疑.挂起的java线程的数量总是与websockets的数量并行,即创建400个websockets总是在主进程中结束~400个挂起的线程.并且永远不会释放内存资源.
谷歌搜索此异常仅以下面的4个结果结束:(其余的是其他例外)
将netty库更新到最新版本(4.1.29.Final)也不起作用,所以我相应地更改了问题的标签.我也在考虑创建一个问题netty.我已经尝试了很多东西,并在应用程序级别上进行了多次实验,但似乎没有任何工作.在这一点上,我对任何想法持开放态度.
如果您总是使用try-with-resource或在 finally 块中关闭打开的文件,则您可能确实超出了文件描述符限制,并且需要另一台主机来接受您的请求。为此,您需要扩展应用程序并对其进行负载平衡。我建议你在集群中部署rabbitmq来解决这个问题。
在某些情况下,RabbitMQ 会忽略您的文件描述符限制。
| 归档时间: | 
 | 
| 查看次数: | 1387 次 | 
| 最近记录: |