1.心跳检测机制

1.1 定时断线重连

客户端断线重连机制

客户端数量多,且需要传递的数据量级较大。可以在周期性的发送数据的时候,使用。要求对数据的即时性不高的时候,才可使用。

优点:可以使用数据缓存。不是每条数据进行一次数据交互。可以定时回收资源,对资源利用率高。相对来说,即时性可以通过其他方式保证。如: 120秒自动断线。数据变化1000次请求服务器一次。300秒中自动发送不足1000次的变化数据。

对于长连接的程序断网重连几乎是程序的标配。断网重连具体可以分为两类:

CONNECT失败,需要重连

实现ChannelFutureListener 用来启动时监测是否连接成功,不成功的话重试

// 实现ChannelFutureListener 用来启动时监测是否连接成功,不成功的话重试//1.lambda 方式
private void doConnect() {Bootstrap b = ...;b.connect().addListener((ChannelFuture f) -> {if (!f.isSuccess()) {long nextRetryDelay = nextRetryDelay(...); // 延时多少重新发送连接请求f.channel().eventLoop().schedule(nextRetryDelay, ..., () -> {doConnect();});}});
}// 2.自定义类的方式
public class ConnectionListener implements ChannelFutureListener {private Client client;public ConnectionListener(Client client) {this.client = client;}@Overridepublic void operationComplete(ChannelFuture channelFuture) throws Exception {if (!channelFuture.isSuccess()) {System.out.println("Reconnect");//因为是建立网络连接所以可以共用EventLoopfinal EventLoop loop = channelFuture.channel().eventLoop();loop.schedule(new Runnable() {@Overridepublic void run() {client.createBootstrap(new Bootstrap(), loop);}}, 1L, TimeUnit.SECONDS);}}
}

程序运行过程中断网、远程强制关闭连接、收到错误包必须重连;

public class Client{public Bootstrap createBootstrap(Bootstrap bootstrap, EventLoopGroup eventLoop) {if (bootstrap != null) {final MyInboundHandler handler = new MyInboundHandler(this);bootstrap.group(eventLoop);bootstrap.channel(NioSocketChannel.class);bootstrap.option(ChannelOption.SO_KEEPALIVE, true);bootstrap.handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {socketChannel.pipeline().addLast(handler);}});bootstrap.remoteAddress("localhost", 8888);bootstrap.connect().addListener(new ConnectionListener(this));}return bootstrap;}
}public class MyInboundHandler extends SimpleChannelInboundHandler {private Client client;public MyInboundHandler(Client client) {this.client = client;}// 和服务器断开连接时触发@Overridepublic void channelInactive(ChannelHandlerContext ctx) throws Exception {final EventLoop eventLoop = ctx.channel().eventLoop();eventLoop.schedule(new Runnable() {@Overridepublic void run() {client.createBootstrap(new Bootstrap(), eventLoop);}}, 1L, TimeUnit.SECONDS);super.channelInactive(ctx);}}

1.2 心跳监测

使用定时发送消息的方式,实现硬件检测,达到心态检测的目的。

心跳监测是用于检测电脑硬件和软件信息的一种技术。如:CPU使用率,磁盘使用率,内存使用率,进程情况,线程情况等。

Netty提供的心跳检测机制分为三种:

  • 读空闲,链路持续时间t没有读取到任何消息;
  • 写空闲,链路持续时间t没有发送任何消息;
  • 读写空闲,链路持续时间t没有接收或者发送任何消息;

心跳检测机制分为三个层面:

  • TCP层面的心跳检测,即TCP的Keep-Alive机制,它的作用域是整个TCP协议栈;
  • 协议层的心跳检测,主要存在于长连接协议中。例如SMPP协议;
  • 应用层的心跳检测,它主要由各业务产品通过约定方式定时给对方发送心跳消息实现。
public class MyServer {public static void main(String[] args) throws Exception {//创建两个线程组EventLoopGroup bossGroup = new NioEventLoopGroup(1);//8个NioEventLoopEventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap serverBootstrap = new ServerBootstrap();serverBootstrap.group(bossGroup, workerGroup);serverBootstrap.channel(NioServerSocketChannel.class);serverBootstrap.handler(new LoggingHandler(LogLevel.INFO));serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();//加入一个netty 提供 IdleStateHandler
//                    说明
//                    1. IdleStateHandler 是netty 提供的处理空闲状态的处理器
//                    2. long readerIdleTime : 表示多长时间没有读, 就会发送一个心跳检测包检测是否连接
//                    3. long writerIdleTime : 表示多长时间没有写, 就会发送一个心跳检测包检测是否连接
//                    4. long allIdleTime : 表示多长时间没有读写, 就会发送一个心跳检测包检测是否连接
//
//                    5. 文档说明
//                    triggers an {@link IdleStateEvent} when a {@link Channel} has not performed
// * read, write, or both operation for a while.
// *                  6. 当 IdleStateEvent 触发后 , 就会传递给管道 的下一个handler去处理
// *                  通过调用(触发)下一个handler 的 userEventTiggered , 在该方法中去处理 IdleStateEvent(读空闲,写空闲,读写空闲)pipeline.addLast(new IdleStateHandler(7000, 7000, 10, TimeUnit.SECONDS));//加入一个对空闲检测进一步处理的handler(自定义)pipeline.addLast(new MyServerHandler());}});//启动服务器ChannelFuture channelFuture = serverBootstrap.bind(7000).sync();channelFuture.channel().closeFuture().sync();} finally {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}
}
public class MyServerHandler extends ChannelInboundHandlerAdapter {/*** @param ctx 上下文* @param evt 事件* @throws Exception*/@Overridepublic void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {if (evt instanceof IdleStateEvent) {//将  evt 向下转型 IdleStateEventIdleStateEvent event = (IdleStateEvent) evt;String eventType = null;switch (event.state()) {case READER_IDLE:eventType = "读空闲";break;case WRITER_IDLE:eventType = "写空闲";break;case ALL_IDLE:eventType = "读写空闲";break;default:throw new IllegalStateException("Unexpected value: " + event.state());}System.out.println(ctx.channel().remoteAddress() + "--超时时间--" + eventType);System.out.println("服务器做相应处理..");//如果发生空闲,我们关闭通道// ctx.channel().close();}}
}

2.Netty 通过WebSocket 编程实现服务器和客户端长连接

2.1 要求

要求:

  1. 实现计语 webSocket 的长连接的全双工的交互
  2. 改变 Http 协议多次请求的约束,实现长连接,服务器可以主动发送消息给浏览器
  3. 客户端浏览器和服务端会相互感知,比如服务器关闭了,浏览器会感知,同样浏览器关闭了,服务器会感知

2.2 代码

public class MyServer {public static void main(String[] args) throws Exception {//创建两个线程组EventLoopGroup bossGroup = new NioEventLoopGroup(1);//8个NioEventLoopEventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap serverBootstrap = new ServerBootstrap();serverBootstrap.group(bossGroup, workerGroup);serverBootstrap.channel(NioServerSocketChannel.class);serverBootstrap.handler(new LoggingHandler(LogLevel.INFO));serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();//因为基于http协议,使用http的编码和解码器pipeline.addLast(new HttpServerCodec());//是以块方式写,添加ChunkedWriteHandler处理器pipeline.addLast(new ChunkedWriteHandler());/*说明1. http数据在传输过程中是分段, HttpObjectAggregator ,就是可以将多个段聚合2. 这就是为什么,当浏览器发送大量数据时,就会发出多次http请求*/pipeline.addLast(new HttpObjectAggregator(8192));/*说明1. 对应websocket ,它的数据是以 帧(frame) 形式传递2. 可以看到WebSocketFrame 下面有六个子类3. 浏览器请求时 ws://localhost:7000/hello 表示请求的uri4. WebSocketServerProtocolHandler 核心功能是将 http协议升级为 ws协议 , 保持长连接5. 是通过一个 状态码 101*/pipeline.addLast(new WebSocketServerProtocolHandler("/hello2"));//自定义的handler ,处理业务逻辑pipeline.addLast(new MyTextWebSocketFrameHandler());}});//启动服务器ChannelFuture channelFuture = serverBootstrap.bind(7000).sync();channelFuture.channel().closeFuture().sync();} finally {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}
}
/*** 这里 TextWebSocketFrame 类型,表示一个文本帧(frame)** @author Administrator*/
public class MyTextWebSocketFrameHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {@Overrideprotected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {System.out.println("服务器收到消息 " + msg.text());//回复消息ctx.channel().writeAndFlush(new TextWebSocketFrame("服务器时间" + LocalDateTime.now() + " " + msg.text()));}/*** 当web客户端连接后, 触发方法*/@Overridepublic void handlerAdded(ChannelHandlerContext ctx) throws Exception {//id 表示唯一的值,LongText 是唯一的 ShortText 不是唯一System.out.println("handlerAdded 被调用" + ctx.channel().id().asLongText());System.out.println("handlerAdded 被调用" + ctx.channel().id().asShortText());}@Overridepublic void handlerRemoved(ChannelHandlerContext ctx) throws Exception {System.out.println("handlerRemoved 被调用" + ctx.channel().id().asLongText());}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {System.out.println("异常发生 " + cause.getMessage());//关闭连接ctx.close();}
}
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<script>var socket;//判断当前浏览器是否支持websocketif(window.WebSocket) {//go onsocket = new WebSocket("ws://localhost:7000/hello2");//相当于channelReado, ev 收到服务器端回送的消息socket.onmessage = function (ev) {var rt = document.getElementById("responseText");rt.value = rt.value + "\n" + ev.data;}//相当于连接开启(感知到连接开启)socket.onopen = function (ev) {var rt = document.getElementById("responseText");rt.value = "连接开启了.."}//相当于连接关闭(感知到连接关闭)socket.onclose = function (ev) {var rt = document.getElementById("responseText");rt.value = rt.value + "\n" + "连接关闭了.."}} else {alert("当前浏览器不支持websocket")}//发送消息到服务器function send(message) {if(!window.socket) { //先判断socket是否创建好return;}if(socket.readyState == WebSocket.OPEN) {//通过socket 发送消息socket.send(message)} else {alert("连接没有开启");}}
</script><form onsubmit="return false"><textarea name="message" style="height: 300px; width: 300px"></textarea><input type="button" value="发生消息" onclick="send(this.form.message.value)"><textarea id="responseText" style="height: 300px; width: 300px"></textarea><input type="button" value="清空内容" onclick="document.getElementById('responseText').value=''"></form>
</body>
</html>

java - (二)netty 心跳监测机制相关推荐

  1. Netty -Netty心跳检测机制案例,Netty通过WebSocket编程实现服务器和客户端长链接

    Netty心跳检测机制案例 案例要求 编写一个Netty心跳检测机制案例,当服务器超过3秒没有读时,就提示读空闲 当服务器超过5秒没有写操作时,提示写空闲 服务器超过7秒没有读或者写操作时,就提示读写 ...

  2. Netty心跳检测机制

    一.Netty心跳检测机制 心跳:即在 TCP 长连接中,客户端和服务器之间定期发送的一种特殊的数据包,通知对方自己还在线,以确保 TCP 连接的有效性. 在 Netty 中,实现心跳机制的关键是 I ...

  3. Netty 心跳检测机制

    心跳检测机制 目的:就是用于检测 检测通信对方是否还"在线",如果已经断开,就要释放资源 或者 尝试重连. 大概的实现原理就是:在服务器和客户端之间一定时间内没有数据交互时, 即处 ...

  4. Netty(八) Netty心跳检测机制

    1.什么是长链接和短链接 在HTTP/1.0中默认使用短连接.也就是说,客户端和服务器每进行一次HTTP操作,就建立一次连接,任务结束就中断连接.当客户端浏览器访问的某个HTML或其他类型的Web页中 ...

  5. netty的编解码、粘包拆包问题、心跳检测机制原理

    文章目录 1. 编码解码器 2. 编解码序列化机制的性能优化 3. Netty粘包拆包 4. Netty心跳检测机制 5. Netty断线自动重连实现 1. 编码解码器 当你通过netty发送或者接受 ...

  6. Netty学习(七):心跳检测机制

    一.什么是心跳检测机制 所谓心跳, 即在 TCP 长连接中, 客户端和服务器之间定期发送的一种特殊的数据包, 通知对方自己还在线, 以确保 TCP 连接的有效性. 心跳机制主要是客户端和服务端长时间连 ...

  7. Netty教程07:心跳检测机制

    需求:编写一个 Netty心跳检测机制案例, 当服务器超过3秒没有读时,就提示读空闲 当服务器超过5秒没有写操作时,就提示写空闲 实现当服务器超过7秒没有读或者写操作时,就提示读写空闲 Server ...

  8. java通过netty实现心跳机制_Netty4服务端心跳机制

    Netty4与Netty3.x的心跳机制略有不同,在Netty4中已经去掉了IdleStateAwareChannelHandler这个类,但IdleStateHandler依旧保留,只是心跳超时的触 ...

  9. Netty 心跳机制及断线重连

    1.心跳检测 心跳检测是在TCP长连接中,客户端和服务端定时向对方发送数据包通知对方自己还在线,保证连接的有效性的一种机制. 为什么使用心跳检测? 假死:如果底层的TCP连接(socket连接)已经断 ...

最新文章

  1. 详解 WSUS 部署
  2. STM32F4 HAL库开发 -- 工程模板解读
  3. 七分钟理解什么是 KMP 算法
  4. 今天我开通了51cto的博客
  5. windows server 2008 R2 服务器关机总结
  6. hadoop之BlockPoolManager源码分析
  7. NB-IoT 的“前世今生”
  8. C# 之 日常问题积累(一)
  9. 易建科技eKing Cloud招聘,快到碗里来~
  10. API函数之GetUserName
  11. Microsoft.Windows.Controls.Ribbon.RibbonWindow 碰到 AvalonDock出现的诡异现象
  12. 在IDEA中使用Maven详细教程
  13. tesseract的安装
  14. C++ —— 宏对于简化类接口的奇技淫巧
  15. 【vue】【intersectionObserver】滚动正文时菜单滚动到对应菜单
  16. (四)Tensorboard学习——mnist_with_summaries.py
  17. EMC测试仪器_新能源汽车EMC测试—HPK高压耦合器测试系统
  18. 致敬第一个1024(第一次Java代码编程)
  19. 每个程序员都应该阅读的最有影响力的书是什么?
  20. Jmeter(110)——阶梯式加压线程组Stepping Thread Group

热门文章

  1. The bean ‘XXX‘ could not be injected because it is a JDK dynamic proxy
  2. 计蒜客信息学3月普及组模拟赛
  3. MVC、MVP、MVVM模式的概念与区别
  4. 春夏秋冬又一春之Redis持久化
  5. 春考天津计算机知识点资料,2016年天津春季高考计算机基础考试大纲
  6. greenplum查询表结构java_Greenplum小把戏 - 几个常用数据库对象大小查询SQL
  7. Unity3D学习笔记8——GPU实例化(3)
  8. 仿网易新闻顶部菜单html,iOS仿网易新闻滚动导航条效果
  9. R语言axis函数参数详解(坐标轴函数)
  10. 深度学习入门(一)快速建立自己的图片数据集