Netty Server не обрабатывает HTTP-запросы после использования Server Bootstrap для настройки

У меня есть микросервис на основе Spring Reactive, который использует Netty Server версии 4.1.101.Final. Он работал совершенно нормально и обрабатывал все отправленные мной HTTP-запросы. Теперь я хочу перехватить идентификаторы соединений, чтобы выяснить, какое соединение используется, а какое закрывается. Для этого я написал собственный обработчик ведения журнала подключений. Ниже приведен мой ConnectionLoggingHandler:

public class ConnectionLoggingHandler extends ChannelInboundHandlerAdapter{
    private static final AtomicInteger connectionIdCounter = new AtomicInteger(0);
    
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception{
        int connectionId=connectionIdCounter.incrementAndGet();
        System.out.println("Connection established : ID = " + connectionId);
        ctx.channel().attr(AttributeKey.valueOf("connectionId")).set(connectionId);
        super.channelActive(ctx);
    }
    
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception{
        //retrieve connectionID
        Integer connectionId = (Integer) ctx.channel().attr(AttributeKey.valueOf("connectionId")).get();
        if (connectionId!=null){
          System.out.println("Connection closed : ID = " + connectionId);  
        }
        super.channelInactive(ctx);
    }
    
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception{
        //retrieve connectionID
        Integer connectionId = (Integer) ctx.channel().attr(AttributeKey.valueOf("connectionId")).get();
        if (connectionId!=null){
          System.out.println("Exception in Connection: ID = " + connectionId);  
        }
        cause.printStackTrace();
        ctx.close();
    }
}

Теперь я хочу добавить этот обработчик на свой сервер Netty. Я попробовал это двумя способами.

Код для пользовательского сервера Netty:

public class CustomNettyServer{
    private int port =8080;
    
    @PostConstruct
    public void startServer() throws InterruptedException{
        EventLoopGroup boss= new NioEventLoopGroup();
        EventLoopGroup worker=new NioEventLoopGroup();
        try{
            ServerBootstrap bootstrap new ServerBootstrap();
            bootstrap.group(boss,worker)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<Channel>(){
                    @Override
                    protected void initChannel(Channel ch) throws Exception{
                        ch.pipeline().addLast(new HttpServerCodec(),new HttpRequestDecoder(),new HttpContentDecompressor(),new HttpResponseEncoder(),new HttpContentCompressor(),new HttpObjectAggregator(512*1024),new ConnectionLoggingHandler());
                        
                    }
                });
            Channel channel = bootstarp.bind(port).sync().channel();
            channel.closeFuture().sync();
        }
        finally{
            boss.shutdownGracefully();
            worker.shutdownGracefully();
        }
    }
}

Когда я использую этот сервер, я могу видеть журналы, присутствующие в моем пользовательском обработчике, когда я отправляю через Postman запрос на установление соединения. Однако мой HTTP-запрос не обрабатывается.
Пишет: входящее сообщение отброшено. Пожалуйста, проверьте конфигурацию вашего конвейера. Я не знаю, чего мне здесь не хватает.

Затем я попробовал еще один способ настройки моего сервера Netty. Ниже приведен мой код для CustomNettyServer.

public class CustomNettyServer implements WebServerFactoryCustomizer<NettyReactiveWebServerFactory>{
    @Override
    public void customize(NettyReactiveWebServerFactory factory){
        factory.addServerCustomizers(server->
        server.tcpConfiguration(tcp->
        tcp.doOnConnection(connection->
        connection.addHandlerLast(new ConnectionLoggingHandler()))));
    }
}

Используя этот метод, я не вижу печати журналов из-за моего ConnectionLoggingHandler всякий раз, когда я нажимаю на запрос и запрос успешно обрабатывается. Я вижу, как обработчик добавляется в конвейер при отправке запроса и удаляется при его обслуживании. Но логи не генерируются. Я также сохранил уровень ведения журнала DEBUG.

Я не знаю, что я делаю не так в этих двух отношениях, и застрял здесь.
Поэтому я хочу знать, как получить журналы идентификаторов соединений, которые открываются, используются и закрываются.
Спасибо.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
67
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Reactor Netty (среда выполнения по умолчанию, используемая Spring WebFlux) не использует классы Bootstrap, предоставляемые Netty.

Правильный способ расширения Reactor Netty — через обратные вызовы жизненного цикла . В вашем примере вы использовали doOnConnection, но на данный момент канал уже активен, и ваша реализация под ConnectionLoggingHandler#channelActive никогда не будет вызываться (проверьте javadoc на предмет addHandlerLast). Вам лучше использовать обратный вызов doOnChannelInit, как показано ниже.

@Component
public class CustomNettyServer
        implements WebServerFactoryCustomizer<NettyReactiveWebServerFactory> {
    @Override
    public void customize(NettyReactiveWebServerFactory factory) {
        factory.addServerCustomizers(server ->
                server.doOnChannelInit((obs, ch, addr) ->
                        ch.pipeline().addAfter(NettyPipeline.HttpCodec, "test", new ConnectionLoggingHandler())));
    }
}

Это заставило мой ConnectionLoggingHanlder работать. Но я не могу понять одного.... Когда я нажимаю на запрос, я вижу, что два соединения устанавливаются, а затем одно закрывается, а другое используется для обслуживания запроса. Почему он устанавливает два соединения? и когда будет закрыто другое соединение? Есть ли по умолчанию тайм-аут простоя, тайм-аут соединения или тайм-аут поддержания активности в netty?

Satyam Pareek 03.06.2024 08:38

Пожалуйста, проверьте это projectreactor.io/docs/netty/release/reference/…

Violeta Georgieva 03.06.2024 12:17

Другие вопросы по теме