第七周总结
性能测试
性能测试指标
响应时间
指应用系统从发出请求到收到最后响应所需要的时间,响应时间是系统最重要的性能指标,直观的反应了新系统的"快慢"。
并发数
系统能够同事处理的请求数目,这个数字也反应了系统的负载特性。对于网站而言,并发数即系统并发用户数,指同事提交请求的用户数目。
吞吐量
指单位时间内系统处理的请求的数量,体现系统的处理能力。
TPS(每秒的事务数)
HPS(每秒HTTP请求数)
QPS(每秒查询数)
吞吐量 = (1000 / 响应时间ms) X 并发数
性能计数器
描述服务器或者操作系统性能的一些数据。包括System Load、对象数与线程数、内存使用、CPU使用、磁盘与网络I/O指标。这些指标也是系统监控的重要参数,对这些指标设置阈值,当监控系统发现性能计数器超过阈值的时候,就向运维和开发人员报警。
System Load:系统负载,指当前正在被CPU执行和等待被CPU执行的线程数目总和,最理想的情况是SysmteLoad = CPU核数。
当 System Load < CPU核数,表示CPU有空闲,资源在浪费。
当 System Load > CPU核数,表示线程在排队等待CPU处理,系统资源不足。
性能测试方法
性能测试的总称,具体可细分为性能测试,负载测试,压力测试,稳定性测试。
性能测试
以系统设计初期规划性的性能指标为预期目标,对系统不断施加压力,验证系统在资源可接受范围内,是否能达到性能预期。
负载测试
对系统不断施加压力,直到系统的某项或多项性能指标达到安全临界值,如某种资源已经呈饱和状态,这时继续对系统施加压力,系统的处理能力不但不能提高,反而会下降。
压力测试
超过安全负载的情况下,对系统继续施加压力,直到系统崩溃不能再处理任何请求,以此获得系统最大压力承受能力。
稳定性测试
被测试系统在特定硬件,软件,网络环境条件下,给系统加载一定业务压力,使系统运行一段较长时间,以此检测系统是否稳定。在生产环境,请求压力是不均匀的,呈波浪特性,因此为了更好模拟生成环境,稳定性测试也应不均匀地对系统施加压力。
随着用户并发数的增加,系统的响应时间也会逐渐变长,错误率也会变大。
全链路压测
在特定的业务场景下,将相关的链路完整的串联起来同时施压,尽可能模拟出用户的真实行为,当系统整站流量都被打上来的时候,必定会暴露出性能瓶颈,才能够探测出系统整体的真实处理能力,以及有指导的在大促前进行容量规划和性能优化。
全链路压测的挑战
压测相关的业务系统众多,并且牵连到整条链路上所有的基础设施和中间件,如何确保压测流量能够畅通无阻,没有死角?
压测的数据怎么构造,数据模型如何与真实贴近?
全链路压测直接在线上的真实环境进行模拟,怎么样来保障对线上无影响?
大型促销活动所带来的巨大流量要怎么制作出来?
数据构造
数据构造可以通过拉取线上数据,线上数据通过筛选,脱敏,Id隔离,订正后就可以当作测试数据使用。
大流量制作
Master + slave结构,
Master作为压测管控台管理slave节点、统计压测结果。
slave节点作为压测引擎,负责发送具体的请求后将结果返回给Master。
数据隔离
逻辑隔离:将测试数据和正常数据写到一起,通过特殊的标识区分开。
可能污染线上数据,破坏线上数据安全性。
虚拟隔离:在所有写数据的地方做mock,并不是真正的写进去。
不会对线上数据产生污染,但是mock对压测结果的准确性可能产生干扰。
物理隔离:所有写数据的地方对压测流量进行识别,判断一旦是压测流量的写,就写到隔离的位置。
系统性能优化
软件系统优化的两个原则
你不能优化一个没有测试的软件
你不能优化一个你不了解的软件
性能优化的一般方法
性能测试,获得性能指标
指标分析,发现性能与资源瓶颈点
架构与代码分析,寻找性能与资源瓶颈关键所在
架构与代码优化,优化关键技术点,平衡资源利用
性能测试,进入性能优化闭环
系统性能优化的分层思想
机房与骨干网络性能优化
异地多活的多机房架构
专线网络与自主CDN建设
服务器与硬件性能优化
使用更优的CPU,硬盘,内存,网卡,对软件的性能优化可能是数量级的,有时候远远超过代码和架构的性能优化
操作系统性能优化
找出消耗系统资源较高的sys应用进行调整
虚拟机性能优化
JVM选择合适的垃圾回收器
基础组件性能优化
选择合适的WEB容器,数据库连接池等基础组件。
选择合适的WEB容器、JDK等其他组件版本。
软件架构性能优化
缓存
将热点数据放入缓存服务器中
从内存获取数据,减少响应时间
减少数据库访问,降低存储设备负载压力
缓存结果对象,而不是原始数据,减少CPU计算
缓存主要优化读操作
异步
即时响应,更好的用户体验
控制消费速度,合适的负载压力
异步主要优化写操作
集群
使用更多的服务器,提供更多的计算资源
软件代码性能优化
并发编程,多线程与锁
资源复用,线程池与对象池
异步编程,生产者与消费者
数据结构,数组,链表,hash表,树
操作系统
进程的运行期状态
运行
当一个进程在CPU上运行,则该进程处于运行状态。处于运行状态的进程的数量小于等于CPU核心数。
就绪
当一个进程获得了除CPU以外的一切所需资源,只要得到CPU即可运行,则该进程处于就绪状态,就绪状态有时也被称为等待运行状态。
阻塞
也称为等待或睡眠状态,当一个进程正在等待某一事件发生(例如等待I/O完成、等待锁)而暂停运行时,这时即使把CPU分配给进程也无法运行,故称该进程处于阻塞状态。
进程VS线程
不同进程轮流在CPU上执行,每次都要进行进程间切换,代价非常大。因此服务器通常是单进程多线程。
进程从操作系统获得基本的内存空间,所有的线程共享着进程的内存地址空间。而每个线程也会拥有自己私有的内存地址范围,其他线程不能访问。
线程安全
当某些代码修改堆内存(进程共享内存)里的数据的时候,如果有多个线程在同时执行,就可能出现同时修改数据的情况。
临界区
多个线程访问共享资源的这段代码被称为临界区,解决线程安全问题的主要方法是使用锁,将临界区的代码加锁,只有获得锁的线程才能执行临界区代码。
锁
锁原语 CAS
CAS(V,E,N)
V表示更新的变量
E表示预期值
N表示新值
如果V值等于E值,则将V的值设置为N,若V值与E值不同,则什么都不做。
CAS是一种系统原语,原语的执行必须是连续且不可被中断的。
偏向锁 轻量级锁 重量级锁
偏向锁
指一段同步代码一直被一个线程锁访问,那么该线程会自动获取锁,降低获取锁的代价。
轻量级锁
指当锁是偏向锁时,被另一个线程锁访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,提高性能。
重量级锁
指当锁是轻量级锁时,另一个线程虽然自旋,但自旋不会一直持续下去,当自旋到一定次数时,还没有获取到锁,就会进入阻塞,该锁就会升级为重量级锁。
总线锁与缓存锁
总线锁
使用处理器的LOCK信号,当一个处理器在内存总线上输出此信号的时候,其他处理器的请求被阻塞,该处理器独占内存。一般当CPU要修改的值跨缓存行时,才会使用总线锁,否则只锁缓存行即可。
缓存锁
是指内存区域如果被缓存存在处理器的缓存行中,没并且在Lock操作期间被锁定,其他线程访问该缓存行时被阻塞。
公平锁 非公平锁
公平锁
按照先来先到的形式获取锁,多个线程按找申请锁的顺序获取锁。性能较低。
非公平锁
多个线程获取锁的顺序并不是按照锁的申请顺序,有可能后申请的线程比先申请的线程优先获取锁。可能会造成饥饿现象。
可重入锁
线程获取到了某个锁,可以再次获取这个锁,而不会造成死锁。
独享锁/互斥锁 共享锁 读写锁
互斥锁
该锁只有一个线程可以持有。
共享锁
多个线程可以持有。
读写锁
读读不互斥,读写互斥,写写互斥。
乐观锁 悲观锁
乐观锁
认为对同一个数据的并发操作,是不会发生修改的。在更新数据的时候,检查是否已经被修改过,如果修改过,就放弃。自旋锁,CAS锁 都属于乐观锁。
悲观锁
认为对一个数据的并发操作,一定会发生修改。重量级锁 属于悲观锁。
分段锁
分段锁的设计目的是细化锁的粒度,当更新操作不需要对整个数组更新的时候,就仅仅针对数组的一段数据进行加锁操作。
自旋锁
尝试获取锁的线程不会立即阻塞,而是不停的尝试获取锁。
磁盘与I/O
文件控制块
文件系统将硬盘空间以块为单位进行划分,每个文件占据若干个块,然后再通过一个文件控制块记录每个文件占据的数据块。
Linux Inode文件控制块
inode中记录着文件权限,所有者,修改时间 等文件信息,以及文件数据库硬盘地址素音
inode是固定结构的,能够记录的硬盘地址索引数也是固定的,只有15个索引。
评论