Netty Review - раскрыт механизм автоматического переподключения Netty: принципы и лучшие практики
Netty Review - раскрыт механизм автоматического переподключения Netty: принципы и лучшие практики
Каталог статей
  • Обзор
  • Pre
  • Клиент автоматически переподключается
  • Code
    • Server
    • Клиент (ключ)
  • тест
    • Начать автоматическое переподключение
    • Автоматическое переподключение после обрыва связи во время работы

Обзор


Pre

Обзор Netty — углубленное обсуждение механизма обнаружения пульса Netty: принципы, практика и анализ исходного кода IdleStateHandler.


Клиент автоматически переподключается

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

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

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


Code

Server

Язык кода:javascript
копировать
package com.artisan.reconnect;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
/**
 * @author маленький мастер
 * @version 1.0
 * @mark: show me the code , change the world
 */
public class ArtisanNettyServer {

    public static void main(String[] args) throws Exception {
        // Создайте две группы потоков BossGroup и WorkerGroup. По умолчанию количество подпотоков, содержащихся в NioEventLoop, в два раза превышает количество ядер процессора.
        // BossGroup просто обрабатывает запросы на соединение , реальная бизнес-обработка будет передана рабочей группе.
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup(8);
        try {
            // Создайте объект запуска на стороне сервера.
            ServerBootstrap bootstrap = new ServerBootstrap();
            // Используйте цепное программирование для настройки параметров
            bootstrap.group(bossGroup, workerGroup) //Настраиваем две группы потоков
                    // Используйте NioServerSocketChannel в качестве реализации канала сервера.
                    .channel(NioServerSocketChannel.class)
                    // Инициализируйте размер очереди сервера. Сервер обрабатывает клиентсоединять запросы последовательно, поэтому одновременно может обрабатываться только один клиентсоединять.
                    // Когда одновременно приходит несколько клиентов, сервер поместит запрос клиентсоединять, который не может быть обработан, в очередь и будет ждать обработки.
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    .childHandler(new ChannelInitializer<SocketChannel>() {//Создаем объект инициализации канала, задаем параметры инициализации, в SocketChannel Выполните перед настройкой

                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            //Устанавливаем процессор для SocketChannel рабочей группы
                            //ch.pipeline().addLast(new LifeCycleInBoundHandler());
                            ch.pipeline().addLast(new ArtisanNettyServerHandler());
                        }
                    });
            System.out.println("netty server start。。");
            // Привяжите порт и синхронизируйте, Создается асинхронный объект ChannelFuture, и о состоянии выполнения асинхронного события можно судить с помощью isDone() и других методов.
            // Запустите сервер (и привяжите порт), привязка — это асинхронная операция, а метод синхронизации — ожидание завершения асинхронной операции.
            ChannelFuture cf = bootstrap.bind(9000).sync();
            // Зарегистрируйте прослушиватель для cf, чтобы слушать события, которые нас интересуют
            /*cf.addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    if (cf.isSuccess()) {
                        System.out.println("Успешно прослушивается порт 9000");
                    } else {
                        System.out.println("Ошибка прослушивания порта 9000");
                    }
                }
            });*/
            // Подождите, пока порт прослушивания сервера закроется. closeFuture — асинхронная операция.
            // Синхронно дождаться завершения процесса закрытия канала с помощью метода синхронизации. Это заблокирует и дождется завершения закрытия канала. Метод wait() объекта вызывается внутренне.
            cf.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}
  1. EventLoopGroup:NettyиспользоватьEventLoopGroupдля обработки цикла событий иIOдействовать。Здесь созданы дваEventLoopGroup,один для обработкисоединятьпросить(bossGroup),另один для обработки实际избизнес-логика(workerGroup)。
  2. ServerBootstrap:ЭтоNettyиз Еще один основной компонент,Используется для настройки и инициализации сервера.
  3. ChannelFuture:Это一个异步результат对象,用于表示通道действоватьизрезультат。
  4. ChannelInitializer:Это一个用于初始化新соединятьизпроцессор。
  5. ArtisanNettyServerHandler:Это должно быть обычаемизкласс обработки,Используется для обработки бизнес-логики,Приведено ниже.
  6. bind()иcloseFuture()bind()Метод используется для запуска сервера и привязки порта,closeFuture()Используется для ожидания закрытия канала сервера。
  7. finallyкусок:Здесь убедитесь, что после запуска сервера произойдет сбой или успех,EventLoopGroupбудет закрыто изящно,освободить ресурсы.

Язык кода:javascript
копировать
package com.artisan.reconnect;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;

/**
 * @author маленький мастер
 * @version 1.0
 * @mark: show me the code , change the world
 * @Description: Пользовательский обработчик должен наследовать определенный HandlerAdapter (спецификацию), указанный netty.
 */
public class ArtisanNettyServerHandler extends ChannelInboundHandlerAdapter {

