Мы используем haproxy перед серверной частью netty-3.6. Мы обслуживаем огромное количество подключений, некоторые из которых могут быть длительными.
Теперь проблема в том, что когда haproxy закрывает соединение для перебалансировки, он делает это, отправляя tcp-RST. Когда класс sun.nio.ch, используемый netty, видит это, он выдает исключение IOException: «Сброс соединения одноранговым узлом».
След:
sun.nio.ch.FileDispatcherImpl.read0(Native Method):1 in ""
sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:39):1 in ""
sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:225):1 in ""
sun.nio.ch.IOUtil.read(IOUtil.java:193):1 in ""
sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:375):1 in ""
org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:64):1 in ""
org.jboss.netty.channel.socket.nio.AbstractNioWorker.process(AbstractNioWorker.java:109):1 in ""
org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:312):1 in ""
org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:90):1 in ""
org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178):1 in ""
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145):1 in ""
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615):1 in ""
java.lang.Thread.run(Thread.java:724):1 in ""
Это вызывает следующие проблемы для каждой конфигурации:
вариант http-pretend-keepalive
Это то, что работает лучше всего (поскольку haproxy, похоже, закрывает большинство соединений с помощью FIN, а не RST), но все же производит около 3 исключений на сервер в секунду. Кроме того, он эффективно нейтрализует балансировку нагрузки, потому что некоторые входящие соединения очень давнишние с очень высокой пропускной способностью: с pretend-keepalive они никогда не перебалансируются на другой сервер с помощью haproxy.
опция http-keep-alive
Поскольку наш бэкэнд ожидает, что соединения keep-alive действительно поддерживаются (и, следовательно, не закрывают их сами по себе), этот параметр сводится к тому, что каждое соединение в конечном итоге создает одно исключение, которое, в свою очередь, приводит к сбою наших серверов. Мы пробовали добавить предпоследний сервер, но это мало помогло.
вариант http-server-close
Теоретически это должно работать как для правильной балансировки нагрузки, так и без исключений. Однако, похоже, что после того, как наши backend-серверы ответят, начинается гонка относительно того, какая сторона первой отправляет свой RST: haproxy или наш зарегистрированный ChannelFutureListener.CLOSE. На практике мы все еще получаем слишком много исключений и наши серверы падают.
Интересно, что чем больше работников мы снабжаем наши каналы, тем больше исключений. Думаю, это ускоряет чтение больше, чем письмо.
В любом случае, я некоторое время читал о различных параметрах каналов и сокетов в netty, а также о haproxy и не нашел ничего, что походило бы на решение (или работало, когда я его пробовал).