谈谈JSF业务线程池的大小配置

这篇具有很好参考价值的文章主要介绍了谈谈JSF业务线程池的大小配置。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.简介

JSF业务线程池使用JDK的线程池技术,缺省情况下采用Cached模式(核心线程数20,最大线程数200)。此外,还提供了Fixed固定线程大小的模式,两种模式均可设置请求队列大小。

本文旨在通过一个简化场景(“单服务应用”)下的负载测试,为“JSF业务线程池大小配置”提供基准测试结果,并形成一些普遍适用的结论。

本文的目标读者包括需要合理配置JSF线程大小的压测工程师、开发部署运维工程师以及架构师。本文不涉及JSF服务端的其他配置项,也不针对“复合服务应用”的合理配置进行探讨。你可以利用本文提供的结论,作为设计压测用例或评估业务线程池大小的基本方法的参考,以便在实践中合理配置JSF业务线程池大小。需要注意的是,JSF业务线程池大小的合理配置应该基于高保真的负载测试结果。

“单服务应用”指应用仅包含一个提供接口,且接口中仅有一个方法。

“复合服务应用”则指应用包含多个提供接口或一个接口中含有多个方法。

2.测试用例说明

本次基准测试选取了USF3.0权限系统,将其定制化为一个单一的服务提供者,仅对该提供者的一个方法进行了测试,因此可以看作是一个“单服务应用”。测试中将CPU作为基准测试的核心资源,并考虑到JVM垃圾收集器的影响,采用了简单的测试数据以保证服务每次调用的一致性,并确保YGC具有规律性(即固定调用量会导致一次30+ms的YGC),无FGC的影响。

测试用例的设计中,所有依赖的服务资源都无限制,以确保测试过程中服务的可用率达到100%。我们的关键性能指标是TP99,即服务响应时长的99%必须小于10ms。

为了测试不同线程池模式下的性能表现,我们使用了JSF线程池的Cached和Fixed两种模式,并针对每种模式进行了多组测试,以得出在满足TP99<10ms的前提下,系统最大的负载情况。

测试应用:USF3.0权限系统(定制化处理)

测试服务:com.jd.susf.service.api.SusfPermissionService#findUserInfo,根据用户信息从Redis中查询一条数据返回的服务。

硬件配置:单台4C 8G

测试方法:在Forcebot系统采用了阶梯发压的方式对JSF业务线程池在Cached和Fixed模式下进行了系统负载测试

拟定SLA要求:服务响应时长的TP99<10ms

注:我们对USF3.0权限系统进行了定制,调整了服务提供方的配置数据,仅保留了 com.jd.susf.service.api.SusfPermissionService。

3.测试结果及分析

3.1.cached线程池的系统负载

图:JSF默认线程池(cached, threads=200)在不同并发用户数(1-200)下的系统负载图

并发用户数 TP99 吞吐量TPS CPU利用率(%)
1~23 <8ms 线性增长 线性增长
24 8ms 6553 99.62
25 11ms 6607 99.83
26~79 迅速增长 缓慢增长 99+
80 74ms 6928 99.82
81~199 缓慢增加 缓慢下降 99.82
200 99ms 6230 99.94

小结:默认的JSF线程池配置存在很大的风险。系统最大可支持24个并发,超过24个并发SLA就无法满足。

3.2 fixed线程池(队列)的系统负载

图:JSF固定线程池(fixed+队列)在不同并发用户数(1-50)下的系统负载图

JSF业务线程数 可支持的最大并发用户数 TP值(50/90/99/999) 吞吐量(TPS) CPU最大利用率(%)
4 11 7/8/10/18 1531 27.67
8 25 8/8/10/18 3113 46.45
16 50 8/8/10/21 6228 87.97
20 23 3/4/10/15 6409 99.92
24 22 3/4/7/15 6178 99.86
25 22 3/4/6/15 6182 98.83

表:JSF固定业务线程池(fixed+队列)在满足TP99<10ms的系统最大负载(最大并发用户数)

小结:

