netty断线重连
一 什么是断线重连
断线重连是指由于发生网络故障而导致服务中断的情况,客户端就需要从重新连接服务端;哪些情况下会导致服务断线呢?常见 的就是 网络情况下,断断续续,导致客户端无法和服务端交互,再比如,机房断电也会导致服务宕机;所以在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);
}
// ....
}
四 模拟断线重连
首先我们先启动 服务端和 客户端,知识追寻者 的代码有个应答 消息;
服务端图片效果如下
客户端图片效果如下
将 服务端 停止 ,客户端会进行断线重连
图片效果如下
重新启动服务端,重连成功