Netty源码断线重连的2021SC@SDUSC

2021SC@SDUSC

上次先是搞清楚了ChannelFuture是什么,明白了ChannelFuture是用来支持异步回调事件,并且在代码中使用的是监听器做异步回调处理。

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();
    }

除了首次启动Client以外,重连时也再次使用到connect,具体的连接方法则是通过 future.channel().eventLoop().schedule()添加一个定时任务,不断重连直到成功,而这里就用到上次说过的

  /**
     * 将指定的侦听器添加到此Future。完成此操作时,将通知指定的侦听器。如果此Future已完成,则会立即通知指定的侦听器。
     */
    Future<V> addListener(GenericFutureListener<? extends Future<? super V>> listener);

   /**
     * 当且仅当I/O操作成功完成时返回true。
     */
    boolean isSuccess();

可以看到定时任务不断执行connect直到连接成功,同时也不会再添加定时任务。这就是能够在断线时客户端用来重连的方法。
解决了这个问题之后还有个需要解决的地方,那就是客户端怎么发现“失联”,如果客户端发现断线,那么只要重连就可以了。这里涉及的方法是hander里的

// channel 处于不活动状态时调用
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.err.println("运行中断开重连。。。");
        nettyClient.connect();
    }

channelInactive方法能在断开时自动启用,由于示例中使用的是客户端的重连,这里的channelInactive就是指服务器关闭,同样的服务器里也可以通过重写channelInactive实现重连,但示例中只是调用父类方法,在客户端关闭后删除客户端。
除此之外exceptionCaught也可以实现断线重连。因为exceptionCaught会在发生异常时被调用

  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
        System.err.println("运行中断开重连。。。");
        nettyClient.connect();
    }

需要注意的是如果同时实现了channelInactive和exceptionCaught则会同时重连两次。以下是过程
首先正常开启服务端和客户端,两者正常对话
Netty源码断线重连的2021SC@SDUSC
Netty源码断线重连的2021SC@SDUSC
此时断开服务器,大约每三秒重连
Netty源码断线重连的2021SC@SDUSC

再次打开服务器还能再连上,如果一开始只打开客户端不打开服务器也是这个情况
Netty源码断线重连的2021SC@SDUSC

上一篇:116. 填充每个节点的下一个右侧节点指针


下一篇:2021-09-06 JMETER压力测试报错:JAVA.NET.BINDEXCEPTION: ADDRESS ALREADY IN USE: CONNECT