Открытые соединения через Spring Websocket STOMP приводят к смерти нашего сервера - PullRequest
0 голосов
/ 19 сентября 2018

Таким образом, мы используем Spring websocket STOMP + RabbitMQ на внутренней стороне, и у нас возникают проблемы с дескрипторами открытых файлов.Через некоторое время мы достигли лимита на сервере, и сервер не принимает никаких соединений, включая веб-сокеты и конечные точки 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, он в какой-то момент достигнет предела, несмотря ни на что.

Мы хотим решить эту проблему иззадняя сторона и желательно к весне без каких-либо обходных путей.Есть идеи?

ОБНОВЛЕНИЕ

RabbitMQ и приложение находятся на разных серверах.На самом деле RabbitMQ работает на Compose.Мы можем воспроизвести эту проблему, не отправляя DISCONNECT сообщений от клиента.

ОБНОВЛЕНИЕ 2

Сегодня я понял, что все файловые дескрипторы и JavaНити всегда остаются там, независимо от того, что происходит.Я реализовал обходной путь, который включает отправку DISCONNECT сообщений из Spring и закрытие объектов 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 и я вижу, что веб-розетки действительно закрыты, но сразу же создаются эти исключения.Поэтому на данный момент я действительно с подозрением отношусь к этому исключениюКоличество зависших java-потоков всегда идет рука об руку с количеством веб-сокетов, т.е. создание 400 веб-сокетов всегда приводит к ~ 400 зависшим потокам в основном процессе.И ресурсы памяти никогда не высвобождаются.

Поиск в Google этого исключения заканчивается только следующими 4 результатами: (Остальное - другие исключения)

Обновление библиотеки netty до последней версии (4.1.29.Final) didnтоже не работает, поэтому я изменил метки вопроса соответственно.Я также рассматриваю возможность создания проблемы против netty.Я много чего перепробовал и несколько раз экспериментировал на уровне приложений, но, похоже, ничего не получалось.Я открыт для любых идей на данный момент.

Ответы [ 2 ]

0 голосов
/ 24 сентября 2018

Клиентская библиотека Java RabbitMQ время от времени возникала проблема с управлением дескрипторами открытых файлов.Это редко плохо, но есть ошибки, например: ChannelManager line 218 .

Вы хотите попробовать несколько разных версий клиентской библиотеки Java, так как это проблема на стороне клиента.В одной версии у меня были тысячи потоков Java, порожденных из-за ошибки в создании соединения (не уверен, какая версия была затронута, я заметил это с помощью FlightRecorder и перешел в раздел блокировок, все потоки ожидали получения класса соединения RabbitMQ (?)замок).

0 голосов
/ 22 сентября 2018

Если вы всегда используете try-with-resource или закрываете свои открытые файлы в блоке finally, возможно, вы действительно превысили лимит дескриптора файла и вам нужен другой хост, чтобы принимать ваши запросы.Для этого вам необходимо масштабировать приложение и распределять его по нагрузке.Я предлагаю вам развернуть rabbitmq в кластере до нуля по этой проблеме.

Есть случаи, когда RabbitMQ игнорирует ограничения файловых дескрипторов .

RabbitMQ doc system limit screengrab

...