第七周 架构方法学习总结
性能测试
性能测试是性能优化的前提,也是性能优化结果的检查和度量标准。不同视角下的性能优化有不同的标准,也有不同的优化手段。
主观视角:用户感受到的性能
客观视角:性能指标衡量的性能
性能测试指标
响应时间
响应时间是指应用系统从发出请求开始到收到最后响应数据所需要的时间。
并发数
并发数是指系统能够同时处理请求的数目,这个数字也反映了系统的负载特性。处理并发用户数,还存在着在线用户数和系统用户数。
吞吐量
吞吐量是指单位时间内系统处理的请求的数量,体现系统的处理能力。对于网站,可以用“请求数/秒”或是“页面数/秒”来衡量,也可以用“访问人数/天”或是“处理的业务数/小时”等来衡量。
吞吐量=(1000/响应时间 ms)*并发数
性能计数器
性能计数器是描述服务器或操作系统性能的一些数据指标。包括 System Load(使用 top 指令查看)、对象与线程数、内存使用、CPU 使用、磁盘与网络 I/O 等指标。
性能测试方法
性能测试是一个总称,具体可以分为性能测试、负载测试、压力测试、稳定性测试。
性能测试
性能测试是指以系统设计初期的性能指标为预期目标,对系统不断施加压力,验证系统在资源可接受范围内,是否达到性能预期。
负载测试
负载测试是指对系统不断增加并发数,使服务器的某项或多项性能指标达到安全临界值,这时候再增加压力,服务器的处理能力不会提升反而下降。
压力测试
压力测试是指超过安全负载的情况下,对系统继续施加压力,直到系统崩溃或不能处理任何情况,以获得系统最大压力承受能力。
稳定性测试
稳定性测试是指被测试系统在特定的硬件、软件、网络环境条件下,给系统一定的业务压力,是系统运行较长一段时间,依此检测系统是否稳定。
在生产环境下,业务请求是不均匀的,呈波浪形的,稳定性测试也应该是不均匀的对系统施加压力。
并发数与性能对照图
看下图可以得知:
当服务器分配给系统的资源越多时,系统的 TPS 就越高;b 点最佳
当服务器资源分配到上限时,系统的 TPS 也达到了上限,这时候如果再分配资源,系统的 TPS 反而下降;达到了 c 点
当服务器资源分配超载时,系统就有可能崩溃。达到了 d 点
在 b 点时,可以发挥系统最佳性能(不会浪费系统资源,同时又有一定的负载能力)。可以根据项目情况选择在 b 点的左右浮动
看下图可以得知:
当并发数越大,系统的响应时间就越慢;
当并发数超过服务器的极限,响应时间会大大提高;
性能优化
性能优化的两个原则
你不能优化一个没有测试过的软件
你不能优化一个你不了解的软件
性能指标
响应时间:完成一次任务花费的时间
并发数:同时处理的任务数
吞吐量:单位时间内完成的任务数
性能计数器:System Load、线程数、进程数、CPU、内存、磁盘、网络使用率
性能优化步骤
通过性能测试,获取性能指标
指标分析,发现性能与资源的瓶颈点
架构与代码分析,寻找性能与资源瓶颈的关键所在
架构与代码优化,优化关键技术点,平衡资源利用
性能测试,进入性能优化闭环
系统性能优化的分层思想
机房与骨干网络性能优化
服务器与硬件性能优化(垂直伸缩可以提升)
操作系统优化(操作系统的参数等)
虚拟机优化(JVM 参数调整)
基础组件优化(Tomcat)
软件架构优化(分布式架构)
软件代码性能优化
机房与骨干网络性能优化
异地多活的多机房架构(提供就近访问)
专线网络与自主 CDN 建设
服务器与硬件性能优化
使用更优的 CPU、磁盘、内存、网卡,对软件的性能优化可能是数量级的,有时候远超代码和架构的性能优化。
网络传输能力不足时,可以选择提升网卡;核数核线程数
操作系统优化
transparent huge page
介绍:http://blog.itpub.net/26736162/viewspace-2214374/
虚拟机优化
GC 优化
基础组件优化
软件架构优化
软件架构优化三板斧:缓存、异步、集群
缓存
从内存获取数据,减少响应时间
减少数据库访问,降低存储设备负载压力
缓存结果对象,而不是原始对象,减少 CPU 计算
缓存主要优化读操作
异步
及时响应,更好的用户体验
控制消费速度,合适的负载压力
异步主要优化写操作
集群
增加资源,提升并发
软件代码性能优化
遵循面向对象的设计原则与设计模式编程
并发编程,多线程与锁
资源复用,线程池与对象池
异步编程,生产者消费者
数据结构,数组、链表、hash 表、树
操作系统
程序运行时架构
程序是静态的
程序运行起来以后,被称为进程
操作系统多任务运行环境
进程分时执行,能够在 CPU 有限的核数下,处理更多数量级的任务。
进程的运行期状态
运行:当一个进程在 CPU 上运行时,则称该进程处于运行状态。处于运行状态的进程数量小于等于 CPU 的核数。
就绪:当一个进程获得了除 CPU 以外的一切所需资源,只要得到 CPU 即可运行,则称此进程处于就绪状态。
阻塞:也成为等待或睡眠状态,当一个进程正在等待某一件事发生(例如等待 I/O 完成,等待锁)而暂时停止运行,这时即使把 CPU 分配给进程也无法运行,所以称为阻塞状态。
进程 vs 线程
不同进程轮流在 CPU 上执行,每次都要进行进程间 CPU 切换,代价非常大。因此服务器应用通常是单进程多线程。
进程从操作系统获取基本的内存空间,所有的线程共享进程的内存地址空间。而每个线程也会拥有自己私有的内存地址范围,其它线程不能访问。
线程栈
// TODO 专题学习
JavaWeb 应用多线程运行时视图
用户请求通过 DNS 解析送达到服务器(指定 IP)的端口;(TODO:需要了解网络协议)
应用监听指定端口,当请求达到时,分配线程进行函数调用(该请求所有函数都是同一个线程)
当函数调用完成之后,释放资源。
线程安全
当执行函数时,会分配线程(开辟虚拟机栈-线程独有),函数中的基础类型变量会存放在栈中。引用类型的变量(也就是实例化对象)存放在堆中(线程共享)。当多个线程同时修改堆中的数据时,可能会存在有些修改动作失效。
临界区
多个线程间共享资源的这段代码被称为临界区,解决线程安全的主要方式就是加锁,将临界区的代码进行加锁,只有获得锁的线程才能执行临界区的代码。
阻塞导致高并发系统崩溃
避免阻塞引起的崩溃
限流:限制访问服务器的数量,减少创建的线程数
降级:关闭部分功能的代码执行,尽快释放资源
反应式:异步
锁
锁原语 CAS(Compare And Swap)
CAS(V,E,N):V 表示要更新的变量,E 表示预期值,N 表示最新值。在执行时,如果 V 等于 E,则将 V 的值改成 N,如果不相等则什么都不做。
CAS 是一种系统原语,原语的执行过程必须是连续的,不允许被中断。
基于 CAS 的 synchronizated 实现
多 CPU 情况下的锁
总线锁
缓存一致性协议
锁的类型
公平锁/非公平锁
公平锁是指按照申请时间先后来获得锁
非公平锁是指随机获取锁,和申请时间无关
可重入锁
当当前线程已经获得该锁,可以再次或多次获取相同的锁,避免造成死锁。
独享锁/互斥锁
该锁只能被一个线程持有
共享锁
该锁可以被多个线程持有
读写锁
读不需要锁,写需要锁
悲观锁
认为每次操作都会发生修改,所以都会加锁。先加锁后修改
乐观锁
认为每次操作都可以修改成功,如果发生数据修改失败(类似 CAS),则放弃。
分段锁
锁的基本概念
自旋锁
尝试获取锁的线程不会立即阻塞,而是采取循环的方式去尝试获取锁,可以减少线程切换,但是会消耗 CPU。
synchronized 轻量级锁就是自旋锁
评论