    /**
     * Прочитайте данные, отправленные клиентом
     *
     * @param ctx объект контекста, Содержит каналы, трубопроводы
     * @param msg Это данные, отправленные клиентом
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("Поток чтения сервера " + Thread.currentThread().getName());
        //Channel channel = ctx.channel();
        //ChannelPipeline pipeline = ctx.pipeline(); //По сути, это двусторонняя ссылка, исходящий входящий
        //Воля msg преобразовать в один ByteBuf, аналог NIO из ByteBuffer
        ByteBuf buf = (ByteBuf) msg;
        System.out.println("Клиент отправил сообщение:" + buf.toString(CharsetUtil.UTF_8));
    }

    /**
     * Метод обработки завершения чтения данных
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ByteBuf buf = Unpooled.copiedBuffer("HelloClient".getBytes(CharsetUtil.UTF_8));
        ctx.writeAndFlush(buf);
    }

    /**
     * обрабатывать исключения, В общем, надо закрыть канал
     *
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
    }
}

определяет обычайизNetty服务器процессорArtisanNettyServerHandler,он наследует отChannelInboundHandlerAdapter。这个процессор Включать了几个重要изметод борьбы склиентизпроситьи响应:

  1. channelRead(ChannelHandlerContext ctx, Object msg):Когда сервер запускается склиент Когда данные получены,Этот метод будет вызван. В этом методе,Вы можете написать логику, которая обрабатывает отправку данных. В этом примере,Он просто печатает полученныйиз Содержание сообщения。
  2. channelReadComplete(ChannelHandlerContext ctx):Этот методchannelReadВызывается после завершения выполнения метода。В этом методе,Вы можете отправлять ответы клиенту. В этом примере,它отправлять了一个简单из"HelloClient"сообщение дляклиент。
  3. exceptionCaught(ChannelHandlerContext ctx, Throwable cause):Этот метод出现异常时被调用。В этом методе,Вы можете написать обработку исключенийизлогика。В этом примере,Он просто закрывает канал.

Клиент (ключ)

Этот код представляет собой простой пример клиента, использующего платформу Netty, реализующую функцию переподключения. Ниже приводится объяснение этого кода на китайском языке:

Язык кода:javascript
копировать
package com.artisan.reconnect;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import java.util.concurrent.TimeUnit;
/**
 * @author маленький мастер
 * @version 1.0
 * @mark: show me the code , change the world
 * @Description: Достигнуто переподключениеизклиент
 */
public class ArtisanNettyClient {
    private String host;
    private int port;
    private Bootstrap bootstrap;
    private EventLoopGroup group;
    public static void main(String[] args) throws Exception {
        ArtisanNettyClient artisanNettyClient = new ArtisanNettyClient("localhost", 9000);
        artisanNettyClient.connect();
    }
    public ArtisanNettyClient(String host, int port) {
        this.host = host;
        this.port = port;
        init();
    }
    private void init() {
        // клиенту требуется группа цикла событий
        group = new NioEventLoopGroup();
        // Создать объект запуска клиента
        // bootstrap многоразовый, Просто инициализируйте его при создании экземпляра NettyClient.
        bootstrap = new Bootstrap();
        bootstrap.group(group)
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        // Добавить процессор
                        ch.pipeline().addLast(new ArtisanNettyClientHandler(ArtisanNettyClient.this));
                    }
                });
    }
    public void connect() throws Exception {
        System.out.println("netty client start。。");
        // Начать клиент подключать серверную часть
        ChannelFuture cf = bootstrap.connect(host, port);
        cf.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                if (!future.isSuccess()) {
                    // Повторное соединение передается внутреннему потоку для выполнения.
                    future.channel().eventLoop().schedule(() -> {
                        System.err.println("Повторно подключиться к серверу...");
                        try {
                            connect();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }, 3000, TimeUnit.MILLISECONDS);
                } else {
                    System.out.println("Сервер соединился успешно...");
                }
            }
        });
        // Мониторинг закрытия канала
        cf.channel().closeFuture().sync();
    }
}

