Netty подходит для длительных клиентов с высоким TPS - PullRequest
0 голосов
/ 07 апреля 2020

Я экспериментировал с несколькими различными библиотеками для создания сервера, который доставляет рыночные данные по TCP, и Netty.io является одним из кандидатов. По сути, я построил небольшой PO C, и у меня возникают некоторые проблемы с производительностью при высоких скоростях впрыска, таких как 64K TPS. Кажется, что он отлично работает при 32K TPS, но падает с обрыва и фактически приводит к остановке выше 64K TPS.

На следующем графике временных рядов показаны сообщения IN и OUT сервера при 64K TPS. Как вы можете видеть при высокой скорости впрыска, она повсюду.

64K TPS

Вот аналогичный график на 32K TPS

32K TPS

Код довольно прост. Я использую запрос для клиента, отправляю его в службу рыночных данных, которая передает сообщения через имеющийся у меня конвейер RX Java. Сообщение кодируется в двоичный ответ и отправляется обратно клиенту по TCP. Я пытаюсь выяснить, где мне нужно начать искать. Я знаю, что узкое место очень много на стороне кодирования, потому что с самого начала количество сообщений на сервер велико. Я делаю грипп sh на канале каждый раз, когда я получаю сообщение, поэтому я не уверен, что это его вызывает. Любое руководство приветствуется.

ServerBootstrap serverBootstrap = new ServerBootstrap();
    serverBootstrap
        .group(parentGroup, workerGroup)
        .channel(NioServerSocketChannel.class)
        .localAddress(port)
        .childOption(ChannelOption.SO_SNDBUF, 16777216)
        .childOption(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(16777216,33554432))
        .childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel socketChannel) throws Exception {
                //Build Pipeline to decode, process messages and encode response
                socketChannel.pipeline()
                    .addLast(
                        new FlushConsolidationHandler(1000, true),
                        createMessageFrameBuilder(),
                        new InboundMessageDecoder<>(),
                        new MarketDataReqResponseHandler<>(),
                        new MessageEncoder()
                    );
            }
        });

1 Ответ

0 голосов
/ 07 апреля 2020

Скорее всего, вы должны собирать потоки, поскольку flush() стоит дорого. Одна из вещей, которую вы можете сделать, это добавить FlushConsolidationHandler в конвейер. Это обеспечит объединение потоков, когда это возможно, и минимизирует системные вызовы.

...