Netty心跳检测

文章目录

    • 一、网络连接假死现象
    • 二、服务器端的空闲检测
    • 三、客户端的心跳报文

客户端的心跳检测对于任何长连接的应用来说,都是一个非常基础的功能。要理解心跳的重要性,首先需要从网络连接假死的现象说起。

一、网络连接假死现象

什么是连接假死呢?如果底层的TCP连接已经断开,但是服务器端并没有正常地关闭套接字,认为这条连接仍然是存在的。

连接假死的具体表现如下:

  1. 在服务器端,会有一些处于TCP_ESTABLISHED状态的正常连接
  2. 在客户端,TCP客户端已经显示连接已经断开
  3. 客户端此时虽然可以进行断线重连操作,但是上一次连接状态依然被服务器端认为有效,并且服务器端的资源得不到正确释放,包括套接字上下文以及接受/发送缓冲区

连接假死的情况虽然不常见,但是确实存在。服务器端长时间运行后,会面临大量假死连接得不到释放的情况。由于每个连接都会消耗CPU和内存资源,因此大量假死的连接会逐渐耗光服务器的资源,使得服务器越来越慢,IO处理效率越来越低,最终导致服务器崩溃。

连接假死通常是由多个原因造成的:

  1. 应用程序出现线程堵塞,无法进行连接的读写
  2. 网络相关的设别出现故障
  3. 网络丢包

解决假死的有效手段是客户端定时进行心跳检测,服务端定时进行空闲检测。

二、服务器端的空闲检测

想解决假死问题,服务器端的有效手段是空闲检测。所谓空闲检测就是每隔一段时间监测子通道是否有数据读写,如果有则子通道是正常的,如果没有则判定为假死,关闭子通道。

服务器端实现空闲检测只需要使用Netty自带的IdleStateHandler空闲状态处理器就可以实现这个功能。

@Slf4j
public class HeartBeatServerHandler extends IdleStateHandler {private static final int READ_IDLE_GAP = 150; // 最大空闲时间(s)public HeartBeatServerHandler() {super(READ_IDLE_GAP, 0, 0, TimeUnit.SECONDS);}@Overrideprotected void channelIdle(ChannelHandlerContext ctx, IdleStateEvent evt) throws Exception {log.info("{}秒内未读到数据,关闭连接", READ_IDLE_GAP);// 其他处理,如关闭会话}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {// 判断消息实例if (!(msg instanceof MessageProtos.Message message)) {super.channelRead(ctx, msg);return;}if (message.getType() == MessageProtos.HeadType.HEART_BEAT) {if (ctx.channel().isActive()) {// 将心跳数据包直接回给客户端ctx.writeAndFlush(msg);}}super.channelRead(ctx, msg);}
}

在HeartBeatServerHandler的构造函数中,调用了基类IdleStateHandler的构造函数,传递了四个参数:

  1. 入站空闲检测时长:指的是一段时间内如果没有消息入站就判定为连接假死
  2. 出站空闲检测时长:指的是一段时间内如果没有数据出站就判定为连接假死
  3. 出/入站检测时长:表示在一段时间内如果没有出站或者入站就判定为连接假死
  4. 时间单位

判定为假死之后IdleStateHandler会回调自己的channelIdle()方法,一般在这个方法中去进行一些连接的关闭。

HeartBeatServerHandler实现的主要功能是空闲检测,需要客户端定时发送心跳数据包(或报文、消息)进行配合,而且客户端发送心跳数据包的时间间隔需要远远小于服务器端的空闲检测时间间隔。

收到客户端的心跳数据包之后可以直接回复客户端,让客户端也能进行类似的空闲检测。由于IdleStateHandler本身是一个入站处理器,只需要重写这个子类的channelRead方法,然后将心跳数据包直接写回给客户端即可。

如果HeartBeatServerHandler要重写channelRead方法,一定要调用积累的channelRead方法,不然IdleStateHandler的入站空闲检测会无效。

三、客户端的心跳报文

与服务器端的空闲检测相配合,客户端需要定期发送数据包到服务器端,通常这个数据包称为心跳数据包。

