性能测试爬坑之路21 -- Analysis 线程
这节课我们主要学习一下后端性能测试的线程的概念,这个概念非常重要,就像刚开始的时候我们用 roadrunner 并发用户也是用线程,用 CPU 处理很多任务也是用线程,服务器要支持很多用户同时访问也是要分配很多线程,所以线程的这个概念非常的重要
首先我们简单的理解一下,什么是线程,现在的 CPU 是一种多线程的工作机制,同时可以处理很多任务,也可以让多线程处理相同的事情,这就是线程,她的应用场合很广,如果同学用过下载软件,比如说迅雷的,还有我们很早之前用的网络蚂蚁啊,flashget 等等这些下载软件,他就是利用多线程来下载的,他把文件分解成几段,然后用线程分别下载其中的一段,这样就可以加速下载的过程充分的利用客户端的带宽,到后来我们的 CPU 叫多核多线程,还有平成我们边听歌曲边上网,边聊天,边工作,我们可以同时做很多事情,没有问题,因为 CPU 是多线程在工作的,再有现在的分布式的应用服务器,就是多线程支持的多用户访问,每一个线程负责一个用户的请求,数据库也是一样的,应用的多线程,每个线程处理一个 sql 请求,通过三层架构来说,客户去访问服务器,服务器一看是数据库操作请求或者是数据库查询请求那么,这个时候服务器会把这个请求转发给数据库,数据库在多线程来处理这个请求,所以多线程应用的场合非常非常的广,
那么线程池是个什么概念,线程池的本质还是线程,他是用来管理多线程的一种机制,他不是一个需要去发请求或者处理请求的一个线程,他不会操作这些东西,而是一种管理机制,我们把所有的线程放在这个线程池里面,这样这些线程就会公用相互的调度,同时空闲的线程也用线程池管理起来,他会看那个线程空闲,他就会让这个线程做这个请求的处理,他通过线程池的管理机制,把这些线程统一的管理起来了,便于我们应用或者服务器更好的控制这些线程,让这些线程的资源利用的更加的合理,这就是是线程池的概念,我们了解这个概念就好了,我们后面在做后端性能调优的时候你可能会看到, thread pool 这样一个参数,你尽量的去调,调里面的数字,线程池的大小对应这个线程池最多管理多少个线程,调的越大越好,调到多大?这里我们就需要了解又一个线程的机制,线程主要消耗的是 CPU 的资源,这些应用程序的线程从哪里来?其实还是从 CPU 里面来,因为 CPU 有多线程,这些应用和应用服务器才会有多线程,所以他最终消耗的是 CPU 的资源,那么 CPU 的资源是有限的,我们普通的处理器就按么几个 CPU 或者几台服务器做一个集群,她的资源总是有限的,所以他能并发的线程书总是有限的,不是说越大越好,你不能调的超过 CPU 的极限,那这个时候 CPU 注定会奔向 100 % 的利用率 ,然后队列越来越长,导致整个系统崩溃,导致的结果就是用户等半天没有反应,最后用户主动放弃了这个请求,但是内存用完了系统就是绝对的崩溃,但 CPU 没有的用了就是先排着队列,队列长一点,内存满了会考虑把虚拟内存用起来,虽然是慢一点,这样会减少一些崩溃,关于虚拟内存,关于内存、虚拟内存、硬盘的读取演示会在线程演示完了给大家演示一下,回到这边来,线程数量的上线就是 CPU 的极限,不是越大越好。
在这里提到线程了,我们在这里再提一下「动态影响」 ,前面我在给大家讲服务器指标的时候提到了动态影响,这个动态影响我想给大家说两个例子来说明一下就可以了,因为这个影响关系有点复杂,我们一定要清楚他们之间的关系,不要因果颠倒,
问题 1:假如现在有一个理想的场景,我有一个论坛,他发一个帖子的时间是3秒钟,那么在 60 秒内可以发送多少帖子?可以发送 20 个,这个没有问题,简单的一个除法,如果我每次发一个帖子暂停两秒,那么 60 秒内可以发送多少帖子?
我们可以得出的结论是发表的帖子大于 12 个,原因很多简单我们暂停了服务器的负载或者说压力减少了,这个时候动态影响的结果是我发一个帖子可能用不来 3 秒钟,这是动态影响,返回来影响你的响应时间了,响应时间我们说在标准情况下,但是这边有服务器暂停了,有休息的时间了,它能够处理的东西就能够更多一点了,
问题 2 :对于三层架构老说 客户端-服务端-数据库,瓶颈可能出现在任意一层,现在我们调高服务器的线程数,那么他可以支持的并发用户更多了,比如说现在服务器端线程数量默认是 100 ,相当于可以并发 100 个用户的访问,但是第 101 个用户进来的时候,他就会让给你用户先排着队,那现在看 100 个肯定不行,我把她调整成 1000 个,请问可以吗?
现在我们就利用 Apache 服务器演示线程数量的修改到底会产生什么样的结果,apche 项目下面有一个 conf 的目录,这个目录地下有一个 Apache 核心的参数文件 httpdconf ,里面有一个参数 ThreadsPerChild 250 每一个子进程能够处理的线程数量,我们就默认 250 个用户他是可以同时处理的,我现在为了做实验方便,我把她改成 10 个用户,改完参数文件后保存,重启 Apache 服务设置才会生效,我现在写一个请求,打开首页,请求一下看看有没有问题,现在我们打开 Controller 来模拟 10 个用户看看有没有问题,我们选择同步增加,运行时间无所谓了,一会看见结果了就直接停止, 10 个人同时给服务器发请求,所以不会有问题对不对?按理说这些请求都能够正常处理的,我们看到服务器都能够处理,没有问题,现在我们把 10 个用户改成 20 个用户,理论上服务器不能够支持 20 个用户的同时访问,要么报错,要么超时,很有可能出现这样的情况,我们现在经过一段时间的运行之后,这边的错误已经陆陆续续的爆出来了,
我们看一下错误的消息到底是什么,我们看到链接到服务器失败,链接拒绝,一共报了 115 个这样的错误,下面的错误是 超时 120s ,我们的客户端已经没有办法连接到服务器的时候等待了 120s ,这个超时的时间是在 loadrunner 里面去设置的,那么现在我们明显感受到是报错了,而错误消息是链接拒绝,服务器没有办法支持这么多的链接,让服务器同时支持这么多的用户来访问,他只能支持 10 个用户同时访问,其他用户访问怎么办? 他只能一直等着,他并不会告诉你出错,他会让你一直等着,等的过程中,你其实用手工打开一个页面就能够感受到什么感受呢 ? 就是页面一点相应都没有,或者说相应很慢,那 loadrunner 测试刚开始的时候没什么感觉但是一旦超时就会一堆的错误爆出来,那所以这个问题要修改,这是 Apache 修改了线程数量表现出来的一种结果,因为她同时只能支持 10 个,其他用户你就等着慢慢排队吧,超时的时间在 run time setting 里面修改,
但是也并不是将线程的并发数量改的越大越好,不是只改个数字就好了,你改的太大也没有用,CPU 搞爆了也没有意义, CPU 没有资源处理,也会排着队,对用户的感受是一样的还是排队等待,所以我们要找到一个合理的值,这个合理的值怎么找?Apache 都是这么改,但是Apache 部署在什么服务器上,这台服务器什么配置,需要测试出来的,我们测试发现同时处理 2000 个是靠谱的,服务器都能够支撑,各项指标都正常,带宽也不会被消耗殆尽,这里设置 2000 是合理的,不能设置的太大让系统崩溃,因为设置的合理之后,我们通过线程数的设定,来屏蔽掉对我们服务器资源的恶意的消耗,比如我们现在设置成 2000 个,同时支撑 2000 个用户,后面的人再进来只能让他们先等着了,最差一点是用户体验差一点,但是不至于把我们的服务器搞垮,这两者要取一个权衡,如果不设限制,用户想来就来,设置再大有什么用,用户来了之后他感觉很慢很慢,服务器资源不够用了,你先等会,还不如直接告诉她让他等着,这比打开一个网页半天没有反应要强的多,所以我们这边相当于加了一个限制,你不能没有限制的来访问,那么服务器撑不住也会出状况,所以这个值的大小是要我们来调整的,那么调整的依据就是我们的服务器的资源相对合理的指标,比方说 3/4 左右,主要是 CPU 了,那么 CPU 考虑完了之后考虑带宽,这个测一下就可以了,通过标准的负载测试方法就可以知道了,100 、 200 、500 、2000 、10000 看看 CPU 、带宽的指标是什么样的,还有一点回到我们前面的动态影响,
问题 3 :假设 修改为 1000 ,服务器硬件可以支撑,那么就可以了吗?有什么别的问题了没有?
这里要考虑到动态影响,我这里修改为 1000 个没有问题,但是数据库那边可以支撑住吗?因为我这边 1000 个请求过来的时候都很可能都带着数据库查询的请求,或者是修改操作的请求,那么相对应的数据库那边需要配备 1000 个线程来处理我们的数据库的请求,这样才能跟我的服务器匹配上,这边刷 1000 个数据库了,数据库也需要 1000 个线程来处理这个请求,这个时候我们考虑到动态影响对后台服务器来说,不单纯要测试服务器就行了,我们还要测试数据库,要他两者同时达到最佳的状态,有可能我们发现最佳的状态不是 1000 个有可能是 800 个,服务器支撑没有问题,数据库也达到了比较良好的状态,这是一种方式,就是把它调整的小一点,第二种方式,就是为了让这个数据库跟服务器更匹配,我们会对数据库的硬件资源进行升级,让两者都类似,这两者硬件都一样,但是因为一边部署的是 Apache 一边部署的是数据库,因为软件系统的不一样,所以即使是相同的硬件,不见得他们理想的状态是同一个线程数量,因为应用系统不一样,他们消耗的资源本身也是有区别的,所以这个是需要我们去测试的,需要我们能够找到一个平衡点,这个平衡点除了 CPU 硬盘 内存 以外还包括传输过程中的带宽平衡点,这样就可以让我们的系统达到一种最佳的状态,这种最佳状态下并发的用户数量才是我们真正意义上的是我们可以精确的最佳用户数,所以对于最佳用户数我们一定要考虑到,各种后端这些性能指标的平衡
这节课关于线程就说到这里,对于线程再多说一句,Apache 有线程,数据库有线程,所以说我们真正在做性能测试的时候,这每一个层次的线程的资源我们都要去关注,包括数据库一样,包括线程池的调整和优化,都是服务器端我们调优的指标,慢慢的去调整优化,慢慢的达到一种最好的状态,还有像前面讲的缓存也是一样的,每一个应用系统都会有缓存的配置,包括像 Java 虚拟机内存的设置,也就是我们的系统分配给 Java 的内存到底有多大,包括 tomcat 也会有他的 jom, 因为 tomcat 内部使用的就是 Java 所以tomcat 也会有系统的一些设置,等等这些服务器对缓存的利用都很重要,一定要特别的引起重视,我们就是要针对自己不同的应用系统,除了去关注他的线程,还要去关注她的缓存,