写点什么

第七周 - 总结

用户头像
jizhi7
关注
发布于: 2020 年 12 月 06 日

一、系统性能主要技术指标:

性能指标:

1、响应时间

2、并发数

3、吞吐量:单位时间内,系统处理请求的数量。TPS每秒事务数,HPS每秒HTTP请求数,QPS每秒查询数等。

4、性能计数器:是描述服务器或操作系统性能的一些数据指标。包括system load、对象与线程数、内存使用、CPU使用、磁盘与I/O等指标。

性能测试方法:

1、性能测试方法是一个总称,具体可分为性能测试、负载测试、压力测试、稳定性测试。

2、性能测试:以系统设计初期规划的性能指标为预期性能,对系统不断施加压力,验证系统在资源可接受的范围内,是否达到性能预期。

3、负载测试:对系统不断增加并发请求以增加系统压力,直到系统的某项或多项性能指标达到安全临界值。

4、压力测试:超过安全负载的情况下,对系统继续施加压力,直到系统崩溃或不能再处理任何请求。以此获得系统最大压力承受能力。

5、稳定性测试:被测试系统在特定硬件、软件、网络环境条件下,给系统加载一定业务压力,使系统运行一段较长时间,一次检测系统是否稳定。在生产环境,请求压力时不均匀的,呈波浪特性,因此为了更好的模拟生产环境,稳定性测试也应不均匀的对系统施加压力。

性能测试怎么做:

1、使用通过性能测试客户端,模拟并发的请求数目(最简单的用一个线程模拟一个并发),不断增加线程数,模拟并发数,然后向系统发出并发请求,然后测试除系统的响应时间TPS、返回的错误率、以及其它的一些性能(负载、cpu、内存、I/O)。

2、经过多轮测试,将这些数据记录下来。然后画出曲线,通过分析这些数据,直到哪些资源是系统的瓶颈,然后考虑升级这些系统资源(如更换CPU、加装内存、使用缓存等)或者是通过分析资源的使用情况,判断是否代码有问题(比如内存占用特别大,是不是内存溢出了)。

二、全链路压测:

全链路压测:

指在特定的业务常场景下,将相关的链路完整的串联起来同时施压,测可能的模拟出真实的用户行为,当系统整站流量都被打上来的时候,必定会暴露出性能瓶颈,才能够探测出系统整体的真实处理能力,以及有指导的在大促前进行容量规划和性能优化,这就是线上实施全链路压测的目的。

全链路压测的挑战:

压测的系统众多,且牵扯到整条链路上的所有基础设施和中间件,如何确保压测流量能够畅通无阻,没有死角(就是压测数据怎么构造出来并且全覆盖),与真实贴近。

全链路压测直接在线上真实环境进行模拟,怎么保障对线上无影响。

全链路压测具体做法:

1、数据构造:

直接dump得到线上用户真实的数据->筛选,脱敏,Id隔离,订正->放入压测基础数据池。

2、数据隔离:

逻辑隔离:通过特殊的标识符区分开。

虚拟隔离:在写数据的地方做mock,并不是真正的去写。

物理隔离:对写数据的压测请求识别,写入到不同的服务器中。

3、流量构造:

通过CDN服务器部署压测服务压测。

三、性能优化的分层思想(不能只盯着代码优化):

1、性能优化的两个基本原则:

你不能优化一个没有测试的软件。

你不能优化一个你不了解的软件。

2、性能优化的一般方法:

1. 性能测试,获得性能指标。

2. 指标分析,发现性能与资源瓶颈点。

3. 架构与代码分析,寻找性能与资源瓶颈关键所在。

4. 架构与代码及其它优化,优化关键技术点,平衡资源利用。

5. 性能测试,进入性能优化闭环,验证优化结果。

3、性能优化的分层:

1. 机房与骨干网络性能优化。

异地多活的多机房架构(高可用,高性能),专线网络与自主CDN建设。

2. 服务器与硬件性能优化。

使用更优的CPU,磁盘,内存,网卡。

3. 操作系统性能优化。

Linux系统的不同参数的影响性能。

4. 虚拟机性能优化。

JVM虚拟机的GC等。

5. 基础组件性能优化。

使用不同的基础组件部署,性能也不同。如使用Jetty代替JBoss。

6. 软件架构性能优化。

缓存:优化读性能。

异步:优化写性能。

集群:

7. 软件代码性能优化。

遵循面向对象的设计原则与设计编程模式。

并发编程,多线程与锁。

资源复用,线程池与对象池。

异步编程,生产者消费者。

数据结构,数组、链表、hash表、树。

四、锁:

1、锁原语CAS:

CAS(V,E,N):Compare And Swap,是比较并替换,V表示内存中要更新的值,E表示预期值,N表示新值。这是一个原子操作,只有当预期的值和内存中的值一样才会替换,否则替换失败。

CAS在一个CPU的一个核心上执行是能保证是原子的,但是多个CPU的核心同时读取一个数据进行CAS的时候就会有问题。办法:总线锁、缓存锁。

2、Java锁:

锁的一部分信息存放在Java的对象头的Mark Word里面。当线程获取锁的时候,第一次会将对象头的Mark Word里的锁线程ID修改为当前线程ID,修改偏向锁的标记为1,此时获得偏向锁。

当在有其它的线程来获取锁的时候,会将对象头的Mark Word的偏向锁标记修改为轻量级锁,然后记录锁记录的指针,该线程会经过几次自旋的CAS操作修改锁的信息,尝试获得锁。

如果还是没有获得锁,锁就会升级为重量级锁,创建一个锁的监视器,并记录下该监视器的地址引用,然后线程将自己的线程ID放到锁的监视器里面等待锁的释放,此时线程就会阻塞等待释放CPU资源。

只有重量级锁,线程才会被阻塞。

 

Sychronized使用在方法上,是对这个类的实例对象加锁了。如果该实例多个方法都加了sychronized关键字,那么它们的加锁对象都是同一个,这些加锁方法都是互斥的。在静态方法上加了锁,那就是锁住了这个类。

3、公平锁非公平锁:

轻量级锁的获取是非公平锁,因为每次线程被调用的时候是不一定的。

4、可重入锁。

5、悲观锁/乐观锁:

悲观锁:认为对同一个数据的并发操作,一定是会发生修改的,哪怕没有修改也会认为是修改。因此对于同一个数据的并发操作,悲观锁才去加锁的方式。悲观锁认为,不加锁的并发操作一定会发生问题。修改会频繁发生。

乐观锁:认为对于同一个数据的并发操作,是不会发生修改的。在更新数据的时候,检查是否已经被修改,如果被修改,就放弃。乐观锁实际上不是一种锁,没有进行加锁操作,只是利用检查修改,达到锁一样的功能(如CAS)。修改不会频繁发生。

6、分段锁:

分段锁的设计目的是细化锁的粒度,当操作不需要更新整个数组的时候,就仅仅针对数据的一段进行加锁操作。

7、自旋锁:

值线程采取循环的方式尝试获取锁。

五、异步并发编程Akka:

1、 特性:

更简单的并发

更简单的分布式

更简单的容错能力

2、 核心Actor:

Akka都是依赖于Actor来运行起来的。

 

用户头像

jizhi7

关注

还未添加个人签名 2018.09.08 加入

还未添加个人简介

评论

发布
暂无评论
第七周-总结