【Netty】客户端功能完善

超时控制

public class RequestTimeoutManager {private final HashedWheelTimer timer = new HashedWheelTimer();private final ConcurrentMap<Long, Timeout> pendingRequests = new ConcurrentHashMap<>();public void addRequest(long requestId, long timeoutMillis, Runnable timeoutCallback) {Timeout timeout = timer.newTimeout(timeout -> {pendingRequests.remove(requestId);timeoutCallback.run();}, timeoutMillis, TimeUnit.MILLISECONDS);pendingRequests.put(requestId, timeout);}public void removeRequest(long requestId) {Timeout timeout = pendingRequests.remove(requestId);if (timeout != null) {timeout.cancel();}}
}public class RequestFuture<T> {private final CompletableFuture<T> future = new CompletableFuture<>();private final long requestId;private final long timeoutMillis;private final RequestTimeoutManager timeoutManager;public RequestFuture(long requestId, long timeoutMillis, RequestTimeoutManager timeoutManager) {this.requestId = requestId;this.timeoutMillis = timeoutMillis;this.timeoutManager = timeoutManager;setupTimeout();}private void setupTimeout() {timeoutManager.addRequest(requestId, timeoutMillis, () -> future.completeExceptionally(new TimeoutException("Request timeout after " + timeoutMillis + "ms")));}public CompletableFuture<T> getFuture() {return future;}public void complete(T result) {timeoutManager.removeRequest(requestId);future.complete(result);}
}public class NettyClientHandler {private final RequestTimeoutManager timeoutManager = new RequestTimeoutManager();private static final long DEFAULT_TIMEOUT = 3000; // 3秒public CompletableFuture<LoginResponse> login(LoginRequest request) {long requestId = generateRequestId();RequestFuture<LoginResponse> future = new RequestFuture<>(requestId, DEFAULT_TIMEOUT, timeoutManager);// 发送请求channel.writeAndFlush(request);return future.getFuture();}// 使用示例public void example() {LoginRequest request = new LoginRequest();login(request).thenAccept(response -> {// 处理响应}).exceptionally(throwable -> {if (throwable instanceof TimeoutException) {// 处理超时}return null;});}
}
超时机制优点
  1. 多层次超时控制:连接建立、请求响应超时、整队不同请求设置不同超时时间
  2. 使用HashedWheelTimer实现定时器,内存占用下、时间精度可控
  3. 异常处理机制,超时自动触发异常,支持异步处理超时情况,方便进行重试

心跳

public class HeartbeatHandler extends ChannelDuplexHandler {private static final int READER_IDLE_TIME = 15; // 读超时时间private static final int WRITER_IDLE_TIME = 5;  // 写超时时间private static final int ALL_IDLE_TIME = 20;    // 总超时时间private final AtomicInteger lostHeartbeatCount = new AtomicInteger(0);private final ConnectionManager connectionManager;@Overridepublic void handlerAdded(ChannelHandlerContext ctx) {ctx.pipeline().addBefore(ctx.name(), "idleStateHandler",new IdleStateHandler(READER_IDLE_TIME, WRITER_IDLE_TIME, ALL_IDLE_TIME, TimeUnit.SECONDS));}@Overridepublic void userEventTriggered(ChannelHandlerContext ctx, Object evt) {if (evt instanceof IdleStateEvent) {IdleStateEvent event = (IdleStateEvent) evt;switch (event.state()) {case READER_IDLE:handleReaderIdle(ctx);break;case WRITER_IDLE:handleWriterIdle(ctx);break;case ALL_IDLE:handleAllIdle(ctx);break;}}}private void handleReaderIdle(ChannelHandlerContext ctx) {int count = lostHeartbeatCount.incrementAndGet();if (count > 3) {  // 连续3次没收到心跳,判定连接断开log.warn("连续{}次未收到心跳,关闭连接", count);ctx.close();connectionManager.scheduleReconnect();} else {log.warn("读空闲超时,第{}次", count);}}private void handleWriterIdle(ChannelHandlerContext ctx) {// 发送心跳包HeartbeatMessage heartbeat = new HeartbeatMessage();ctx.writeAndFlush(heartbeat).addListener(future -> {if (!future.isSuccess()) {log.error("发送心跳包失败", future.cause());ctx.close();}});}private void handleAllIdle(ChannelHandlerContext ctx) {log.warn("全局空闲超时,关闭连接");ctx.close();connectionManager.scheduleReconnect();}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) {if (msg instanceof HeartbeatMessage) {// 收到心跳响应,重置计数器lostHeartbeatCount.set(0);}ctx.fireChannelRead(msg);}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {log.error("心跳处理异常", cause);ctx.close();}
}