① 在fixed线程模式下,CPU的利用率存在使用上限。

② 队列的使用可以有效增加系统对并发量的支持,同时也会带来吞吐量的提升。然而,由于任务在队列中等待,服务的响应时间会出现“水涨船高”的现象,存在一定风险。

3.3 fixed线程池的系统负载

图:JSF固定线程池(fixed)模式下,系统最大并发用户数时的系统负载

JSF业务线程数 并发用户数 TP99 吞吐量(TPS) CPU最大利用率(%)
4 4 5 1063 20.26
8 8 5 2216 36.62
16 16 6 4262 68.56
20 20 5 5550 86.22
24 24 8 6711 99.62
25 25 16 6644 98.77
26 26 19 6744 99.93

小结:综合固定线程池(fixed)的性能表现,需要设置一个合理的线程数大小来平衡CPU资源的充分利用和满足SLA的需求,线程数过小会导致CPU资源浪费,线程数过大则无法满足SLA

4.结论

根据测试结果和数据分析,我们得出以下结论:

  • JSF线程池的默认配置在并发量高的场景下存在风险:所有线上生产环境中的JSF服务所在的服务器,很少有能够在200个线程的情况下还能够满足SLA的。最大200个线程的线程池配置,将服务器置于“并发量高的场景下被压垮”的风险中。线程池大小的合理配置应该来自高保真的负载测试。
  • 足量的线程数才能保证资源(CPU)的利用率:业务型的服务通常都存在一定的IO操作(网络,磁盘等),线程执行过程中会发生等待,CPU利用率不高,需要增加并发的线程数量,让更多的线程参与CPU的分配,才能提高CPU的利用率。服务中IO操作越多,等待时长越长,需要的并发线程就越多。对于有IO操作的业务型服务,负载测试的线程数可以从2N(N是服务器的CPU核数)开始。
  • 过多的线程数只会降低系统的SLA:当线程数已能100%利用CPU后,增加线程数,线程就无法获取足够的CPU分配,这样服务的响应时间就会增大。在一定范围内,TP99还可能满足SLA的要求,系统的吞吐量也会有少量的增加。再持续增加线程数,TP99就无法满足系统的要求,系统的吞吐量也会开始下降。
  • 固定的线程数可以保护系统需要承担的负载能力:固定线程数可以保证系统对CPU的利用率限定在一定的负载范围内,保护系统稳定运行,保证响应时间TP99,但也限定了系统的并发能力。合理设置队列大小可以增加系统的并发度,也不会影响系统TP99,但会整体拉高服务的响应时间,出现不稳定性的变化,存在风险。
  • 让CPU100%的高负载运行:通常服务对外的SLA承诺通常高于服务真实的性能,这是因为我们考虑了基础设施及依赖服务的不稳定性。因此,即使CPU已经达到了100%,我们仍然可以增加一定数量的线程数,而不会影响对外的响应时间TP99的承诺。这样可以提高系统的并发能力。虽然系统可以在高负载下运行,但我们需要进一步进行稳定性测试,以提高系统的可靠性。

综上所述,线程池大小的合理配置需要结合业务需求和系统资源情况进行评估和测试,并预留合理的buffer空间,以保证系统稳定运行和满足用户的SLA。

5.附录

附录一:统计指标及术语说明

并发用户数:同时发起请求的用户数。

TP值(50/90/99/999):客户端的TP值,单位ms,数据来源于Forcebot。

吞吐量TPS:数据来源于Forcebot。

CPU利用率(%):数据来源于PFinder。

JSF业务线程数:JSF业务线程池的线程数,如:<jsf:server id="jsf" protocol="jsf" threadpool="fixed" threads="16" />

fixed/cached:JSF业务线程池的线程池类型,如:<jsf:server id="jsf" protocol="jsf" threadpool="fixed" threads="200"/>

作者:京东物流 刘江波

来源:京东云开发者社区 自猿其说Tech 转载请注明来源文章来源地址https://www.toymoban.com/news/detail-699624.html

