当前位置: 首页 > 后端技术 > Java

Netty系列:自动重连

时间:2023-04-01 22:14:00 Java

介绍我们在使用客户端与服务端的连接时,可能会因为各种问题导致客户端与服务端的连接中断。这种情况下,一般情况下我们需要使用一个监控程序来监控客户端和服务端之间的连接。如果第一次发现连接断开,需要手动重连。比较麻烦。今天给大家介绍一种netty中自动重连的方法。使用netty建立连接要使用netty建立连接,首先需要启动服务器。一般来说,服务端是使用ServerBootstrap来启动服务端,如下图://绑定端口并启动ChannelFuturef=b.bind(PORT).sync();对于客户端来说,可以通过Bootstrap来启动,如下所示://连接到服务器ChannelFuturef=b.connect(HOST,PORT).sync();断开连接后如何自动重连?对于客户端,自动重连只需要再次调用Bootstrap的connect方法即可。现在的关键问题是如何找到时间再次调用connect。我们知道,无论是服务端还是客户端,对消息的处理都需要注册一个专门处理消息的handler。对于读取消息,一般需要继承ChannelInboundHandlerAdapter。许多与通道生命周期相关的方法都定义在这个处理程序中。我们可以从这些生命周期方法开始。一般而言,客户端与服务器的连接状态如下:而服务器关闭,会触发CHANNELINACTIVE和CHANNELUNREGISTERED两个事件,这样我们就可以在客户端重写下面两个方法,在方法中加入重连逻辑。@OverridepublicvoidchannelInactive(finalChannelHandlerContextctx){println("连接断开:"+ctx.channel().remoteAddress());}@OverridepublicvoidchannelUnregistered(finalChannelHandlerContextctx)throwsException{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中添加一些监听器来监听connect的执行状态。这里定义的connect方法如下:staticvoidconnect(){bs.connect().addListener(future->{if(future.cause()!=null){handler.startTime=-1;handler.println(“建立连接失败:”+future.cause());}});}自动重连的模拟在上一节中,我们已经知道了如何自动重连。本节将模拟自动重连。这是一个名为IdleStateHandler的类。从名字可以看出,该类在Channel没有进行任何读写操作时触发Idle状态。表示Idle状态的类称为IdleStateEvent。Idle有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(newChannelInitializer(){@OverrideprotectedvoidinitChannel(SocketChannelch)throwsException{ch.pipeline().addLast}(newIdleStateHandler(READ_TIMEOUT,0,0),handler);}});IdleStateEvent是由用户发起的事件。要捕获此事件,需要重写userEventTriggered:publicvoiduserEventTriggered(ChannelHandlerContextctx,Objectevt){if(!(evtinstanceofIdleStateEvent)){return;}IdleStateEvente=(IdleStateEvent)evt;if(e.state()==IdleState.READER_IDLE){//空闲状态println("空闲状态,关闭连接");ctx.close();}}上面的例子中,我们捕获了IdleStateEvent,判断如果IdleState的状态为IdleState.READER_IDLE,那么channel就会关闭。作为本文的总结,我们介绍了重连的原理和用户触发的事件。我希望你会喜欢。本文示例可参考:learn-netty4本文已收录于http://www.flydean.com/09-netty-reconnect/最流行的解读,最深刻的干货,最简洁的教程,很多你不知道的小技巧等你来发现!欢迎关注我的公众号:《程序那些事儿》,懂技术,更懂你!