Этот код определяет файл с именемArtisanNettyClientиздобрый,он содержитклиентиз初始化исоединятьлогика。

  • EventLoopGroup:NettyиспользоватьEventLoopGroupдля обработки цикла событий иIOдействовать。Здесь созданNioEventLoopGroup,для обработкиклиентизIOдействовать。
  • Bootstrap:ЭтоNettyиз Еще один основной компонент,Используется для настройки и инициализации клиента.
  • ChannelFuture:Это一个异步результат对象,用于表示通道действоватьизрезультат。
  • connect()метод:这个метод用于启动клиентисоединятьна сервер。еслисоединятьнеудача,它将использоватьscheduleметод在3Повторите попытку через несколько секундсоединять。
  • ArtisanNettyClientHandler:Это должно быть обычаемизкласс обработки,Используется для обработки бизнес-логики,Но в этом коде не приведена конкретная реализация.
  • init()метод:这个метод用于初始化клиентизBootstrapиEventLoopGroup
  • operationComplete()метод:ЭтоChannelFutureListenerиз回调метод,для обработкисоединятьдействоватьизрезультат。еслисоединятьнеудача,Он организует повторную попытку соединения. Если соединение прошло успешно,Он напечатает сообщение об успехе.
  • closeFuture().sync():这个метод用于等待клиентканал закрыт,Обязательноклиент Заполните все необходимое перед закрытиемизочистка。

В этом примере клиент попытается подключиться к указанному адресу и порту сервера, и если соединение не удастся, он автоматически повторит попытку подключения.


Язык кода:javascript
копировать
package com.artisan.reconnect;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;
/**
 * @author маленький мастер
 * @version 1.0
 * @mark: show me the code , change the world
 */