到了这里,关于谈谈JSF业务线程池的大小配置的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 线程池的核心线程数该怎么设置

    为什么要用线程池?线程池中的线程可以重复利用,避免了重复创建线程造成的资源开销。在线程的执行时间比较短,任务比较多的时候非常适合用线程池。 如果运行的线程少于核心线程,会尝试去开启一个新的核心线程(addWorker),如果有空间的核心线程,也不会去使用,

    2024年02月08日
    浏览(30)
  • 聊聊线程池的预热

    本文主要研究一下线程池的预热 java/util/concurrent/ThreadPoolExecutor.java ThreadPoolExecutor定义了prestartCoreThread,用于启动一个核心线程 java/util/concurrent/ThreadPoolExecutor.java prestartAllCoreThreads用于启动所有的核心线程 ThreadPoolExecutor提供了prestartCoreThread方法,用于启动一个核心线程,提供了

    2024年02月08日
    浏览(30)
  • 线程池的执行流程

    如果所示,就是线程池的执行过程,可以分为三个主要步骤: 1.提交任务后会首先进行当前工作线程数与核心线程数的比较,如果当前工作线程数小于核心线程数,则直接调用 addWorker() 方法创建一个核心线程去执行任务; 2.如果工作线程数大于核心线程数,即线程池核心线程

    2023年04月09日
    浏览(28)
  • 线程池的五种状态

    1、RUNNING 状态说明:线程池处于RUNNING状态时,能够接收新任务以及对已添加的任务进行处理。 状态切换:线程池的初始状态为RUNNING。换句话说线程池一旦被创建,就处于RUNNING状态,且线程池中的任务数为0 2、SHUTDOWN 状态说明:线程池处于SHUTDOWN状态时,不接收新任务,但能

    2023年04月09日
    浏览(64)
  • Java线程池的入门

    一、线程池的优势 1.降低系统资源消耗,通过重用已存在的线程,降低线程创建和销毁造成的消耗。 2.提高系统相应速度,当有任务到达时,通过复用已存在的行程,无需等待新线程的创建便能立刻执行。 3.方便线程并发数的管控,因为线程若是无限制创建,可能会导致内存

    2024年02月08日
    浏览(36)
  • python------线程池的应用

    在python中经常会使用异步,线程池,进程池,解决io操作,在爬虫中并不建议使用进程池(消耗过大) 目标:会使用线程池 1:导入 我们可以看到了只有在demo1完全运行完毕才会运行demo2,这个时候是单任务 2:基本使用方法 我们可以看到这时候2个线程的一起跑 3:线程池的基本使用步骤  

    2024年02月15日
    浏览(31)
  • SpringBoot线程池和Java线程池的实现原理

    @ 目录 使用默认的线程池 方式一:通过 @Async 注解调用 方式二:直接注入 ThreadPoolTaskExecutor 线程池默认配置信息 SpringBoot 线程池的实现原理 覆盖默认的线程池 管理多个线程池 JAVA常用的四种线程池 newCachedThreadPool newFixedThreadPool newScheduledThreadPool newSingleThreadExecutor Java 线程池中

    2023年04月11日
    浏览(36)
  • Qt 中线程池的使用

    我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题:如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。 那么有没有一种办

    2024年02月11日
    浏览(33)
  • Springboot结合线程池的使用

    配置文件 配置类 方式一:线程池结合CompletableFuture来实现 配置线程池类 CompletableFuture使用线程池进行调用 任务类 方式二:使用@EnableAsync和@Async方式实现 在启动类上加@EnableAsync注解 编写线程池配置 使用 任务类 方式三:重写springboot默认的线程池配置 在启动类上加@EnableAsy

    2024年02月01日
    浏览(45)
  • android中线程池的选择

    线程池是把一个或多个线程通过统一的方式进行调度和重复使用的技术。 避免了因为线程过多而带来使用上的开销。 在安卓开发中,为了更好的性能体验,我们在选择线程池的时候,需要从具体需求来考虑,主要考虑以下几方面: 1、从任务的优先级; 2、任务的执行时间长

    2023年04月23日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包