Netty 性能优化与调试指南
Netty 是一款高性能的网络通信框架,其高性能得益于良好的设计和优化。但是在实际使用中,如果配置或实现不当,可能会导致性能下降或调试困难。本文将从性能优化和调试两方面入手,详细讲解如何在使用 Netty 时提高应用性能和诊断问题。
1. 性能优化
Netty 的性能主要受以下几个因素影响:线程模型、内存管理、编解码效率和网络配置。针对这些方面,以下是优化建议。
1.1 线程模型优化
1.1.1 合理配置线程池
Netty 使用 EventLoopGroup
作为线程池:
BossGroup
:处理连接请求,通常设置为单线程即可。WorkerGroup
:处理 I/O 操作,线程数可以设置为CPU 核心数 * 2
。
EventLoopGroup bossGroup = new NioEventLoopGroup(1); // 单线程
EventLoopGroup workerGroup = new NioEventLoopGroup(Runtime.getRuntime().availableProcessors() * 2); // 核心数 * 2
如果系统有较多的计算密集型任务,可以引入额外的 EventExecutorGroup
来执行耗时任务,避免阻塞 EventLoop
。
1.1.2 避免阻塞 I/O
Netty 是基于非阻塞 I/O 的框架,因此不建议在 ChannelHandler
中使用阻塞操作,如:
- 长时间的数据库查询。
- 文件 I/O 操作。
可以使用线程池或异步方式处理耗时任务:
EventExecutorGroup executorGroup = new DefaultEventExecutorGroup(4);
pipeline.addLast(executorGroup, new MyHandler());
1.2 内存管理优化
1.2.1 使用内存池
Netty 的 ByteBuf
提供了两种内存管理方式:
- Pooled:通过内存池分配和复用内存,适合高并发场景。
- Unpooled:每次分配独立内存块,适合小规模、简单场景。
建议开启内存池:
Bootstrap bootstrap = new Bootstrap();
bootstrap.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
1.2.2 避免内存泄漏
Netty 使用引用计数(Reference Counting)管理 ByteBuf
的内存。如果没有正确释放 ByteBuf
,可能会导致内存泄漏。
确保 ByteBuf
被正确释放:
@Override
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {try {// 处理 ByteBuf} finally {msg.release(); // 确保释放}
}
或者使用 SimpleChannelInboundHandler
,Netty 会自动释放消息:
public class MyHandler extends SimpleChannelInboundHandler<ByteBuf> {@Overrideprotected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) {// 不需要手动释放}
}
1.3 编解码优化
1.3.1 使用高效的序列化工具
Netty 提供了自定义协议的编解码能力,选择合适的序列化工具可以显著提升性能:
- Protobuf:Google 提供的高性能序列化框架。
- Kryo:高效的序列化工具,适合 Java 对象。
- JSON:易读性强,但性能稍逊。
示例:使用 Protobuf 编解码器:
pipeline.addLast(new ProtobufDecoder(MyMessage.getDefaultInstance()));
pipeline.addLast(new ProtobufEncoder());
1.3.2 减少粘包和拆包
对于大数据量传输,使用 Netty 的自带工具处理粘包和拆包问题:
LengthFieldBasedFrameDecoder
:通过数据头部的长度字段拆包。DelimiterBasedFrameDecoder
:通过分隔符拆包。
示例:
pipeline.addLast(new LengthFieldBasedFrameDecoder(65536, 0, 4, 0, 4));
pipeline.addLast(new LengthFieldPrepender(4));
1.4 网络配置优化
1.4.1 TCP 参数优化
- 开启
TCP_NODELAY
:减少延迟,提高小数据包的传输效率。 - 调整
SO_BACKLOG
:增加等待连接队列长度。 - 调整
SO_RCVBUF
和SO_SNDBUF
:优化缓冲区大小。
示例:
bootstrap.option(ChannelOption.TCP_NODELAY, true);
bootstrap.option(ChannelOption.SO_BACKLOG, 128);
bootstrap.option(ChannelOption.SO_RCVBUF, 32 * 1024);
bootstrap.option(ChannelOption.SO_SNDBUF, 32 * 1024);
1.4.2 使用直接内存
直接内存可以避免 Java 堆内存的复制,提升 I/O 性能:
bootstrap.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
2. 调试技巧
调试是保证程序稳定性的重要环节。Netty 提供了多种工具和方法帮助开发者快速诊断问题。
2.1 使用 LoggingHandler
LoggingHandler
是 Netty 提供的内置调试工具,可以记录所有 I/O 事件。
示例:
pipeline.addLast(new LoggingHandler(LogLevel.INFO));
2.2 捕获异常
确保在 ChannelHandler
中捕获异常,避免程序因未处理的异常而崩溃:
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {cause.printStackTrace();ctx.close();
}
2.3 启用 JVM 调试工具
- 使用 JProfiler 或 VisualVM:监控内存使用和线程运行状况。
- GC 日志:启用 GC 日志,分析垃圾回收对性能的影响。
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log
2.4 检查内存泄漏
Netty 提供了内存泄漏检测工具,可以在开发阶段启用:
System.setProperty("io.netty.leakDetection.level", "PARANOID");
泄漏检测级别:
- DISABLED:禁用泄漏检测。
- SIMPLE:默认级别,低开销。
- ADVANCED:更详细的检测。
- PARANOID:全面检测,适合开发和调试。
2.5 使用 Wireshark 监控网络流量
使用工具如 Wireshark 捕获和分析网络数据包,可以帮助发现粘包、拆包和数据传输中的问题。
2.6 使用 Netty 的性能调试工具
Netty 提供了内部的性能分析工具:
- EventLoop 监控:监控事件循环的任务执行时间。
- ByteBuf 分析:分析内存分配和释放情况。
3. 性能优化案例
以下是一个实际优化案例的简单实现:
public class OptimizedNettyServer {public static void main(String[] args) throws InterruptedException {EventLoopGroup bossGroup = new NioEventLoopGroup(1);EventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap bootstrap = new ServerBootstrap();bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childOption(ChannelOption.TCP_NODELAY, true).childOption(ChannelOption.SO_KEEPALIVE, true).childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT).childHandler(new ChannelInitializer<Channel>() {@Overrideprotected void initChannel(Channel ch) throws Exception {ch.pipeline().addLast(new LoggingHandler(LogLevel.INFO));ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(65536, 0, 4, 0, 4));ch.pipeline().addLast(new MyBusinessHandler());}});ChannelFuture future = bootstrap.bind(8080).sync();System.out.println("Server started on port 8080");future.channel().closeFuture().sync();} finally {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}
}
4. 总结
通过本文,您可以系统性地优化 Netty 的性能,并使用调试工具定位和解决问题:
性能优化要点:
- 合理配置线程模型。
- 使用内存池和零拷贝技术。
- 选择高效的序列化方式。
- 配置 TCP 参数以提高网络性能。
调试要点:
- 使用
LoggingHandler
和内存泄漏检测工具。 - 捕获和处理异常。
- 借助外部工具(如 Wireshark 和 JProfiler)进行深度分析。
通过这些优化和调试方法,您可以构建更高效、更稳定的 Netty 应用程序。
相关文章:
Netty 性能优化与调试指南
Netty 是一款高性能的网络通信框架,其高性能得益于良好的设计和优化。但是在实际使用中,如果配置或实现不当,可能会导致性能下降或调试困难。本文将从性能优化和调试两方面入手,详细讲解如何在使用 Netty 时提高应用性能和诊断问题…...
网络安全产品之认识WEB应用防火墙
随着B/S架构的广泛应用,Web应用的功能越来越丰富,蕴含着越来越有价值的信息,应用程序漏洞被恶意利用的可能性越来越大,因此成为了黑客主要的攻击目标。传统防火墙无法解析HTTP应用层的细节,对规则的过滤过于死板&#…...
R学习——因子
目录 1 定义因子(factor函数) 2因子的作用 一个数据集中的 只需要考虑可以用哪个数据来进行分类就可以了,可以用来分类就可以作为因子。 Cy1这个因子对应的水平level是4 6 8: 1 定义因子(factor函数) 要…...
2024 亚马逊云科技re:Invent:Werner Vogels架构哲学,大道至简 六大经验助力架构优化
在2024亚马逊云科技re:Invent全球大会第四天的主题演讲中,亚马逊副总裁兼CTO Dr.Werner Vogels分享了 The Way of Simplexity,繁简之道,浓缩了Werner在亚马逊20年构建架构的经验。 Werner表示,复杂性总是会“悄无声息”地渗透进来…...
【代码随想录day58】【C++复健】 117. 软件构建(拓扑排序);47. 参加科学大会(dijkstra(朴素版)精讲)
117. 软件构建(拓扑排序) 继续边看解析边做题,思考时的问题做个如下的总结: 1. 存边用什么数据结构? 在题目中,我们需要存储节点之间的依赖关系(边信息)。选择适合的数据结构非常重…...
单目深度估计模型 lite-mono 测试
lite-mono 使用工业数据集kitti 进行训练,目的使用单目摄像头实现物体深度预测,关于kitti数据集的介绍和下载参考 (二)一文带你了解KITTI数据集-CSDN博客文章浏览阅读2.7w次,点赞64次,收藏294次。文章介绍…...
JAVA基础学习笔记_网络编程
文章目录 网络编程网络编程三要素IPIPv4细节InetAddress 端口号协议 UDPUDP协议(发数据)UDP协议(接受数据)UDP聊天室单播,组播,广播 TCP中文乱码问题代码细节,三次握手和四次挥手 网络编程 计算机之间通过网络进行数据传输 软件结构 C/S,Client/Server,客户端服务器,精美但麻…...
说下JVM中一次完整的GC流程?
大家好,我是锋哥。今天分享关于【说下JVM中一次完整的GC流程?】面试题。希望对大家有帮助; 说下JVM中一次完整的GC流程? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在JVM中,垃圾回收(GC&am…...
鸿蒙NEXT开发案例:保质期计算
【引言】 保质期计算应用是一个基于鸿蒙NEXT框架开发的数字和文本统计组件。用户可以输入商品的生产日期和保质期天数,应用会自动计算并展示相关信息,包括保质状态、剩余天数、生产日期和到期日期。 【环境准备】 • 操作系统:Windows 10 …...
LLM并发加速部署方案(llama.cpp、vllm、lightLLM、fastLLM)
大模型并发加速部署 解析当前应用较广的几种并发加速部署方案! llama.cpp、vllm、lightllm、fastllm四种框架的对比: llama.cpp:基于C,①请求槽,②动态批处理,③CPU/GPU混合推理vllm:基于Pyth…...
用最小的代价解决mybatis-plus关于批量保存的性能问题
1.问题说明 问题背景说明,在使用达梦数据库时,mybatis-plus的serviceImpl.saveBatch()方法或者updateBatchById()方法的时候,随着数据量、属性字段的增加,效率越发明显的慢。 serviceImpl.saveBatch(); serviceImpl.updateBatch…...
蓝桥杯历届真题 --#递推 翻硬币(C++)
文章目录 思路完整代码结语 原题链接 思路 通过观察测试用例,我们猜测,从左到右依次对比每一个位置上的状态,如果不一样我们就翻一次,最终得到的答案即为正解。 完整代码 //这里是引入了一些常用的头文件,和一些常规操作 //第一…...
BurpSuite-8(FakeIP与爬虫审计)
声明:学习视频来自b站up主 泷羽sec,如涉及侵权马上删除文章 感谢泷羽sec 团队的教学 视频地址:IP伪造和爬虫审计_哔哩哔哩_bilibili 一、FakeIP 1.配置环境 BurpSuite是java环境下编写的,而今天的插件是python编写的,…...
JAVA8、Steam、list运用合集
Steam运用 Java Stream API为开发人员提供了一种函数式和声明式的方式来表达复杂的数据转换和操作,使代码更加简洁和富有表现力。 1、使用原始流以获得更好的性能【示例:求和】 使用 int、long 和 double 等基本类型时,请使用IntStream、LongStream 和 DoubleStream 等基本流…...
深入详解人工智能机器学习:强化学习
目录 强化学习概述 强化学习的基本概念 定义 关键组件 强化学习过程 常用算法 应用示例 示例代码 代码解释 应用场景 强化学习核心概念和底层原理 核心概念 底层原理 总结 强化学习概述 强化学习(Reinforcement Learning, RL)是机器学习中的…...
docker的简单使用
文章目录 docker简介docker架构镜像和容器镜像有关的常用命令容器相关常用命令 docker简介 Docker是一个开源的应用容器引擎,基于Go语言并遵从Apache2.0协议开源。 Docker可以让开方子打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到…...
启动的docker容器里默认运行dockerd
问题 已在Dockerfile里yum install docker 但docker run 启动容器后, docker ps等命令无法执行 ps -aux 没有dockerd 进程 临时解决 另开一个终端 docker exec -it 容器名 bash 手动启 dockerd 默认启动 分析 现在启动容器的默认命令是 /sbin/init sbin/init 是根文件系统…...
Python爬虫技术的最新发展
在互联网的海洋中,数据就像是一颗颗珍珠,而爬虫技术就是我们手中的潜水艇。2024年,爬虫技术有了哪些新花样?让我们一起潜入这个话题,看看最新的发展和趋势。 1. 异步爬虫:速度与激情 随着现代Web应用的复…...
什么是厄尔米特(Hermitian)矩阵?
厄米矩阵(Hermitian Matrix)定义 在数学和物理中,厄米矩阵是满足以下条件的复方阵: A A † \mathbf{A}\mathbf{A}^\dagger AA† 其中, A † \mathbf{A}^\dagger A†表示矩阵 A \mathbf{A} A的共轭转置,即…...
从零开始:Linux 环境下的 C/C++ 编译教程
个人主页:chian-ocean 文章专栏 前言: GCC(GNU Compiler Collection)是一个功能强大的编译器集合,支持多种语言,包括 C 和 C。其中 gcc 用于 C 语言编译,g 专用于 C 编译。 Linux GCC or G的安…...
Excel + Notepad + CMD 命令行批量修改文件名
注意:该方式为直接修改原文件的文件名,不会生成新文件 新建Excel文件 A列:固定为 renB列:原文件名称C列:修改后保存的名称B列、C列,需要带文件后缀,为txt文件就是.txt结尾,为png图片…...
1.1 android:监听并处理返回事件
在Android开发过程中,默认执行返回事件是结束当前界面,返回上一个界面,没有任何提示,但用户可能会误操作,这时出现一个提示界面对用户较为友好,接下来,让我们探究返回事件的处理。 一、onBackP…...
解决Ubuntu关机主板不断电的问题(其它使用GRUB的Linux发行版大概率也可用)
前言: 在某些主板上,Ubuntu20.04系统关机并不会连带主板一起断电。 猜测可能是主板太老了。无法识别较新的系统的关机信号,导致无法断电。连带着一些电脑周边设备也不会断电导致状态无法重置,后续会出现一些问题。 目标…...
【CTF-Web】文件上传漏洞学习笔记(ctfshow题目)
文件上传 文章目录 文件上传 What is Upload-File?Upload-File In CTF Web151 考点:前端校验解题: Web152 考点:后端校验要严密解题: Web153 考点:后端校验 配置文件介绍解题: Web154 考点&am…...
无法正常启动此程序,因为计算机丢失wlanapi.dll
wlanapi.dll丢失怎么办?有没有什么靠谱的修复wlanapi.dll方法_无法启动此程序,因为计算机中丢失wlanapi.dll-CSDN博客 wlanapi.dll是 Windows 操作系统中的一个动态链接库文件,主要与 Windows 无线 LAN (WLAN) API 相关。该DLL提供了许多必要的函数&…...
C++ webrtc开发(非原生开发,linux上使用libdatachannel库)
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、libdatachannel库的下载和build二、开始使用 1.2.引入库3.开始使用 总结 前言 使用c开发webrtc在互联网上留下的资料甚少,经过我一段时间的探…...
vue-router路由传参的两种方式(params 和 query )
一、vue-router路由传参问题 1、概念: A、vue 路由传参的使用场景一般应用在父路由跳转到子路由时,携带参数跳转。 B、传参方式可划分为 params 传参和 query 传参; C、而 params 传参又可分为在 url 中显示参数和不显示参数两种方式&#x…...
VBA高级应用30例应用在Excel中的ListObject对象:向表中添加注释
《VBA高级应用30例》(版权10178985),是我推出的第十套教程,教程是专门针对高级学员在学习VBA过程中提高路途上的案例展开,这套教程案例与理论结合,紧贴“实战”,并做“战术总结”,以…...
github操作学习笔记(杂乱版)
git开源的分布式版本控制系统: 每次修改文件提交后,都会自动创建一个项目版本 查看git版本看有没有安装成功:git --version 把默认编辑器设置成vim:git config --global core.editor "vim" 1、设置昵称和邮箱ÿ…...
TaskBuilder SQL执行工具
为了方便开发者连接当前任擎服务器上配置的各个数据源对应的数据库进行相关操作,TaskBuilder提供了一个SQL执行工具,点击系统侧边栏里的执行SQL图标 ,即可打开该工具,界面如下图所示: 该工具从上至下分为三个区域&a…...
快速掌握Quartz.Net计划任务调度框架,轻松实现定时任务
前言 Quartz.Net是一个开源的作业调度框架,可以用于管理计划任务和定期执行。Quartz.Net提供了丰富的作业计划选项,例如精确或模糊时间表达式、日期和时间限制等。Quartz.Net采用分布式架构,允许在多个计算机上运行任务。 Quartz.Net架构设…...
Linux ufw命令丨Linux网络防火墙ufw命令详解
ufw(Uncomplicated Firewall)是Ubuntu系统上默认的防火墙组件,它为轻量化配置iptables而开发,提供了一个非常友好的界面用于创建基于IPv4和IPv6的防火墙规则 ufw在Ubuntu 8.04 LTS后的所有发行版中默认可用,它通过命令…...
shell编程(完结)
shell编程(完结) 声明! 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章 笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其…...
深入了解Text2SQL开源项目(Chat2DB、SQL Chat 、Wren AI 、Vanna)
深入了解Text2SQL开源项目(Chat2DB、SQL Chat 、Wren AI 、Vanna) 前言1.Chat2DB2.SQL Chat3.Wren AI4.Vanna 前言 在数据驱动决策的时代,将自然语言查询转化为结构化查询语言(SQL)的能力变得日益重要。无论是小型创业…...
【Linux】报错:cannot create directory ‘test’: Read-only file system
1 报错 ❤️在使用mkdir test命令创建文件夹的时候,报错如下: mkdir:cannot create directory ‘test’:Read-only file system 2 解决方法 mount -o remount,rw / 🦋上述命令在Linux系统中用于重新挂载(root)文件系统,并将其从只读模式切换到读写模式。 ■ 下面是对…...
python mat是什么文件
.mat就是matlab的文件格式,一般用于matlab和python间的数据传输,python中numpy和scipy提供了一些函数,可以很好的对.mat文件的数据进行读写和处理。 在python中可以使用scipy.io中的函数loadmat()读取mat文件,函数savemat保存文…...
Redis: 一个高效的内存数据存储解决方案
Redis: 一个高效的内存数据存储解决方案 介绍 Redis(Remote Dictionary Server)是一种开源的高性能键值存储系统。它常被用作缓存、消息队列、会话存储、实时数据分析等多种场景。与传统的关系型数据库不同,Redis 是基于内存的数据存储&…...
AR眼镜_消费级工业AR智能眼镜主板硬件解决方案
AR眼镜的研发是一项复杂的软硬件集成工程,它需要在摄影、音频、交互和连接等多个方面提供卓越的基础体验,因此产品的每个细节都显得尤为重要。 在设计AR眼镜时,重量、体积和散热性能都是必须认真考量的关键因素。在芯片平台的选择上ÿ…...
C# 异常处理
C# 异常处理 异常处理是编程中不可或缺的一部分,它允许程序在遇到错误或意外情况时优雅地处理这些问题,而不是直接崩溃。C# 提供了一套强大的异常处理机制,包括 try-catch 块、finally 块和 throw 语句。本文将深入探讨 C# 中的异常处理,包括如何捕获和处理异常,以及如何…...
图解SSH原理
1. 初见SSH SSH是一种协议标准,其目的是实现安全远程登录以及其它安全网络服务。 SSH仅仅是一协议标准,其具体的实现有很多,既有开源实现的OpenSSH,也有商业实现方案。使用范围最广泛的当然是开源实现OpenSSH。 2. SSH工作原理 …...
如何快速批量把 PDF 转为 JPG 或其它常见图像格式?
在某些特定场景下,将 PDF 转换为 JPG 图片格式却具有不可忽视的优势。例如,当我们需要在不支持 PDF 查看的设备或软件中展示文档内容时,JPG 图片能够轻松被识别和打开;此外,对于一些网络分享或社交媒体发布的需求&…...
在CentOS中安装和卸载mysql
在CentOS7中安装和卸载mysql 卸载mysql1、查看是否安装过mysql2、查看mysql服务状态3、关闭mysql服务4、卸载mysql相关的rpm程序5、删除mysql相关的文件6、删除mysql的配置文件my.cnf 安装mysql1、下载mysql相关的rpm程序2、检查/tmp临时目录权限3、安装mysql前的依赖检查3、安…...
第十二章:异常(2)
六、自定义异常类 1. 定义一个类继承 异常类 (1) 定义异常类如果为运行时异常,则需要继承 RuntimeException class CheckedPasswordException extends RuntimeException{} (2) 定义异常类如果为非运行时异常,则需要继承 Exception class CheckedPass…...
DAY5 C++运算符重载
1.类实现> 、<、!、||、!和后自增、前自减、后自减运算符的重载 代码: #include <iostream>using namespace std; class Complex {int rel;int vir; public:Complex(){};Complex(int rel,int vir):rel(rel),vir(vir){cout << "…...
Qt之点击鼠标右键创建菜单栏使用(六)
Qt开发 系列文章 - menu(六) 目录 前言 一、示例演示 二、菜单栏 1.MenuBar 2.Menu 总结 前言 QMainWindow是一个为用户提供主窗口程序的类,包含一个菜单栏(menubar)、多个工具栏(toolbars)、一个状态栏(status…...
Ant Design Pro实战--day01
下载nvm https://nvm.uihtm.com/nvm-1.1.12-setup.zip 下载node.js 16.16.0 //非此版本会报错 nvm install 16.16.0 安装Ant Design pro //安装脚手架 npm i ant-design/pro-cli -g //下载项目 pro create myapp //选择版本 simple 安装依赖 npm install 启动umi yarn add u…...
ejb组件(rmi) webservice平台(xml)
springboot bean 在 Spring Boot 中,Bean 是 Spring 框架的核心概念之一,表示由 Spring 容器管理的对象。通过 Bean 或其他注解(如 Component、Service、Repository 等)来定义和管理这些对象。以下是关于 Spring Boot 中 Bean 的…...
[高考] 学习数学的难点
最近想看一些机器学习的书,发现很多概念,很多符号,很多地方是,不知道具体的意思,不懂其中的内涵,所以需要再重新查阅很多的资料,去理解作者每句话是什么意思。 总结一下难点。以詹姆斯-斯图尔特…...
西门子200 smart PLC助力水处理企业自动化改造
摘要 西门子的200SMART PLC,以其强大的功能和灵活的应用性,正成为环保行业中不可或缺的一环。今天,我们就来看看这个小小的PLC是如何在处理环保问题中大显身手的。 不得不说,环保行业的痛点可不少。 比如污水处理,传…...
redis 怎么样查看list
在 Redis 中,可以通过以下方法查看列表的内容或属性: 1. 查看列表中的所有元素 使用 LRANGE 命令: LRANGE key start endkey 是列表的名称。start 是起始索引,0 表示第一个元素。end 是结束索引,-1 表示最后一个元素…...