public class ArtisanNettyClientHandler extends ChannelInboundHandlerAdapter {
    private ArtisanNettyClient artisanNettyClient;
    public ArtisanNettyClientHandler(ArtisanNettyClient artisanNettyClient) {
        this.artisanNettyClient = artisanNettyClient;
    }
    /**
     * Этот метод будет запущен, когда сервер завершит работу.
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        // СоздайтеByteBuf,Содержит строку «HelloServer»из
        ByteBuf buf = Unpooled.copiedBuffer("HelloServer".getBytes(CharsetUtil.UTF_8));
        // Отправить сообщение на сервер
        ctx.writeAndFlush(buf);
    }
    /**
     * Он сработает, когда на канале произойдет событие чтения, то есть сервер отправит данные клиенту.
     *
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // Получить содержимое сообщения
        ByteBuf buf = (ByteBuf) msg;
        // 打印服务端отправлятьиз消息
        System.out.println("Получено сообщение от сервера:" + buf.toString(CharsetUtil.UTF_8));
        // Адрес сервера печати
        System.out.println("Адрес сервера: " + ctx.channel().remoteAddress());
    }
    /**
     * Вызывается, когда канал неактивен
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        // Распечатать сообщение с подсказкой
        System.err.println("Отключить и снова подключить во время работы...");
        // 调用клиентизconnectметод进行重连
        artisanNettyClient.connect();
    }
    /**
     * Вызывается при обнаружении исключения
     *
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        // Распечатать информацию о стеке исключений
        cause.printStackTrace();
        // Закрыть канал
        ctx.close();
    }
}

Этот класс обработчика содержит некоторые основные методы для обработки активации, чтения, неактивности и исключений канала. Вот краткое описание каждого метода:

  • channelActive():когдаклиентуспехсоединятьна сервер时,Этот метод будет называться,и отправляет сообщение на сервер.
  • channelRead():когдаклиент Когда сообщение получено с сервера,Этот метод будет называться,и打印出接收到из Содержание сообщенияи服务器изадрес。
  • channelInactive():когда通道不再活跃时(Например,связь отключена),Этот метод будет называться,И попробуйте перезагрузить сервер.
  • exceptionCaught():когда捕获到异常时,Этот метод будет называться,и打印异常из Информация трассировки стека,Затем Закрыть канал。

Этот класс обработки является частью клиентской логики и отвечает за взаимодействие между клиентом и сервером.


тест

Начать автоматическое переподключение

Сначала запустите клиент (обязательно), а затем запустите сервер, чтобы проверить автоматическое переподключение клиента.

Запускайте клиент, а не сервер

Запустить сервер


Автоматическое переподключение после обрыва связи во время работы

Сбой сети или сбой сервера во время работы системы,В результате клиент отключается от сервера и его необходимо подключить заново.,Можно найти вклиент处理данныеизHandlerизchannelInactiveметод中进行重连。

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

Отключить сервер

Восстановить сервер

boy illustration
Учебное пособие по Jetpack Compose для начинающих, базовые элементы управления и макет
boy illustration
Код js веб-страницы, фон частицы, код спецэффектов
boy illustration
【новый! Суперподробное】Полное руководство по свойствам компонентов Figma.
boy illustration
🎉Обязательно к прочтению новичкам: полное руководство по написанию мини-программ WeChat с использованием программного обеспечения Cursor.
boy illustration
[Забавный проект Docker] VoceChat — еще одно приложение для мгновенного чата (IM)! Может быть встроен в любую веб-страницу!
boy illustration
Как реализовать переход по странице в HTML (html переходит на указанную страницу)
boy illustration
Как решить проблему зависания и низкой скорости при установке зависимостей с помощью npm. Существуют ли доступные источники npm, которые могут решить эту проблему?
boy illustration
Серия From Zero to Fun: Uni-App WeChat Payment Practice WeChat авторизует вход в систему и украшает страницу заказа, создает интерфейс заказа и инициирует запрос заказа
boy illustration
Серия uni-app: uni.navigateЧтобы передать скачок значения
boy illustration
Апплет WeChat настраивает верхнюю панель навигации и адаптируется к различным моделям.
boy illustration
JS-время конвертации
boy illustration
Обеспечьте бесперебойную работу ChromeDriver 125: советы по решению проблемы chromedriver.exe не найдены
boy illustration
Поле комментария, щелчок мышью, специальные эффекты, js-код
boy illustration
Объект массива перемещения объекта JS
boy illustration
Как открыть разрешение на позиционирование апплета WeChat_Как использовать WeChat для определения местонахождения друзей
boy illustration
Я даю вам два набора из 18 простых в использовании фонов холста Power BI, так что вам больше не придется возиться с цветами!
boy illustration
Получить текущее время в js_Как динамически отображать дату и время в js
boy illustration
Вам необходимо изучить сочетания клавиш vsCode для форматирования и организации кода, чтобы вам больше не приходилось настраивать формат вручную.
boy illustration
У ChatGPT большое обновление. Всего за 45 минут пресс-конференция показывает, что OpenAI сделал еще один шаг вперед.
boy illustration
Copilot облачной разработки — упрощение разработки
boy illustration
Микросборка xChatGPT с низким кодом, создание апплета чат-бота с искусственным интеллектом за пять шагов
boy illustration
CUDA Out of Memory: идеальное решение проблемы нехватки памяти CUDA
boy illustration
Анализ кластеризации отдельных ячеек, который должен освоить каждый&MarkerгенетическийВизуализация
boy illustration
vLLM: мощный инструмент для ускорения вывода ИИ
boy illustration
CodeGeeX: мощный инструмент генерации кода искусственного интеллекта, который можно использовать бесплатно в дополнение к второму пилоту.
boy illustration
Машинное обучение Реальный бой LightGBM + настройка параметров случайного поиска: точность 96,67%
boy illustration
Бесшовная интеграция, мгновенный интеллект [1]: платформа больших моделей Dify-LLM, интеграция без кодирования и встраивание в сторонние системы, более 42 тысяч звезд, чтобы стать свидетелями эксклюзивных интеллектуальных решений.
boy illustration
LM Studio для создания локальных больших моделей
boy illustration
Как определить количество слоев и нейронов скрытых слоев нейронной сети?
boy illustration
[Отслеживание целей] Подробное объяснение ByteTrack и детали кода