LINUX.ORG.RU

Вопросы по Netty

 ,


0

3

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

Каналы отличная абстракция, но кажется, что на каждое сообщение создавать канал не очень производительное решение. Есть ли у кого опыт заворачивания прогонки батча сообщений в один канал или это не стоит того ? То есть хотелось бы уйти от

bootstrap.connect().addListener(
                (ChannelFutureListener) connectionFuture -> connectionFuture.channel().writeAndFlush(msg));
на каждое сообщение.

Самый главный вопрос, в моем приложении мне нужно получить финальный респонс от сервера, в котором будет статус код. Не нашел элегантного решения, кроме как складывать статус в аттрибут канала. К тому же, чтобы гарантированно дождаться ответа с респонзом нужно вызывать sync(), что ударяет про перформансу обработки пайплайна. Хотелось бы уйти от sync() и как-то решить вопрос откуда мне забирать статус и куда его соответственно сохранять.

pipelineFuture.channel().closeFuture().sync().addListener( // здесь хотелось бы урать метод sync(), но пока без него мы не гарантируем получения статус кода
                (ChannelFutureListener) future -> {
                    if (future.isSuccess()) {
                        AttributeKey<Integer> status = AttributeKey.valueOf(future.channel().id().asShortText());
                        Integer statusCode = future.channel().attr(status).get();
                        // deal with status code
                    }
                });

сторим статус в финальном хендлере

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object in) {
	//...
       ctx.channel().attr(AttributeKey.valueOf(channelId)).set(statusCode);
    }

            Bootstrap b = new Bootstrap();
            b.group(workerGroup)
                .channel(NioSocketChannel.class)
                .option(ChannelOption.SO_KEEPALIVE, true)
                .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)
                .handler(new NettyClientChannelInitializer(xxxx));


                logger.info("Connecting to server..");
                ChannelFuture f = b.connect(server, port).sync();
                f.channel().closeFuture().sync();

NettyClientChannelInitializer наследуется от io.netty.channel.ChannelInitializer и дальше внутри делаешь что хочешь с тем что пришло. Хочешь SSL прикручивай, хочешь HTTP парси.

xpahos ★★★★★
()
Ответ на: комментарий от xpahos

С пайплайном хендлеров вообще нет проблем, все работает. Но работает не очень производительно, хотелось бы понять какие ручки нужно подкручивать. В твоем примере вызывается sync(); Это уже сильный спад перформанса. Хотелось бы какой то гарантированный листенер, в который можно завернуть получение финального ответа от сервера.

nullb0t
() автор топика
Ответ на: комментарий от bytecode

Спад заключается в разных значениях requests/sec. Приложение в конечном счете публикует уведомление об обработке запроса в кролик. Скорость появления уведомлений и служит метрикой производительности приложения.

nullb0t
() автор топика
Ответ на: комментарий от nullb0t

В твоем примере вызывается sync(); Это уже сильный спад перформанса.

SO_KEEPALIVE тебе видимо ни о чем не говорит, не знаю как ты собрался без базовых знаний какой-то спад перформанса ловить.

xpahos ★★★★★
()
Ответ на: комментарий от xpahos

Метрика уже была описана чуть выше. Если покажешь пример который гарантированно работает, но без вызова sync() буду премного благодарен, а пока выглядит так что от этого нельзя уйти.

nullb0t
() автор топика
Ответ на: комментарий от nullb0t

Ок, для тех кто не понимает что такое TCP.

ChannelFuture f = b.connect(server, port).sync();

Создает TCP соединение, ну там хендшейк и все такое. keepalive гарантирует, что ядро будет проверять живо ли соединение.

f.channel().closeFuture().sync();

Ждет когда клиент пошлет RST/FIN. Без вызова sync ты просто не будешь ждать окончания соединения, т.е. у тебя будет куча открытых сокетов, которые возможно через 2 минуты протухнут. Запрос это не соединение, в одном канале может быть бесчисленное количество запросов, которые лимитированы лишь сетевой картой/ядром и цпу, который процессит эти данные. Так понятно?

xpahos ★★★★★
()
Ответ на: комментарий от xpahos

Ждет когда клиент пошлет RST/FIN. Без вызова sync ты просто не будешь ждать окончания соединения

Через addListener мы можем добиться такого же поведения ? В случае с connect это отлично работает, если посмотришь на код в первом сообщении там нет никакого sync.

nullb0t
() автор топика
Ответ на: комментарий от nullb0t

ботовод, facepalm стек оверфлов в этом точно не поможет

ибо ваших знаний в tcp/ip ~= 0

anonymous
()
Ответ на: комментарий от nullb0t

addListener == await, чем отличается await от sync поищи в самом netty.

xpahos ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.