@Slf4j
public class HeartBeatClientHandler extends ChannelInboundHandlerAdapter {// 心跳的时间间隔,单位为秒private static final int HEART_BEAT_INTERVAL = 50;// 在Handler业务处理器被加入到流水线时开始发送心跳数据包@Overridepublic void handlerAdded(ChannelHandlerContext ctx) throws Exception {ClientSession session = ctx.channel().attr(ClientSession.CLIENT_SESSION).get();MessageProtos.MessageHeartBeat heartBeat =MessageProtos.MessageHeartBeat.newBuilder().setSeq(0).setJson("{\"from\":\"client\"}").setUid(session.getUserDTO().getUserId()).build();MessageProtos.Message message = MessageProtos.Message.newBuilder().setType(MessageProtos.HeadType.HEART_BEAT).setSessionId(session.getSessionId()).setMessageHeartBeat(heartBeat).build();heartBeat(ctx, message);super.handlerAdded(ctx);}private void heartBeat(ChannelHandlerContext ctx, MessageProtos.Message message) {// 提交在给定延迟后启用的一次性任务。ctx.executor().schedule(() -> {if (ctx.channel().isActive()) {log.info("发送心跳消息给服务端");ctx.writeAndFlush(message);// 递归调用,发送下一次的心跳heartBeat(ctx, message);}}, HEART_BEAT_INTERVAL, TimeUnit.SECONDS);}// 接收到服务器的心跳回写@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {if (!(msg instanceof MessageProtos.Message message)) {super.channelRead(ctx, msg);return;}if (message.getType() == MessageProtos.HeadType.HEART_BEAT) {log.info("收到会写的心跳信息");} else {super.channelRead(ctx, msg);} }
}

在HeartBeatClientHandler实例被加入到流水线时,它重写的handlerAdded方法被回调。在handlerAdded方法中开始调用heartBeat方法发送心跳数据包。heartBeat是一个不断递归调用的方法,它使用了ctx.executor()获取当前通道绑定的Reactor反应器NIO线,然后通过NIO现线程的schedule定时调度方法,在50s后触发这个方法的执行,再之后递归调用同样延时50s后继续发送。

客户端的心跳间隔要比服务器端的空闲检测时间间隔要短,一般来说要比它的一半要短一些,可以直接定义为空闲检测时间间隔的1/3,以防止公网偶发的秒级抖动。

HeartBeatClientHandler实例并不是一开始就装配到流水线中的,它装配的实际实在登录成功之后。

HeartBeatClientHandler实际上也可以集成IdleStateHandler类在客户端进行空闲检测,这样客户端也可以对服务器进行假死判定,在服务器假死的情况下,客户端可以发起重连。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/135713.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

外贸网站优化常用流程和一些常识

外贸网站google排名,总以为是单个网页标签的优化过程。 显然,这些观点都是错误的,九凌网络是做谷歌优化服务,九凌网络跟大家分享外贸网站Google优化常用流程和一些常识需要做以下几个步骤: 第一步:网站诊断&#xff0…

OpenHarmony 4.0 Release 编译异常处理

一、环境配置 编译环境:Ubuntu 20.04 OpenHarmony 软件版本:4.0 Release 设备平台:rk3568 二、下拉代码 参考官网步骤: OpenHarmony 4.0 Release 源码获取 repo init -u https://gitee.com/openharmony/manifest -b OpenHarmo…

接口测试 Mock 实战(二) | 结合 jq 完成批量化的手工 Mock

因为本章的内容是使用jq工具配合完成,因此在开始部分会先花一定的篇幅介绍jq机器使用,如果读者已经熟悉jq,可以直接跳过这部分。 先来看应用场景,App 经常会有一些信息展示的列表页,比如商家的菜品、股票的公司、文章的…

uni-app:js实现数组中的相关处理-数组复制

一、slice方法-浅拷贝 使用分析 创建一个原数组的浅拷贝,对新数组的修改不会影响到原数组slice() 方法创建了一个原数组的浅拷贝,这意味着新数组和原数组中的对象引用是相同的。因此,当你修改新数组中的对象时,原数组中相应位置的…

【网络】UDP协议

UDP协议 一、传输层1、再谈端口号2、两个命令 二、UDP协议1、UDP协议格式2、UDP的解包和分用3、UDP的特点4、UDP使用注意事项5、基于UDP的应用层协议 一、传输层 我们以前在学习HTTP等应用层协议时,为了便于理解,简单的认为HTTP协议是将请求和响应直接发…

如何使用 NFTScan NFT API 在 Arbitrum 网络上开发 Web3 应用

Arbitrum 是以太坊的 Layer 2 扩容方案,为以太坊面临的高 gas 费和网络拥堵问题,提供了一个解决方案。作为 Layer 1 的以太坊基础层受每秒只能验算 15 笔交易的限制,在目前以太坊使用需求庞大的情况下,局限了以太坊的可扩展性。Ar…

安全防御——四、防火墙理论知识

安全防御 一、防火墙1、防火墙是如何诞生的2、防火墙如何分类2.1 软件型防火墙2.1.1 个人防火墙2.1.2 网关型防火墙 3、硬件型防火墙4、防火墙的技术类型5、代理服务器什么是代理 6、防火墙的接口模式7、防火墙抵御的攻击7.1 DDoS攻击7.2 单包攻击7.3 用户行为不受控7.4 威胁安…

