一 什么是斷線重連
斷線重連是指由於發生網絡故障而導致服務中斷的情況,客戶端就需要從重新連接服務端;哪些情況下會導致服務斷線呢?常見 的就是 網絡情況下,斷斷續續,導致客戶端無法和服務端交互,再比如,機房斷電也會導致服務宕機;所以在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);
}
// ....
}
四 模擬斷線重連
首先我們先啟動 服務端和 客戶端,知識追尋者 的代碼有個應答 消息;
服務端圖片效果如下
客戶端圖片效果如下
將 服務端 停止 ,客戶端會進行斷線重連
圖片效果如下
重新啟動服務端,重連成功