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 转载请注明来源

谈谈JSF业务线程池的大小配置的更多相关文章

  1. 到底如何设置 Java 线程池的大小?

    来源:ifeve.com/how-to-calculate-threadpool-size/ 在我们日常业务开发过程中,或多或少都会用到并发的功能.那么在用到并发功能的过程中,就肯定会碰到下面这个问题 ...

  2. java多线程、线程池及Spring配置线程池详解

    1.java中为什么要使用多线程使用多线程,可以把一些大任务分解成多个小任务来执行,多个小任务之间互不影像,同时进行,这样,充分利用了cpu资源.2.java中简单的实现多线程的方式 继承Thread ...

  3. Tomcat线程池与NIO配置

    每个web客户端请求对于服务器端来说就一个单独的线程,客户端的请求数量增多将会导致线程数就上去了,CPU就忙着跟线程切换. 而NIO则是使用单线程(单个CPU)或者只使用少量的多线程(多CPU)来接受 ...

  4. 简单RPC框架-业务线程池

    *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...

  5. spring定时任务.线程池,自定义多线程配置

    定时任务及多线程配置xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=" ...

  6. 谈谈Java的线程池设计

    在实际项目中,如果因为想异步执行暂时性的任务而不断创建线程是很浪费资源的事情(当一个任务执行完后,线程也没用了).这种情况下,最好是将任务提交给线程池执行. 所谓池,就是将管理某一种资源,对资源进行复 ...

  7. 基于Netty的RPC架构学习笔记(十二):借助spring实现业务分离、聊天室小项目、netty3和4、5的不同、业务线程池以及消息串行化

    文章目录 借助spring实现业务分离(

  8. 【mq读书笔记】客户端处理消息(回调提交到异步业务线程池,pullRequest重新入队)

    看一下客户端收到消息后的处理: MQClientAPIImpl#processPullResponse private PullResult processPullResponse( final Re ...

  9. Java线程池实现原理及其在美团业务中的实践

    本文转载自Java线程池实现原理及其在美团业务中的实践 导语 随着计算机行业的飞速发展,摩尔定律逐渐失效,多核CPU成为主流.使用多线程并行计算逐渐成为开发人员提升服务器性能的基本武器.J.U.C提供 ...

  10. SpringBoot异步使用@Async原理及线程池配置

    前言 在实际项目开发中很多业务场景需要使用异步去完成,比如消息通知,日志记录,等非常常用的都可以通过异步去执行,提高效率,那么在Spring框架中应该如何去使用异步呢 使用步骤 完成异步操作一般有两种 ...

随机推荐

  1. 代码随想录算法训练营Day14 二叉树

    代码随想录算法训练营 代码随想录算法训练营Day14 二叉树|理论基础 递归遍历 基础知识 二叉树都是通过栈来实现的. 二叉树的种类 在我们解题过程中二叉树有两种主要的形式:满二叉树和完全二叉树. 满 ...

  2. AntV L7 快速入门示例

    1. 引言 L7 地理空间数据可视分析引擎是一种基于 WebGL 技术的地理空间数据可视化引擎,可以用于实现各种地理空间数据可视化应用.L7 引擎支持多种数据源和数据格式,包括 GeoJSON.CSV ...

  3. RESTful API 简介

    RESTful API 简介 想必使用过 PHP.JSP 这一类服务器动态页面技术的程序员应该都还记得,在使用这种传统的动态页面架构构建应用程序的时候,用于描述用户界面的 HTML 页面通常都是在服务 ...

  4. 自研ORM 完美支持 Exists查询 非常灵活

    示例代码 Case 1 Code var data = db.Query<Product>() .Where(w => db.Query<Product>().Where ...

  5. 自研ORM嵌套查询和子查询,强不强大您说了算。

    测试代码 var count = 0; var refAsync = new RefAsync<int>(); //下面示例方法的重载均支持 var query = db.Query< ...

  6. Kotlin协程-那些理不清乱不明的关系

    Kotlin的协程自推出以来,受到了越来越多Android开发者的追捧.另一方面由于它庞大的API,也将相当一部分开发者拒之门外.本篇试图从协程的几个重要概念入手,在复杂API中还原出它本来的面目,以 ...

  7. [ARM 汇编]进阶篇—异常处理与中断—2.4.2 ARM处理器的异常向量表

    异常向量表简介 在ARM架构中,异常向量表是一组固定位置的内存地址,它们包含了处理器在遇到异常时需要跳转到的处理程序的入口地址.每个异常类型都有一个对应的向量地址.当异常发生时,处理器会自动跳转到对应 ...

  8. java调用WebService(未完成)记录篇

    背景: 因工作需要和一个Sap相关系统以WebService的方式进行接口联调,之前仅听过这种技术,但并没有实操过,所以将本次开发相关的踩坑进行记录 通过一个实例来认识webservice 服务端 首 ...

  9. Python潮流周刊#9:如何在本地部署开源大语言模型?

    你好,我是猫哥.这里每周分享优质的 Python 及通用技术内容,部分为英文,已在小标题注明.(标题取自其中一则分享,不代表全部内容都是该主题,特此声明.) 首发于我的博客:https://pytho ...

  10. 从头学Java17-Modules模块

    模块Modules 了解module系统如何塑造 JDK,如何使用,使项目更易于维护. 烧哥注 从头讲JDK17的文章比较少,英文为主,老外虽能讲清原理,但写的比较绕,所以决定翻译一下,也有个别细节完 ...