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

Java задняя часть Netty
Серия Netty: автоматическое повторное подключение

Это 10-й день моего участия в августовском испытании обновлений. Узнайте подробности события:Испытание августовского обновления

Введение

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

Используйте netty для установки соединения

Чтобы установить соединение с помощью netty, сначала необходимо запустить сервер, обычно с помощью ServerBootstrap для запуска сервера следующим образом:

// 绑定端口并启动
ChannelFuture f = b.bind(PORT).sync();

Для клиента его можно запустить через Bootstrap следующим образом:

// 连接服务器
ChannelFuture f = b.connect(HOST, PORT).sync();

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

Итак, когда соединение между клиентом и сервером разорвано, как автоматически переподключиться?

Для клиента для автоматического переподключения достаточно снова вызвать метод подключения Bootstrap. Ключевой вопрос сейчас заключается в том, как найти время для повторного вызова connect.

Мы знаем, что независимо от сервера или клиента для обработки сообщения необходимо зарегистрировать обработчик специально для обработки сообщения.

Для чтения сообщений вообще необходимо наследовать ChannelInboundHandlerAdapter.В этом обработчике определены многие методы, связанные с жизненным циклом канала.Начнем с этих методов жизненного цикла.

Вообще говоря, состояние соединения между клиентом и сервером такое:

КАНАЛ ЗАРЕГИСТРИРОВАН --> КАНАЛ АКТИВЕН --> ПРОЧИТАТЬ --> ЧТЕНИЕ ЗАВЕРШЕНО --> КАНАЛ НЕАКТИВЕН --> КАНАЛ НЕ ЗАРЕГИСТРИРОВАН

Если соединение между клиентом и сервером закрыто, будут инициированы два события, CHANNEL INACTIVE и CHANNEL UNREGISTERED, поэтому мы можем переписать следующие два метода на стороне клиента и добавить в метод логику повторного подключения.

    @Override
    public void channelInactive(final ChannelHandlerContext ctx) {
        println("连接断开:" + ctx.channel().remoteAddress());
    }

    @Override
    public void channelUnregistered(final ChannelHandlerContext ctx) throws Exception {
        println("sleep:" + ReconnectClient.RECONNECT_DELAY + 's');

        ctx.channel().eventLoop().schedule(() -> {
            println("重连接: " + ReconnectClient.HOST + ':' + ReconnectClient.PORT);
            ReconnectClient.connect();
        }, ReconnectClient.RECONNECT_DELAY, TimeUnit.SECONDS);
    }

В методе channelInactive мы просто печатаем логи. Основная логика в методе channelUnregistered, в этом методе мы сначала получаем текущий канал через ctx, затем получаем eventLoop в канале, затем вызываем его метод schedule, и через заданное время снова вызываем метод connect().

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

Определенный здесь метод подключения выглядит следующим образом:

    static void connect() {
        bs.connect().addListener(future -> {
            if (future.cause() != null) {
                handler.startTime = -1;
                handler.println("建立连接失败: " + future.cause());
            }
        });
    }

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

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

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

Класс, представляющий состояние бездействия, называется IdleStateEvent.У бездействия есть 6 состояний: FIRST_READER_IDLE_STATE_EVENT, READER_IDLE_STATE_EVENT, FIRST_WRITER_IDLE_STATE_EVENT, WRITER_IDLE_STATE_EVENT, FIRST_ALL_IDLE_STATE_EVENT и ALL_IDLE_STATE_EVENT.

Представляет IDLE состояния чтения, IDLE состояния записи и IDLE состояния чтения и записи соответственно.

Таким образом, мы можем добавить IdleStateHandler при запуске клиента.Когда клиент не читает сообщение с сервера в течение определенного периода времени, мы вызываем ctx.close(), чтобы закрыть канал, тем самым запуская операцию переподключения на клиенте. боковая сторона.

        bs.group(group)
                .channel(NioSocketChannel.class)
                .remoteAddress(HOST, PORT)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new IdleStateHandler(READ_TIMEOUT, 0, 0), handler);
                    }
                });

IDLESTATEEVENT - это событие от пользователя. Для захвата этого события необходимо переопределить USEREVentTrigging:

    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
        if (!(evt instanceof IdleStateEvent)) {
            return;
        }
        IdleStateEvent e = (IdleStateEvent) evt;
        if (e.state() == IdleState.READER_IDLE) {
            // 在Idle状态
            println("Idle状态,关闭连接");
            ctx.close();
        }
    }

В приведенном выше примере мы захватываем IdleStateEvent и определяем, является ли состояние IdleState IdleState.READER_IDLE, а затем закрываем канал.

Суммировать

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

Примеры этой статьи могут относиться к:learn-netty4

Эта статья была включена вWoohoo.Floyd Press.com/09-Netty-Hot…

Самая популярная интерпретация, самая глубокая галантерея, самое понятное руководство, множество советов, которых вы не знаете, и т. д.!

Добро пожаловать, чтобы обратить внимание на мой официальный аккаунт: «Программируйте эти вещи», разбирайтесь в технологиях, лучше поймите себя!