需要配合IdleStateHandler处理器使用

支持多级超时检测
  1. 读空闲超时:检测服务器是否存活
  2. 写空闲超时:触发心跳包发送
  3. 全局空闲超时:作为最后的保障
渐进式处理
  1. 连续多次心跳失败才断开连接
  2. 支持重连机制
状态管理
  1. 使用原子技术器记录失败次数
  2. 收到心跳响应时重置计数
  3. 异常情况自动断开重连
可配置性
  1. 超时时间可配置
  2. 失败重试次数可配置
  3. 心跳间隔可配置

流量控制

public class CustomTrafficShapingHandler extends ChannelDuplexHandler {private final GlobalTrafficShapingHandler globalTrafficHandler;public CustomTrafficShapingHandler(EventLoopGroup group,long writeLimit,        // 写入速率限制,单位为字节/秒long readLimit,         // 读取速率限制,单位为字节/秒long checkInterval      // 检查间隔,单位为毫秒) {this.globalTrafficHandler = new GlobalTrafficShapingHandler(group, writeLimit, readLimit, checkInterval);}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) {// 当收到数据时,通过令牌桶算法控制读取速率globalTrafficHandler.channelRead(ctx, msg);}@Overridepublic void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {// 当发送数据时,通过令牌桶算法控制发送速率globalTrafficHandler.write(ctx, msg, promise);}
}

GlobalTrafficShapingHandlernetty提供的流量整形处理器,主要通过领票捅算法来实现流量控制,工作原理:

  1. 令牌桶的算法
    • 系统按照设定的速率往桶里放入令牌
    • 每次读写操作都需要消耗令牌
    • 如果桶里没有足够的令牌,操作会被延迟执行
  2. 使用示例:
// 配置:写入限制 1MB/s,读取限制 1MB/s,检查间隔 1秒
CustomTrafficShapingHandler handler = new CustomTrafficShapingHandler(group,1 * 1024 * 1024,  // 写入限制:1MB/s1 * 1024 * 1024,  // 读取限制:1MB/s1000              // 检查间隔:1秒
);

异常重试机制

public class RetryPolicy {private final int maxAttempts;private final long initialRetryDelay;public <T> CompletableFuture<T> execute(Supplier<CompletableFuture<T>> action) {return executeWithRetry(action, 0);}private <T> CompletableFuture<T> executeWithRetry(Supplier<CompletableFuture<T>> action, int attempt) {return action.get().exceptionally(throwable -> {if (attempt < maxAttempts && isRetryable(throwable)) {return executeWithRetry(action, attempt + 1).join();}throw new CompletionException(throwable);});}
}
优点
  1. 集中处理所有异常
  2. 不同类型异常有不同的处理策略
  3. 支持自动重连机制
  4. 异常日志记录
  5. 优雅处理连接断开

优雅关闭

public class ShutdownHook {private final NettyClient client;private final ExecutorService executorService;public void registerShutdownHook() {Runtime.getRuntime().addShutdownHook(new Thread(() -> {client.shutdown();executorService.shutdown();try {executorService.awaitTermination(5, TimeUnit.SECONDS);} catch (InterruptedException e) {Thread.currentThread().interrupt();}}));}
}

监控指标收集

public class MetricsHandler extends ChannelDuplexHandler {private final MeterRegistry registry;@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) {Timer.Sample sample = Timer.start(registry);try {ctx.fireChannelRead(msg);} finally {sample.stop(registry.timer("netty.request.time"));registry.counter("netty.request.count").increment();}}
}