使用 Threejs 从基础开始构建 3D 地球

需求 threejs学习-3D 地球 实现: 1、使用粒子效果模拟宇宙星空 2、贴图、模型等资源的加载 3、加载资源的监听 4、效果合成器 EffectComposer 的初级使用 5、在地球上设置坐标以及坐标涟漪动画 6、标点间建立飞线 7、简单动画建议先浏览一遍git地址上代码&#xff…

xv6-x86在ubuntu14.04 i386下正常编译、调试,在ubuntu23.04下编译各种报错--google镜像

来源 原git仓库 xv6-x86(xv6-public) 文档 mit 6.828/2023/ 文档 MIT 6.828/2018/xv6/book-rev11.pdf 原readme 注: xv6-x86(xv6-public) 已经被放弃了, 原作者转向了xv6-riscvxv6-x86文档来源:mit-pdos/xv6-book.git, 它需要 heirloom-doctools 来编译成pdf&#x…

【论文笔记】UniPAD: A Universal Pre-training Paradigm for Autonomous Driving

原文链接:https://arxiv.org/pdf/2310.08370.pdf 1. 引言 过去的3D场景理解预训练方法多采用2D图像领域中的想法,可大致分为基于对比的方法和基于MAE的方法。 基于对比的方法通过对比损失,在特征空间中将相似的3D点拉进而将不相似的点分开…

这些机器视觉工程师犯法了,竟然在闲鱼或淘宝上卖公司的机器视觉程序架构源码

目录 ​从个人层面来讲:从公司层面来讲: ​从个人层面来讲: 个人是法盲,法律意识淡薄只是一方面,另外一个方面就是对于代码的所有权,以及代码的安全性重视不够。把机器视觉程序架构源码打包在闲鱼或淘宝上…

CCF ChinaSoft 2023 论坛巡礼 | NASAC青年软件创新奖论坛

2023年CCF中国软件大会(CCF ChinaSoft 2023)由CCF主办,CCF系统软件专委会、形式化方法专委会、软件工程专委会以及复旦大学联合承办,将于2023年12月1-3日在上海国际会议中心举行。 本次大会主题是“智能化软件创新推动数字经济与社…

网络服务退出一个问题的解析

一、问题 在实际开发中遇到一个问题,解决的过程虽然不长,但确实是想得比较多,总结一下,以供参考。这是一个网络通信的服务端而且使用的是别人封装好的库,通信等都没有问题,但在退出时会报一个错误&#xf…

云安全—Dashboard 攻击面

0x00 前言 众所周知,如果只是一味的REST接口或者命令行话的操作方式,就会变相的提高操作门款,并且不会有很好的呈现方式,所以就有了web ui的方式,也就是Dashboar面板,本篇主要讨论一下关于Dashboar面板的概…

Vue3使用 xlsx 导出excel 数据

一、安装 xlsx 库 首先,在你的 Vue 3 项目中使用 npm 或 yarn 安装 xlsx 库 npm install xlsx # 或 yarn add xlsx二、创建一个导出 Excel 的方法 在你的 Vue 组件中,创建一个方法来处理数据并导出 Excel。例如: // 引入 xlsx 库 import * …

asp.net人事管理信息系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio

一、源码特点 asp.net 人事管理信息系统是一套完善的web设计管理系统,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为vs2010,数据库为sqlserver2008,使用c#语言 开发 asp.net 人事管理系统1 应用技术…

做一个网站可以app封装打包?

app封装打包,有些网站可以打包APP,将网站转换为APP。不同的网站平台和工具可能具有不同的功能和限制,因此app封装打包需要根据具体情况选择适合的平台和工具。 一些网站平台提供了将网站转换为APP的功能,例如HBuilderX、Appgyver…

adb and 软件架构笔记

Native Service,这是Android系统里的一种特色,就是通过C或是C代码写出来的,供Java进行远程调用的Remote Service,因为C/C代码生成的是Native代码(机器代码),于是叫Native Service。 native服务…

怎么调整excel表里面所有单元格中,某个相同字体大小,单元格中其他文字大小不变?

环境: excel 2021 python3.8 问题描述: 怎么调整excel表里面所有单元格里面1这个字体大小,单元格里面其他文字不变? excel表里面。很多单元格都有1,1和文字都是10号字体,现在想把全部1字字体调整为16号其他字大小都不变 解决方案: 一、使用python来实现,经过测…

vivo 网络端口安全建设技术实践

作者:vivo 互联网安全团队 - Peng Qiankun 随着互联网业务的快速发展,网络攻击的频率和威胁性也在不断增加,端口是应用通信中的门户,它是数据进出应用的必经之路,因此端口安全也逐渐成为了企业内网的重要防线之一&…