摘 要
如何才能让同样的硬件服务器发挥出最佳性能?本文通过对实际项目中安全管理平台服务器性能测试调优的实战经验分享,深入剖析了 Tomcat 和 ElasticSearch 的性能问题及调优方法,同时探讨了性能测试数据模型的优化策略。通过一系列调优措施前后的数据对比,展示了调优的显著效果。
01
Tomcat 性能测试调优
在对平台进行性能压测时,发现系统的吞吐量(TPS - Transactions Per Second)始终无法达到预期目标。经过深入排查,初步判断问题根源在于 Tomcat 的线程池配置。当大量并发请求涌入时,线程池中的可用线程数量迅速耗尽,新的请求不得不等待线程资源的释放,从而导致整体处理效率低下,TPS 增长受限。
线程池的概念
线程池是一种用于管理线程的技术机制。它预先创建一定数量的线程,并将这些线程保存在一个 “池子” 中。当有任务需要执行时,无需每次都重新创建线程,而是直接从线程池中获取一个空闲线程,让其负责处理该任务,使用完毕后再将线程归还到池中,以供后续任务复用。这样可以大大减少线程创建与销毁所带来的开销,提高系统性能与资源利用率。
以一个简单的生活场景类比,线程池就像是一个公共工具租赁仓库。仓库预先准备了一批工具(相当于线程池中的线程),当人们需要干活时,直接从仓库里取一件工具来使用,等活干完了,再把工具归还到仓库(类比任务执行完后线程的归还),而不需要每次干活都去新买一件工具,节省了成本与时间。
图1 Tomcat线程池
线程池优点
资源复用:避免频繁创建和销毁线程带来的系统开销,降低资源浪费,提升系统响应速度。如在高并发的 Web 应用中,快速响应大量用户请求。
控制并发:通过设置线程池大小,合理限制系统同时处理的任务数量,防止因过多线程导致系统资源耗尽而崩溃。例如,防止因过多数据库连接耗尽数据库服务器资源。
线程池缺点
线程管理开销:线程池本身需要维护线程的状态、调度等信息,这会占用一定的系统资源,尤其在大规模线程池场景下较为明显。
线程池工作原理
Tomcat 的线程池工作原理如下:当有客户端请求到达时,线程池首先检查是否有空闲线程。如果存在空闲线程,就将该请求分配给空闲线程进行处理;若当前没有空闲线程,且线程池中的线程数量尚未达到最大线程数限制,线程池会创建一个新的线程来处理该请求;然而,一旦线程数量达到最大值,后续新到达的请求将被放入等待队列中,直到有线程完成任务并空闲下来,再从队列中取出请求进行处理。
图2 Tomcat线程池工作流程
线程池调优方法
根据服务器硬件配置(如 CPU 核心数、内存大小)以及实际业务的并发需求,合理调整 Tomcat 线程池,对系统性能会产生较大的影响。
Tomcat 线程池可调整的参数主要是核心线程数、最大线程数和等待队列。一般经验法则是,线程池核心线程数可以设置为 CPU 核心数 + 1,最大线程数可根据系统承载能力适当放宽,同时要结合内存合理配置等待队列大小。例如,在一台 4 核 CPU、8GB 内存的服务器上,对于 CPU 密集型业务,核心线程数设为 5,最大线程数设为 10,等待队列长度设为 50;对于 I/O 密集型业务,核心线程数可适当增大,如设为 8,最大线程数设为 15,等待队列长度设为 80。调优的过程需要通过多次压力测试,观察系统TPS、资源利用率等指标,逐步微调,直至达到理想的效果。
Tomcat性能调优实践
按照上面说的方法,压测、监控、微调、再压测,如此循环。在系统优化前,随着并发用户数增加,TPS 在达到一定值后增长缓慢,且 CPU 使用率波动剧烈,时常出现接近 100% 的峰值;经过多次优化后,TPS 曲线明显上扬,能够稳定承载更高的并发请求,同时 CPU 使用率趋于平稳,维持在 70% - 80% 之间,表明系统性能得到显著提升。
图3 Tomcat性能测试优化前后对比
Tomcat性能优化结果对比
Tomcat参数调优前,在高并发下TPS增长乏力,资源利用率不稳定;参数调优后,TPS曲线斜率明显增大,能够平稳支撑更高并发请求,资源使用率趋于合理区间。我们以并发用户数 500为例,来看具体测试数据对比。
优化前 TPS 约为 200,CPU 使用率峰值达 95%;优化后 TPS 提升至300,CPU 使用率稳定在 75% 左右,内存占用也更加平稳,未出现频繁的 GC(垃圾回收)导致的性能抖动。
表1 Tomcat性能优化对比
对比项 | 优化前 | 优化后 |
TPS(用户并发数100) | 80 | 80 |
TPS(用户并发数300) | 146 | 198 |
TPS(用户并发数800) | 203 | 421 |
CPU使用率均值 | 96% | 75% |
02
Elasticsearch 性能测试调优
Elasticsearch 数据库简介
Elasticsearch 是一个分布式、RESTful 风格的搜索和数据分析引擎,它能够快速地存储、搜索和分析海量数据。基于 Lucene 库构建,提供了分布式多租户能力,使得数据能够在集群环境下高效处理,广泛应用于日志分析、全文检索、商业智能等领域。
Elasticsearch 技术原理
Elasticsearch中数据存储与检索的核心概念是索引。当数据写入Elasticsearch时,它会根据文档的字段值构建倒排索引。倒排索引类似于一本字典,将文档中的每个关键词映射到包含该关键词的文档列表。例如,对于多篇文档,如果其中一些文档包含“大数据” 这个词,在倒排索引中就会有“大数据”-> [文档 1,文档 3,文档 5] 这样的映射关系。这样,当进行搜索查询时,Elasticsearch 能够快速定位到包含关键词的文档,大大提高检索效率。
为了实现数据的分布式存储与处理,Elasticsearch 将索引划分成多个分片。每个分片本质上是一个独立的Lucene索引,可独立存储数据、执行搜索操作。安全管理平台采用的是按业务分索引和按时间分片的设计方案,当有查询请求时,Elasticsearch 能够并行地在多个索引上的多个分片进行搜索,将“大问题”分解成若干个“小问题”并行处理,最后将汇总结果返回给客户端。例如,在10亿数据量的系统中进行数据检索,ElasticSearch数据库共有10个索引,一个索引划分为10个分片,每个分片平均存储 1 千万条数据,查询时先确定索引范围,每个索引中的10个分片同时工作,大大缩短查询响应时间。
ElasticSearch数据库的入库机制和原理是通过内存缓冲区接收文档,同时写入Translog(事务日志)确保操作持久化,防止数据丢失。默认每1秒执行Refresh,将内存数据转为文件系统缓存中的Lucene段,实现近实时搜索(未刷盘)。当Translog达到阈值(如512MB)或定时触发时,执行Flush将数据持久化到磁盘,清空Translog并生成持久化Segment。写入时,文档按路由规则分配到主分片,主分片通过同步复制确保所有副本分片写入成功,保障高可用。通过调整refresh_interval减少Segment生成频率,或使用Bulk API批量提交,可显著提升吞吐量。故障恢复时,依赖Translog重放未持久化操作,副本分片自动提升为主分片,确保数据可靠。
Elasticsearch 数据入库调优方法
通过了解ElasticSearch数据库的索引、分片、入库机制和原理,调优遵循“少改动,大效果”的原则,本次调优针对数据入库进行优化。在数据入库环节,优化批量写入操作至关重要。通过增大单次批量写入的文档数量,减少网络请求次数,可以提高写入效率。但也要注意避免一次性批量过大导致内存溢出问题。
例如,原本每次批量写入 100 条文档,优化后可尝试每次写入 500 条,根据服务器内存与性能监控情况调整。同时,合理设置索引刷新间隔,延长刷新时间,减少频繁刷新索引对写入性能的影响。如将默认的每秒刷新一次调整为每 5 秒刷新一次,让更多数据批量写入后再统一刷新到磁盘,提升整体入库速度。
ElasticSearch性能调优实践
按照上面说的方法,压测、监控、微调、再压测,如此循环。
在相同的硬件环境以及数据样本集下,初始配置每次批量写入 100 条文档时,记录写入 100 万条数据所需的时间,经多次测试平均耗时约为 30 分钟,且在此过程中,服务器 CPU 使用率频繁出现尖峰,内存占用也呈稳步上升趋势,接近内存阈值时出现明显的性能波动,甚至偶尔引发短暂卡顿。
调整批量写入数量为每次500条,再次进行同样规模的数据写入测试。此时,平均耗时大幅缩短至10分钟以内,CPU使用率曲线趋于平稳,维持在一个相对合理的区间,波动幅度极小,内存占用增长速率也明显放缓,始终未触及预警阈值,系统整体运行流畅,未出现卡顿现象。这充分表明合理增大批量写入数量对提升入库效率、稳定系统资源利用率有着显著效果。
接着,聚焦于索引刷新间隔调整带来的性能变化。保持批量写入优化后的配置不变,先以默认每秒刷新1次索引的设置,向 Elasticsearch 持续写入 500 万条数据,同时监测写入速率以及服务器资源消耗。结果发现,写入速率极不稳定,频繁出现骤降,平均写入速率仅能维持在每秒200-300条文档左右,服务器磁盘I/O长时间处于高负载状态,接近饱和,严重制约了数据入库的整体效能。
将索引刷新间隔调整为每 5 秒刷新一次后,重复上述写入测试。写入速率得到极大提升,平均稳定在每秒 800 - 1000 条文档,磁盘 I/O 负载大幅降低,在整个数据写入过程中,CPU、内存与磁盘资源协同工作,未出现明显的性能瓶颈,确保了高效稳定的数据入库流程。
Elasticsearch 性能优化结果对比
Elasticsearch优化前查询响应时间长、吞吐量低,节点资源时常出现瓶颈;优化后,响应时间大幅缩短,吞吐量翻倍增长。在处理相同规模的查询任务时,优化前10个并发查询平均响应时间为7秒,吞吐量为每秒50次查询;优化后平均响应时间缩短至2秒,吞吐量提升至每秒120次查询,同时各节点CPU、内存、磁盘I/O负载均衡,均未出现资源过度占用节点。100万数据的入库时间从原先的30分钟变为10分钟以内;平均每秒写入数从200-300条数据到800-1000条数据。性能对比结果如下:
图4 ElasticSearch性能测试优化前后对比
表2 Elasticsearch性能测试对比
对比项 | 优化前 | 优化后 |
单次批量写入数(条) | 100 | 500 |
100万数据写入耗时(分钟) | 30 | 9.8 |
每秒入库数(条) | 260 | 990 |
10个并发查询耗时(秒) | 7 | 2 |
吞吐量(次/秒) | 50 | 120 |
03
性能测试数据模型调优
性能数据模型简介
当前性能数据模型的构建设计是基于现场设备日志量和实时数据采集结果,采用每日1个索引的存储机制。然而,在研发版本测试验证场景中,往往没有足够长的时间,一般需在1周内集中生成并入库100亿条满规格数据,与现场长期分散写入的实际业务场景存在显著差异。
这种测试方式导致大规模数据集中在少量索引,查询效率随数据量增大而急剧下降,尤其是复杂关联查询与聚合操作。这种效果和真实客户场景不符,测试结果对产品优化指导价值不大;而且容易导致磁盘空间不足、磁盘损坏、索引损坏等问题,整个测试环境不可用,影响产品研发测试进度。
性能数据模型的原理
性能数据模型的设计原理是通过短时间高吞吐写入模拟客户现场长期积累的海量数据场景,从而实现对平台产品大数据量的压力测试。
具体数据模型设计如下:
数据结构模拟:基于现场设备日志特征(如字段类型、数据格式、时间戳分布)构建数据模板,确保数据的多样性和单条数据的规格都与现场保持一致。
存储架构模拟:采用与现场相同的每日单索引策略,通过时间戳字段按天切分索引。即产品版本与现场版本保持一致。
数据量模拟:测试模型集中写入与现场等效的数据总量,如100亿条。
为了压缩性能测试时间,大数据量压力测试的时间一般在一周左右,即将现场1年的时间压缩至1周,短期内生成100亿级数据,实现对现场数据量的压力模拟。
性能数据模型的调优方法
目前产品的存储架构是参照客户现场的真实场景设计的方案。
在客户现场的长期运行环境里,通常是以长达3年的时间跨度来规划数据存储与管理模式。如此累计下来,3年时间大约产生3*365=1095个索引。这种按照时间序列精细划分索引的方式,能够精准适配客户多样化的查询需求。
一方面,从数据查询的频率分布来看,客户日常业务操作更多聚焦于近期某一时段的数据检索,例如过去一周、一个月或者一个季度内的数据详情,较少涉及对全部 3 年数据的一次性全量查询。以每日为单位构建索引,当执行这类针对近期特定时段的查询任务时,系统能够迅速定位到对应的少量索引,极大地缩减了无效数据的检索范围,显著提升查询响应速度,避免因海量数据的全表扫描而导致长时间延迟。
另一方面,考虑到硬件资源的合理利用与系统稳定性维护。集中式的单索引存储在数据量急剧膨胀时,极易引发资源瓶颈,无论是CPU密集型的复杂查询计算,还是磁盘 I/O 频繁读写操作,都可能因单一索引的过度负载而陷入瘫痪。相反,分布式的多索引架构能够将数据压力均匀分散至各个索引所对应的存储区域,使得服务器的 CPU、内存、磁盘等关键资源得以均衡负载,确保系统在长期运行过程中始终保持稳定高效的工作状态,从容应对客户现场复杂多变的业务需求。
深入剖析当前数据模型,发现现在方案在模拟实际业务场景时存在显著缺陷。按照现在方案,1周内打入高达100亿的数据量,将导致大量数据集中存储于少量索引中,这与客户现场的真实使用情境严重不符。因此,性能测试时应该把100亿数据量平均写入到3年的每一个索引中,更符合客户现场业务运行3年的数据模型。
所以,性能数据模型的调优方法就是采用自动化方法,把大量数据分索引存入平台的数据库。
性能数据模型的调优实践
按照上述方法,通过编写自动化脚本,模拟时间流逝,以15分钟为一个间隔模拟1天时间。这样平台系统将根据时间自动建立索引,从而将100亿数据均匀分配到1095个索引中。每个索引独立维护,在查询时,根据时间范围精准定位到对应的少数几个索引进行检索,避免全量数据扫描。例如,查询过去1小时内的数据,只需涉及4个索引,大大减少了无效数据的检索量,提高查询效率。
图5 修改系统时间脚本
性能测试数据新旧模型对比
旧的数据模型下,随着数据量增长,查询性能呈指数级下降,数据维护成本高;新的数据模型通过分布式索引存储,精准定位查询范围,有效控制了查询响应时间的增长趋势。在数据量达到100亿时,旧模型复杂查询平均耗时30秒以上,新模型将平均耗时控制在 10秒以内,且随着后续业务增长,新模型的扩展性优势将更加凸显,能够轻松应对海量数据挑战。
表3 新旧数据模型对比
对比项 | 旧数据模型 | 新数据模型 |
数据量(亿条) | 100 | 100 |
索引数量 | 11 | 1095 |
复杂查询平均耗时(秒) | 30-50 | 10 |
04
总 结
通过Tomcat、Elasticsearch及数据模型的系统性调优,平台性能实现显著提升,在有限的时间里实现了对产品性能的充分测试。总结经验如下:
理解产品底层逻辑,设计合理调优方案
性能调优对技术能力要求很高,必须先充分理解产品运行的底层逻辑,才能设计出来可靠的监控和调优方案。
完善性能监控方案,逐步调优逐步优化
性能调优不会一步到位,系统性能表现是系统内部多种因素综合作用的结果。在进行系统调优时,必须首先完善监控方案,可准确度量性能结果,再结合底层的技术原理,逐步调优,逐步优化,直至最后满足要求。
深入理解业务场景,仿真测试体现价值
性能测试压力测试,并不是为了追求一个数字,最终目标是满足客户现场的使用要求。产品设计和性能测试都要充分理解客户的业务场景,满足客户现场要求才能最后体现产品的价值。
本次实践表明,通过参数调优和数据模型重构,可在不增加硬件投入的条件下,充分释放系统潜力,最大程度满足客户现场要求,为类似场景性能优化提供可复用的方法论与实战参考。
渠道合作咨询 田先生 15611262709
稿件合作 微信:shushu12121
📍发表于:中国 北京