SSL/TLS支持

public class SslContextFactory {public static SslContext createSslContext() {return SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();}
}

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

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

相关文章

【鸿蒙开发】Hi3861学习笔记- DS18B20温度传感器

00. 目录 文章目录 00. 目录01. DS18B20简介02. DS18B20引脚及电路03. DS18B20内部结构框图04. DS18B20内存映射05. 硬件设计06. 软件设计07. 实验现象08. 附录 01. DS18B20简介 DS18B20 是常用的数字温度传感器&#xff0c;其输出的是数字信号&#xff0c;具有体积小&#xf…

跨境大文件传输如何突破延迟与丢包双重困局

一、行业痛点&#xff1a;跨国传输的挑战 在全球化业务场景中&#xff0c;跨境大文件传输常面临网络延迟高、丢包率频发等问题。传统TCP协议因其“先建联再传输”的机制&#xff0c;在高时延、高丢包环境下效率骤降&#xff0c;导致跨国协作、影视渲染、科研数据共享等场景中传…

uni-app——计时器和界面交互API

API 基本概要 概念说明 API&#xff08;应用程序接口&#xff09;是预先定义的方法集合&#xff0c;用于实现特定功能。在 uni-app 中&#xff0c;通过全局对象 uni 调用 API&#xff0c;例如 uni.getSystemInfoSync 获取设备信息。 API 分类与调用规则 事件监听型 以 on 开…

Dify 升级攻略:从0.15.3迈向1.1.0,元数据管理全攻略!

嘿&#xff0c;小伙伴们&#xff01;今天给大家带来一个超实用的干货分享——Dify从0.15.3升级到1.1.0版本的详细攻略。这次升级不仅带来了功能上的更新&#xff0c;还特别强化了元数据管理。相信很多小伙伴和我一样&#xff0c;一直在使用Dify来提升工作效率&#xff0c;但每次…

15.三数之和-力扣(python)

给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以包含重复的三元组。 示例 1&a…

numpy学习笔记14:模拟随机游走过程

numpy学习笔记14&#xff1a;模拟随机游走过程 随机游走是一种数学统计模型&#xff0c;其中的每一步方向和大小都是随机的。下面使用 NumPy 模拟一维和二维的随机游走过程&#xff1a; 1.代码示例 import numpy as np import matplotlib.pyplot as plt plt.rcParams[font.s…

YOLOv11 目标检测

本文章不再赘述anaconda的下载以及虚拟环境的配置&#xff0c;博主使用的python版本为3.8 1.获取YOLOv11的源工程文件 链接&#xff1a;GitHub - ultralytics/ultralytics: Ultralytics YOLO11 &#x1f680; 直接下载解压 2.需要自己准备的文件 文件结构如下&#xff1a;红…

dijkstra算法——47. 参加科学大会

卡码网:47. 参加科学大会https://kamacoder.com/problempage.php?pid=1047 题目描述 小明是一位科学家,他需要参加一场重要的国际科学大会,以展示自己的最新研究成果。 小明的起点是第一个车站,终点是最后一个车站。然而,途中的各个车站之间的道路状况、交通拥堵程度以…

Rust语言介绍和猜数字游戏的实现

文章目录 Rust语言介绍和猜数字游戏的实现cargo是什么使用Rust编写猜数字 Rust语言介绍和猜数字游戏的实现 Rust语言是一种系统编程语言&#xff0c;核心强调安全性、并发性以及高性能&#xff0c;由类似于C/C的底层控制能力&#xff0c;性能也非常接近&#xff0c;Rust有一些…

Ubuntu下Docker部署Misskey:打造你的去中心化社交平台

引言 在信息爆炸的时代&#xff0c;人们对于社交平台的需求日益增长&#xff0c;同时也更加注重数据的隐私和自由。Misskey作为一个开源的去中心化社交平台&#xff0c;为用户提供了一个全新的选择。本文将详细介绍如何在Ubuntu Linux环境下&#xff0c;利用Docker快速部署Mis…

