2017-02-08 44 views
1

Я пишу TCP-сервер, используя Netty v4. Сервер будет обрабатывать несколько подключений от клиентов и передавать данные им.Netty server - медленный потребитель по TCP

Я хочу, чтобы определить, когда клиент потребляет данные с низким коэффициентом. Я в основном хочу избежать буферов TCP, чтобы их заполнить только потому, что клиент медленный!

Это в основном то, что делает ZeroMQ (называемое «Медленное обнаружение подписчика (Suicidal Snail Pattern)»). Как это можно сделать с помощью Netty?

Мой текущий код (я просто покажу настройки сервера):

 ServerBootstrap b = new ServerBootstrap(); 
     b.group(bossGroup, workerGroup) 
      .channel(NioServerSocketChannel.class) 
      .option(ChannelOption.SO_BACKLOG, 1000) 
      .handler(new LoggingHandler(LogLevel.INFO)) 
      .childHandler(new ChannelInitializer<SocketChannel>() { 
      @Override 
      public void initChannel(SocketChannel ch) throws Exception { 
       ChannelPipeline p = ch.pipeline(); 
       p.addLast(new Handler()); 
      } 
      }); 

     ChannelFuture f = b.bind(8000).sync(); 
     f.channel().closeFuture().sync(); 

Это вариант Ва SO_BACKLOG делает? Он говорит, что для подключения в очереди, но я заинтересован в том, чтобы пакеты были поставлены в очередь для определенного соединения.

ответ

0

Один из способов сделать это - использовать WriteBufferWaterMark s. Цитирование от Javadoc:

WriteBufferWaterMark используется для установки низкой отметки воды и воды высокой отметки для буфера записи. Если количество байтов, помещенных в буфер записи , превышает знак высокой воды, Channel.isWritable() начнет вернуть false. Если количество байт, помещенных в очередь в буфере записи , превышает знак высокой воды, а затем опускается ниже нижней отметки воды , Channel.isWritable() снова начнет возвращать значение true.

Установка соответствующих водяные знаков на вашем ребенок канала configs, медленный потребитель отметит канал не доступные для записи для «длинных» периодов времени по сравнению с потребителями энергичными. Таким образом, прослушивание изменений состояния записи в канале и отслеживание количества каналов времени не записываются, чтобы идентифицировать медленных потребителей и относительную тяжесть отставания, а затем вы можете отключить клиента, если их медлительность достигает определенного порога.

+0

Вы можете использовать 'Channel.isWritable()' даже без изменения водяных знаков. Они имеют значения по умолчанию.«Селектор» перестает сообщать OP_WRITE, когда заполняется буфер отправки сокета. – EJP

+0

@ Николас большое спасибо. Очень простая версия: 'if (! Ctx.channel(). IsWritable()) ctx.channel(). Close();' right? Это безопасно? – Will

+0

@ Николас, ты не ответил на мой последний вопрос, но я все еще думаю, что ваш ответ полезен: Р спасибо! Я соглашусь! – Will

0

Это что делает опция SO_BACKLOG?

Какая опция SO_BACKLOG?

Он говорит, что для подключения в очередь

Correct.

но я заинтересован в пакеты в очередь для конкретного соединения

Таким образом, вы не заинтересованы в SO_BACKLOG.

+0

Я заинтересован в опции отрезать (разъединителя) клиентов, когда они слишком медленно потребляя сообщения из буфера TCP. Имеет ли это смысл? – Will

0

В случае ваша единственная цель состоит в том, чтобы избежать переполнения буфера (противодавление), этот подход будет достаточно:

if (ctx.channel().isWritable()) { 
    ctx.writeAndFlush(msg); 
}