网站系统架构图/兰州网络seo
文章目录
- 前言
- 一、超时监测
- 二、IdleStateHandler类
- 三、ReadTimeoutHandler类
- 四、WriteTimeoutHandler类
- 五、实现心跳机制
- 5.1. 定义心跳处理器
- 5.2. 定义 ChannelInitializer
- 5.3. 编写服务器
- 5.4. 测试
- 结语
前言
回顾Netty系列文章:
- Netty 概述(一)
- Netty 架构设计(二)
- Netty Channel 概述(三)
- Netty ChannelHandler(四)
- ChannelPipeline源码分析(五)
- 字节缓冲区 ByteBuf (六)(上)
- 字节缓冲区 ByteBuf(七)(下)
- Netty 如何实现零拷贝(八)
- Netty 程序引导类(九)
- Reactor 模型(十)
- 工作原理详解(十一)
- Netty 解码器(十二)
- Netty 编码器(十三)
- Netty 编解码器(十四)
- 自定义解码器、编码器、编解码器(十五)
- Future 源码分析(十六)
- Promise 源码分析(十七)
- 一行简单的writeAndFlush都做了哪些事(十八)
一、超时监测
Netty 的超时类型 IdleState 主要分为以下3类:
- ALL_IDLE : 一段时间内没有数据接收或者发送。
- READER_IDLE : 一段时间内没有数据接收。
- WRITER_IDLE : 一段时间内没有数据发送。
针对上面的 3 类超时异常,Netty 提供了 3 类ChannelHandler来进行监测。
- IdleStateHandler : 当 Channel 一段时间未执行读取、写入或者两者都未执行时,触发 -IdleStateEvent 事件。
- ReadTimeoutHandler :在一定时间内未读取任何数据时,引发 ReadTimeoutEvent 事件。
- WriteTimeoutHandler :当写操作在一定时间内无法完成时,引发 WriteTimeoutEvent 事件。
二、IdleStateHandler类
IdleStateHandler 包括了读\写超时状态处理,观察以下 IdleStateHandler 类的构造函数源码。
public IdleStateHandler(int readerIdleTimeSeconds, int writerIdleTimeSeconds, int allIdleTimeSeconds) {this((long)readerIdleTimeSeconds, (long)writerIdleTimeSeconds, (long)allIdleTimeSeconds, TimeUnit.SECONDS);
}public IdleStateHandler(long readerIdleTime, long writerIdleTime, long allIdleTime, TimeUnit unit) {this(false, readerIdleTime, writerIdleTime, allIdleTime, unit);
}public IdleStateHandler(boolean observeOutput, long readerIdleTime, long writerIdleTime, long allIdleTime, TimeUnit unit) {this.writeListener = new ChannelFutureListener() {public void operationComplete(ChannelFuture future) throws Exception {IdleStateHandler.this.lastWriteTime = IdleStateHandler.this.ticksInNanos();IdleStateHandler.this.firstWriterIdleEvent = IdleStateHandler.this.firstAllIdleEvent = true;}};this.firstReaderIdleEvent = true;this.firstWriterIdleEvent = true;this.firstAllIdleEvent = true;ObjectUtil.checkNotNull(unit, "unit");this.observeOutput = observeOutput;if (readerIdleTime <= 0L) {this.readerIdleTimeNanos = 0L;} else {this.readerIdleTimeNanos = Math.max(unit.toNanos(readerIdleTime), MIN_TIMEOUT_NANOS);}if (writerIdleTime <= 0L) {this.writerIdleTimeNanos = 0L;} else {this.writerIdleTimeNanos = Math.max(unit.toNanos(writerIdleTime), MIN_TIMEOUT_NANOS);}if (allIdleTime <= 0L) {this.allIdleTimeNanos = 0L;} else {this.allIdleTimeNanos = Math.max(unit.toNanos(allIdleTime), MIN_TIMEOUT_NANOS);}}
在上述源码中,构造函数可以接收以下参数:
-
readerIdleTimeSecond:指定读超时时间,指定 0 表明为禁用。
-
writerIdleTimeSecond:指定写超时时间,指定 0 表明为禁用。
-
allIdleTimeSecond:在指定读写超时时间,指定 0 表明为禁用。
IdleStateHandler 使用示例:
public class MyChannelInitializer extends ChannelInitializer<Channel> {@Overrideprotected void initChannel(Channel channel) throws Exception {channel.pipeline().addLast("idleStateHandler",new IdleStateHandler(60,30,0));channel.pipeline().addLast("myHandler",new MyHandler());}
}public class MyHandler extends ChannelDuplexHandler {@Overridepublic void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {if(evt instanceof IdleStateEvent){IdleStateEvent e = (IdleStateEvent) evt;if(e.state() == IdleState.READER_IDLE){ctx.close();}else if(e.state() == IdleState.WRITER_IDLE){ctx.writeAndFlush(new PingMessage());}}}
}
在上述示例中,IdleStateHandler 设置了读超时时间为 60 秒,写超时时间为 30 秒。MyHandler 是针对超时事件 IdleStateEvent 的处理。
- 如果 30 秒内没有出站流量(写超时)时发送 ping 消息的示例。
- 如果 60 秒内没有入站流量(读超时)时,连接关闭。
三、ReadTimeoutHandler类
ReadTimeoutHandler 类包括了读超时状态处理。ReadTimeoutHandler 类的源码如下:
public class ReadTimeoutHandler extends IdleStateHandler {private boolean closed;public ReadTimeoutHandler(int timeoutSeconds) {this((long)timeoutSeconds, TimeUnit.SECONDS);}public ReadTimeoutHandler(long timeout, TimeUnit unit) {super(timeout, 0L, 0L, unit);//禁用了写超时、读写超时}protected final void channelIdle(ChannelHandlerContext ctx, IdleStateEvent evt) throws Exception {assert evt.state() == IdleState.READER_IDLE;//只处理读超时this.readTimedOut(ctx);}protected void readTimedOut(ChannelHandlerContext ctx) throws Exception {if (!this.closed) {ctx.fireExceptionCaught(ReadTimeoutException.INSTANCE);//引发异常ctx.close();this.closed = true;}}
}
从上述源码可以看出,ReadTimeoutHandler 继承自 IdleStateHandler,并在构造函数中禁用了写超时、读写超时,而且在处理超时时,只会针对 READER_IDLE状态进行处理,并引发 ReadTimeoutException 异常。
ReadTimeoutHandler 的使用示例如下:
public class MyChannelInitializer extends ChannelInitializer<Channel> {@Overrideprotected void initChannel(Channel channel) throws Exception {channel.pipeline().addLast("readTimeoutHandler",new ReadTimeoutHandler(30));channel.pipeline().addLast("myHandler",new MyHandler());}
}//处理器处理ReadTimeoutException
public class MyHandler extends ChannelDuplexHandler {@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {if(cause instanceof ReadTimeoutException){//...}else {super.exceptionCaught(ctx,cause);}}
}
在上述示例中,ReadTimeoutHandler 设置了读超时时间是 30 秒。
四、WriteTimeoutHandler类
WriteTimeoutHandler 类包括了写超时状态处理。WriteTimeoutHandler 类的源码如下:
public class WriteTimeoutHandler extends ChannelOutboundHandlerAdapter {private static final long MIN_TIMEOUT_NANOS;private final long timeoutNanos;private WriteTimeoutHandler.WriteTimeoutTask lastTask;private boolean closed;public WriteTimeoutHandler(int timeoutSeconds) {this((long)timeoutSeconds, TimeUnit.SECONDS);}public WriteTimeoutHandler(long timeout, TimeUnit unit) {ObjectUtil.checkNotNull(unit, "unit");if (timeout <= 0L) {this.timeoutNanos = 0L;} else {this.timeoutNanos = Math.max(unit.toNanos(timeout), MIN_TIMEOUT_NANOS);}}public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {if (this.timeoutNanos > 0L) {promise = promise.unvoid();this.scheduleTimeout(ctx, promise);}ctx.write(msg, promise);}public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {WriteTimeoutHandler.WriteTimeoutTask task = this.lastTask;WriteTimeoutHandler.WriteTimeoutTask prev;for(this.lastTask = null; task != null; task = prev) {task.scheduledFuture.cancel(false);prev = task.prev;task.prev = null;task.next = null;}}private void scheduleTimeout(ChannelHandlerContext ctx, ChannelPromise promise) {WriteTimeoutHandler.WriteTimeoutTask task = new WriteTimeoutHandler.WriteTimeoutTask(ctx, promise);task.scheduledFuture = ctx.executor().schedule(task, this.timeoutNanos, TimeUnit.NANOSECONDS);if (!task.scheduledFuture.isDone()) {this.addWriteTimeoutTask(task);promise.addListener(task);}}private void addWriteTimeoutTask(WriteTimeoutHandler.WriteTimeoutTask task) {if (this.lastTask != null) {this.lastTask.next = task;task.prev = this.lastTask;}this.lastTask = task;}private void removeWriteTimeoutTask(WriteTimeoutHandler.WriteTimeoutTask task) {if (task == this.lastTask) {assert task.next == null;this.lastTask = this.lastTask.prev;if (this.lastTask != null) {this.lastTask.next = null;}} else {if (task.prev == null && task.next == null) {return;}if (task.prev == null) {task.next.prev = null;} else {task.prev.next = task.next;task.next.prev = task.prev;}}task.prev = null;task.next = null;}protected void writeTimedOut(ChannelHandlerContext ctx) throws Exception {if (!this.closed) {ctx.fireExceptionCaught(WriteTimeoutException.INSTANCE);ctx.close();this.closed = true;}}//...
}
从上述源码可以看出,WriteTimeoutHandler 在处理超时时,引发了 WriteTimeoutException 异常。
WriteTimeoutHandler 的使用示例如下:
public class MyChannelInitializer extends ChannelInitializer<Channel> {@Overrideprotected void initChannel(Channel channel) throws Exception {channel.pipeline().addLast("writeTimeoutHandler",new WriteTimeoutHandler(30));channel.pipeline().addLast("myHandler",new MyHandler());}
}//处理器处理ReadTimeoutException
public class MyHandler extends ChannelDuplexHandler {@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {if(cause instanceof WriteTimeoutException ){//...}else {super.exceptionCaught(ctx,cause);}}
}
在上述示例中,WriteTimeoutHandler 设置了写超时时间是 30 秒。
五、实现心跳机制
针对超时的解决方案——心跳机制。
在程序开发中,心跳机制是非常常见的。其原理是,当连接闲置时可以发送一个心跳来维持连接。一般而言,心跳就是一段小的通信。
5.1. 定义心跳处理器
public class HeartbeatServerHandler extends ChannelInboundHandlerAdapter {// (1)心跳内容private static final ByteBuf HEARTBEAT_SEQUENCE = Unpooled.unreleasableBuffer(Unpooled.copiedBuffer("Heartbeat",CharsetUtil.UTF_8)); @Overridepublic void userEventTriggered(ChannelHandlerContext ctx, Object evt)throws Exception {// (2)判断超时类型if (evt instanceof IdleStateEvent) {IdleStateEvent event = (IdleStateEvent) evt;String type = "";if (event.state() == IdleState.READER_IDLE) {type = "read idle";} else if (event.state() == IdleState.WRITER_IDLE) {type = "write idle";} else if (event.state() == IdleState.ALL_IDLE) {type = "all idle";}// (3)发送心跳ctx.writeAndFlush(HEARTBEAT_SEQUENCE.duplicate()).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);System.out.println( ctx.channel().remoteAddress()+"超时类型:" + type);} else {super.userEventTriggered(ctx, evt);}}
}
对上述代码说明:
-
定义了心跳时,要发送的内容。
-
判断是不是 IdleStateEvent 事件,是则处理。
-
将心跳内容发送给客户端。
5.2. 定义 ChannelInitializer
HeartbeatHandlerInitializer用于封装各类ChannelHandler,代码如下:
public class HeartbeatHandlerInitializer extends ChannelInitializer<Channel> {private static final int READ_IDEL_TIME_OUT = 4; // 读超时private static final int WRITE_IDEL_TIME_OUT = 5;// 写超时private static final int ALL_IDEL_TIME_OUT = 7; // 所有超时@Overrideprotected void initChannel(Channel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();pipeline.addLast(new IdleStateHandler(READ_IDEL_TIME_OUT,WRITE_IDEL_TIME_OUT, ALL_IDEL_TIME_OUT, TimeUnit.SECONDS)); // (1)pipeline.addLast(new HeartbeatServerHandler()); // (2)}
}
对上述代码说明如下:
- 添加了一个IdleStateHandler到 ChannelPipeline,并分别设置了读、写超时的时间。为了方便演示,将超时时间设置的比较短。
- 添加了HeartbeatServerHandler,用来处理超时时,发送心跳。
5.3. 编写服务器
服务器代码比较简单,启动后侦听 8083 端口。
public final class HeartbeatServer {static final int PORT = 8083;public static void main(String[] args) throws Exception {// 配置服务器EventLoopGroup bossGroup = new NioEventLoopGroup(1);EventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap b = new ServerBootstrap();b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 100).handler(new LoggingHandler(LogLevel.INFO)).childHandler(new HeartbeatHandlerInitializer());// 启动ChannelFuture f = b.bind(PORT).sync();f.channel().closeFuture().sync();} finally {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}
}
5.4. 测试
首先启动 HeartbeatServer,客户端用操作系统自带的 Telnet 程序即可:
telnet 127.0.0.1 8083
可以看到客户端与服务器的交互效果如下图。
结语
文章如果对你有帮助,看完记得点赞、关注、收藏。
相关文章:

【Netty】Netty中的超时处理与心跳机制(十九)
文章目录 前言一、超时监测二、IdleStateHandler类三、ReadTimeoutHandler类四、WriteTimeoutHandler类五、实现心跳机制5.1. 定义心跳处理器5.2. 定义 ChannelInitializer5.3. 编写服务器5.4. 测试 结语 前言 回顾Netty系列文章: Netty 概述(一&#…...

尚硅谷大数据hadoop教程_mapReduce
p67 课程介绍 p68概述 p69 mapreduce核心思想 p70 wordcount源码 序列化类型 mapReduce三类进程 p71 编程规范 用户编写的程序分成三个部分:Mapper、Reducer和Driver。 P72 wordcount需求案例分析 p 73 -78 案例环境准备 (1)创建maven…...

一键启停脚本
在/root 目录下创建bin文件夹再创建你的文件 文件里面写如下命令 #!/bin/bash if [ $# -lt 1 ] then echo "No Args Input..." exit ; fi case $1 in "start") echo " 启动集群 " echo " --------------- 启动 -------…...

20230604_Hadoop命令操作练习
20230604_Hadoop命令操作示例 再HDFS中创建文件夹:/itcast/it heima,如存在请删除(跳过回收站)。 hdfs dfs -mkdir -p /itcast/itheima上传/etc/hosts文件到hdfs的/itcast/itheima内。 hadoop fs -put /etc/hosts /itcast/itheima…...

hashCode 与 equals(重要)?
hashCode () 作用是获取哈希码,也称为散列码,实际上是返回一个int 整数,哈希码作用是确定该对象在哈希表中的索引位置;hashCode() 定义在JDK的Object.java中,意味着Java中的任何类都包含有hashCode() 函数。 散列表存…...

华为OD机试(2023.5新题) 需要打开多少监控器(java,py,c++,js)
华为OD机试真题目录:真题目录 本文章提供java、python、c++、jsNode四种代码 题目描述 某长方形停车场,每个车位上方都有对应监控器,当且仅当在当前车位或者前后左右四个方向任意一个车位范围停车时,监控器才需要打开 给出某一时刻停车场的停车分布,请统计最少需要打开…...

209.长度最小的子数组
2023.6.1 这道题的关键是滑动窗口法,滑动窗口法应设定好窗口左侧的右移条件与窗口右侧的移动条件 本例中先初始化好用到的各种值 循环的终止条件是滑动窗口右侧超出列表的范围 走来 cur_sum nums[right] 是将cur_sum的值更新为当前滑动窗口[left,right]的值之和 接…...

react antd Modal里Form设置值不起作用
问题描述: react antd Modal里Form设置值不起作用,即使用form的api。比如:编辑时带出原有的值。 造成的原因:一般设置值都是在声明周期里设置,比如:componentDidMounted里设置,hook则在useEff…...

idea连接Linux服务器
一、 介绍 配置idea的ssh会话和sftp可以实现对linux远程服务器的访问和文件上传下载,是替代Xshell的理想方式。这样我们就能在idea里面编写文件并轻松的将文件上传到linux服务器中。而且还能远程编辑linux服务器上的文件。掌握并熟练使用,能够大大提高我…...

在windows环境下使用winsw将jar包注册为服务(实现开机自启和配置日志输出模式)
前言 Windows系统使用java -jar m命令行运行Java项目会弹出黑窗。首先容易误点导致程序关闭,其次我们希望能在Windows系统做到开机自动启动。因此对于SpringBoot程序,目前主流的方法是采用winsw,简单容易配置 1.下载winsw工具 https://git…...

汽车通用款一键启动舒适进入拓展蓝牙4G网络手机控车系统
1.PKE无钥匙舒适进入功能,靠近车门自动开锁,离开车门自动上锁 2.一键启动/熄火 3.远程遥控启动/熄火 4.遥控设防盗/解除防盗 5.遥控开后尾箱锁负信号输出(需要原车自带尾箱马达和继电器) 6.静音防盗/解除防盗 7.启动车后踩脚刹自动上锁 8.熄火车辆后自动开锁…...

QSettings Class
QSettings类 QSettings类公共类型(枚举)公有成员函数静态成员函数函数作用这个类写文件的特征 QSettings类 QSettings类提供持久的独立于平台的应用程序设置。 头文件:#include< QSettings >qmake:QT core继承(父):QObje…...

【vue】关于vue中的插槽
当在Vue.js中构建可复用的组件时,有时候需要在父组件中传递内容给子组件。Vue的插槽(slot)机制提供了一种灵活的方式来实现这种组件间通信。 插槽允许你在父组件中编写子组件的内容,然后将其传递给子组件进行渲染。这样ÿ…...

Springboot整合Mybatis Plus【超详细】
文章目录 Mybatis Plus简介快速整合1,导入依赖2,yml文件中配置信息3,启动类上加上扫描mapper接口所在包的注解4,编写配置类5,实现自动注入通用字段接口(非必需)6,编写生成器工具类 使…...

接口测试-使用mock生产随机数据
在做接口测试的时候,有的接口需要进行大量的数据进行测试,还不能是重复的数据,这个时候就需要随机生产数据进行测试了。这里教导大家使用mock.js生成各种随机数据。 一、什么是mock.js mock.js是用于生成随*机数据,拦截 Ajax 请…...

Kohl‘s百货的EDI需求详解
Kohls是一家美国的连锁百货公司,成立于1962年,总部位于美国威斯康星州的门多西。该公司经营各种商品,包括服装、鞋子、家居用品、电子产品、化妆品等,并拥有超过1,100家门店,分布在美国各地。本文将为大家介绍Kohls的E…...

二叉树part6 | ● 654.最大二叉树 ● 617.合并二叉树 ● 700.二叉搜索树中的搜索 ● 98.验证二叉搜索树
文章目录 654.最大二叉树思路代码 617.合并二叉树思路代码 700.二叉搜索树中的搜索思路代码 98.验证二叉搜索树思路官方题解代码困难 今日收获 654.最大二叉树 思路 前序遍历构造二叉树。 找出数组中最大值,然后递归处理左右子数组。 时间复杂度On2 空间复杂度On …...

Linux命令记录
Shells 查看当前系统shell cat /etc/shells # 输出 # /etc/shells: valid login shells /bin/sh /bin/bash /usr/bin/bash /bin/rbash /usr/bin/rbash /bin/dash /usr/bin/dash查看正在使用的shell echo $SHELL # 输出 /bin/bashLinux文件结构 bin:系统可执行文件b…...

eBPF 入门实践教程十五:使用 USDT 捕获用户态 Java GC 事件耗时
eBPF (扩展的伯克利数据包过滤器) 是一项强大的网络和性能分析工具,被广泛应用在 Linux 内核上。eBPF 使得开发者能够动态地加载、更新和运行用户定义的代码,而无需重启内核或更改内核源代码。这个特性使得 eBPF 能够提供极高的灵活性和性能,…...

Linux :: vim 编辑器的初次体验:三种 vim 常用模式 及 使用:打开编辑、退出保存关闭vim
前言:本篇是 Linux 基本操作篇章的内容! 笔者使用的环境是基于腾讯云服务器:CentOS 7.6 64bit。 学习集: C 入门到入土!!!学习合集Linux 从命令到网络再到内核!学习合集 目录索引&am…...

Linux内核进程创建流程
本文代码基于Linux5.10 内容主要参考《Linux内核深度解析》余华兵 当Linux内核要创建一个新进程时, 流程大致如下 ret fork(); if (ret 0) {/* 子进程装载程序 */ret execve(filename, argv, envp); } else if (ret > 0) {/* 父进程 */ } 大致可以分为创建新…...

【03.04】大数据教程--HTTP协议和静态Web服务器
HTTP协议和静态Web服务器 HTTP(Hypertext Transfer Protocol)是一种用于传输超文本的协议,它是Web上的基础通信协议。静态Web服务器是指能够提供静态内容(如HTML、CSS、JavaScript和图像文件)的服务器。 在本教程中&am…...

数据共享传输:台式机和笔记本同步文件!
为什么要在台式机和笔记本同步文件? “我想在台式机和笔记本同步文件。因为我工作时使用笔记本,在家里使用安装了Windows 10系统的台式机,我想要在笔记本和台式机之间同步应用程序、游戏、文档等。有没有一种可以在台式机和笔记本同步文件的…...

java设计模式(十二)代理模式
目录 定义模式结构角色职责代码实现静态代理动态代理jdk动态代理cglib代理 适用场景优缺点 定义 代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。说简单点,代理模式就是设置一个中间代理来控制访问原目标对象,以达到…...

Umi微前端水印踩坑以及解决方案
最近公司需要在管理后台加一个水印方案~ 项目用的umi方案,以为就是改一个配置的问题,后来发现坑点还蛮多~ 希望此稳定能帮助到用umi 的你们. 一. 先来说说心路历程 坑点1 umi的水印适配只能在layout中进行配置,也就是路由配置中layout为false的页面无法配置水印,比如说登录页…...

Android RK3588-12 hdmi-in Camera方式支持NV24格式
hdmi-in Camera方式支持NV24格式 modified: hardware/interfaces/camera/device/3.4/default/ExternalCameraDevice.cpp modified: hardware/interfaces/camera/device/3.4/default/ExternalCameraDeviceSession.cpp diff --git a/hardware/interfaces/camera/device/3.4…...

Hive窗口函数详细介绍
文章目录 Hive窗口函数概述样本数据表结构表数据 窗口函数窗口聚合函数count()SQL演示 sum()SQL演示 avg()SQL演示 min()SQL演示 max()SQL演示 窗口分析函数first_value() 取开窗第一个值应用场景SQL演示 last_value()取开窗最后一个值应用场景SQL演示 lag(col, n, default_val…...

牛客网【c语言练习】
单选题 下面代码段的输出是(-12 ) int main() {int a3; printf("%d\n",(aa-a*a)); } aa-9,此时还是等于3,因为a*a只是运算,并没有赋值;之后再算a-9,运算之前a等于3,运算…...

C++类和对象(上)
文章目录 🦍1. 面向过程和面向对象🦧2. 类的引入🐶3. 类的定义🦮4. 类的访问控制和封装🍖4.1 访问限定符🍖4.2 封装 🐩5. 类的作用域🐅6. 类的实例化🐄7. 类的大小计算&a…...

JavaScript 数据透视表 DHTMLX Pivot Crack
DHTMLX Pivot JavaScript 数据透视表 - 强大的数据汇总和报告 使用我们的高速 JavaScript/HTML5 Pivot 组件可视化您的复杂数据,从而提高您的商业智能。 它可以帮助您以方便的方式汇总大型数据集。 主要特征 纯 JavaScript 库,可轻松与任何服务器端集成…...