DeepSeek Chat 自动化交互技术分析

本文将对 DeepSeek Chat 自动化交互脚本进行技术分析&#xff0c;包括代码结构、实现原理以及关键技术点。该脚本使用 Selenium 实现了对 DeepSeek Chat 平台的自动化登录和问答功能。 1. 代码结构概览 该脚本主要由以下几个部分组成&#xff1a; 环境准备与依赖导入&#x…

128. Longest Consecutive Sequence

如果n-1存在于数组中&#xff0c;则以n开头的连续序列可以忽略掉&#xff0c;因为以n-1开头的连续序列的长度肯定至少比以n开头的连续序列长1个元素。这是本题的关键。然后利用哈希表查询元素是否在数组中。 class Solution { public:int longestConsecutive(vector<int>…

《SQL编程思想》中的 MySQL 建表语句和测试数据

《SQL编程思想》中的 MySQL 建表语句 建表语句 -- 创建 4 个示例表和索引 CREATE TABLE department( dept_id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 部门编号&#xff0c;自增主键, dept_name VARCHAR(50) NOT NULL COMMENT 部门名称) ENGINEInnoDB COMM…

基于ssm学科竞赛小程序的设计及实现(源码+lw+部署文档+讲解),源码可白嫖!

摘要 随着信息时代的来临&#xff0c;过去的学科竞赛管理方式的缺点逐渐暴露&#xff0c;本次对过去的学科竞赛管理方式的缺点进行分析&#xff0c;采取计算机方式构建学科竞赛小程序。本文通过阅读相关文献&#xff0c;研究国内外相关技术&#xff0c;提出了一种关于竞赛信息…

【redis】什么是持久化之 RDB

什么是持久化 MySQL 的事务&#xff0c;有四个比较核心的特性&#xff1a; 原子性一致性持久性>持久化&#xff08;说的一回事&#xff09; 把数据存储在硬盘上>持久把数据存在内存上>不持久重启进程/重启主机之后&#xff0c;数据是否还存在 隔离性 Redis 是一个内存…

Python 鼠标轨迹算法 - 防止游戏检测

一.简介 鼠标轨迹算法是一种模拟人类鼠标操作的程序&#xff0c;它能够模拟出自然而真实的鼠标移动路径。 鼠标轨迹算法的底层实现采用C/C语言&#xff0c;原因在于C/C提供了高性能的执行能力和直接访问操作系统底层资源的能力。 鼠标轨迹算法具有以下优势&#xff1a; 模拟…

游戏立项时期随笔记录(1)

模拟经营的项目还没有完全结束&#xff0c;这几天又有可能涉及到一个新项目。感想随笔记录一下&#xff0c;防止忘记。今天一天整理这个&#xff0c;搞得今天没时间看数学和AI。 在 Unity3D 游戏前端主程序的立项时期&#xff0c;核心目标是明确技术方向、评估可行性、搭建基础…

Channel-wise Knowledge Distillation for Dense Prediction论文阅读和

paper&#xff1a;https://arxiv.org/pdf/2011.13256.pdf code&#xff1a;https://github.com/open-mmlab/mmrazor 这篇paper主要是商汤开源的mmrazor中提及在detection有效果&#xff0c;我之前记录的几篇sota文章虽然在各自的paper中在detection领域都有提及有增益&#…

hide函数的使用方法

在编程中&#xff0c;我们常常需要控制元素的显示与隐藏。特别是在前端开发中&#xff0c;hide 函数是一个非常常见的操作&#xff0c;尤其是在 JavaScript 和 jQuery 中。它可以让你轻松地将元素从视图中隐藏&#xff0c;进而提升用户交互体验和页面的响应能力。本文将介绍如何…

【MySQL】基本操作 —— DML 与约束

目录 DML 基本介绍DML 常见操作添加数据 insert给指定字段添加数据给全部字段添加数据给指定字段批量添加数据给全部字段批量添加数据 修改数据 update删除数据 delete 约束基本概念约束操作主键约束添加单列主键添加多列主键&#xff08;联合主键&#xff09;修改表结构添加主…