netty断线重连(3)

x33g5p2x  于2021-08-23 转载在 Java  
字(2.7k)|赞(0)|评价(0)|浏览(122)

一 什么是断线重连

断线重连是指由于发生网络故障而导致服务中断的情况,客户端就需要从重新连接服务端;哪些情况下会导致服务断线呢?常见 的就是 网络情况下,断断续续,导致客户端无法和服务端交互,再比如,机房断电也会导致服务宕机;所以在netty中对服务进行断线重连是非常有必要的做的一个流程;

二 netty断线重连步骤

netty 什么情况下需要断线重连?

netty 刚刚启动时需要断线重连,有可能服务刚刚启动,连接失败,此时就可以尝试断线重连,保证服务正常运行;其次,当服务在运行过程中出现网络故障的时候需要断线重连,这样能保证服务即使宕机恢复后也能马上恢复;所以 netty 的断线重连需要 2 步骤,缺一不可;

三 客户端断线重连

netty 的服务端一般情况下不需要断线重连,应为服务端服务宕机就只能重新启动服务;所以今天我们研究的是客户端的断线重连;

3.1 服务启动时断线重连

首先 我们需要写一个监听器 实现 ChannelFutureListener 接口的 operationComplete 方法, 在这边 我们 使用构造器注入的方式获取 nettyClient 实例, 当客户端连接操作完成后启动一个负载监听,在方法中我们使用 channelFuture.isSuccess() 的 结果进行判定 客户端的连接是否启动成功;如果没有启动成功则启动新的线程进行重连,确保客户端连接时能连接成功;

@Slf4j
public class ConnectionListener implements ChannelFutureListener {
    private NettyClient nettyClient;
    public ConnectionListener(NettyClient nettyClient) {
        this.nettyClient = nettyClient;
    }
    @Override
    public void operationComplete(ChannelFuture channelFuture) throws Exception {
        if (!channelFuture.isSuccess()) {
            log.warn("-------------客户端重新连接-----------------");
            final EventLoop loop = channelFuture.channel().eventLoop();
            loop.schedule(new Runnable() {
                @SneakyThrows
                @Override
                public void run() {
                    nettyClient.connect(8080,"127.0.0.1");
                }
            }, 1L, TimeUnit.SECONDS);
        }
    }

}

这边我们只是实现了一个监听器,我们还需要把监听器注入到客户端;

public void connect(int port, String host) {

        // 创建线程组
        NioEventLoopGroup nioEventLoopGroup = new NioEventLoopGroup();
        // netty启动辅助类
        Bootstrap bootstrap = new Bootstrap();
        //
        bootstrap.group(nioEventLoopGroup)
                .channel(NioSocketChannel.class)
                .option(ChannelOption.TCP_NODELAY, true)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        // 处理IO事件
                        ChannelPipeline pipeline = socketChannel.pipeline();
                        // 异常断线重连
                        pipeline.addLast(new NettyClientHandler(new NettyClient()));
                    }
                });
        // 异步操作
        ChannelFuture connect = null;
        try {
            connect = bootstrap
                    .connect(host, port)
                    .addListener(new ConnectionListener(this))// netty 启动时如果连接失败,会断线重连
                    .sync();
            // 关闭客户端
            connect.channel()
                    .closeFuture()
                    .sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

3.2 服务运行中断重连

我们 在 NettyClientHandler 实现一个 channelInactive 方法,当服务端断线时 我们会触发这个方法重启启动一个线程进行断线重连;

@Slf4j
public class NettyClientHandler extends ChannelInboundHandlerAdapter {

    private NettyClient nettyClient;


    public NettyClientHandler(NettyClient nettyClient) {
        this.nettyClient = nettyClient;
    }
	// ....

    /**
     * @Author lsc
     * <p> 运行时断线重连</p>
     * @Param [ctx]
     * @Return
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        final EventLoop eventLoop = ctx.channel().eventLoop();
        eventLoop.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("22222222222222222");
                nettyClient.connect(8080, "127.0.0.1");
            }
        }, 1L, TimeUnit.SECONDS);
        super.channelInactive(ctx);
    }
	// ....
}

四 模拟断线重连

首先我们先启动 服务端和 客户端,知识追寻者 的代码有个应答 消息;

服务端图片效果如下

客户端图片效果如下

将 服务端 停止 ,客户端会进行断线重连

图片效果如下

重新启动服务端,重连成功

想获取本套教程源码和后续内容 关注 公众号 知识追寻者 , 后台回复 netty 获取源码

相关文章