写点什么

架构师训练营 4 期 第 7 周

用户头像
引花眠
关注
发布于: 2021 年 02 月 14 日

作业一(至少完成一项):

性能压测的时候,随着并发压力的增加,系统响应时间和吞吐量如何变化,为什么?


响应时间: 从用户发送一个请求到用户接收到服务器返回的响应数据这段时间就是响应时间。 吞吐量:单位时间内系统处理的客户端请求的数量,只要用 TPS 衡量。


随着并发压力的增加,系统响应时间越来越长,直至系统崩溃,因为随着并发的增加,后端服务处理请求所需的服务器资源上升, 响应时间先小幅上升,当达到系统吞吐量极限时,响应时间快速上升直至系统崩溃,响应超时。



随着并发压力的增加,后端服务处理请求所需的服务器资源上升,系统吞吐量先逐渐增加,当达到系统最大负载能力时到达最高点,之后并发请求数增加吞吐量下降,直至系统崩溃,吞吐量为 0


用你熟悉的编程语言写一个 Web 性能压测工具

输入参数:URL,请求总次数,并发数。输出参数:平均响应时间,95% 响应时间。用这个测试工具以 10 并发、100 次请求压测 www.baidu.com


压测工具


作业二:根据当周学习情况,完成一篇学习总结

本周关注的是性能优化相关

性能测试

如果有进行性能优化,那么首先要知道现在性能的状态,否则就谈不上优化,而性能测试正是性能优化的前提和基础,也是性能优化结果的检查和度量标准。


主观视角:用户感受到的性能。 客观视角:性能指标衡量的性能。


优化前必须做性能测试,没有性能测试谈优化无异于耍流氓。


性能测试的主要指标:响应时间、并发数、吞吐量、性能计数器等。 吞吐量:(1000/相应时间 ms)* 并发数


性能测试方法:性能测试、负载测试、压力测试、稳定性测试。


吞吐量与并发用户数关系


响应时间与并发用户数关系


性能优化

基本原则:

  1. 不能优化一个没有做性能测试的软件

  2. 不能优化一个不了解的软件


性能优化的一般方法:


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

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

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

  4. 架构与代码分析,优化关键技术,平衡资源利用

  5. 性能测试,进入性能优化闭环


系统性能优化的分层思想,从距离用户最近的地方开始:


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

  2. CDN 缓存静态资源

  3. 服务器与硬件性能优化

  4. 使用更好的硬件 CPU、内存、网卡等

  5. 操作系统性能优化

  6. 定制操作系统使其适合所执行的任务

  7. 虚拟机性能优化(JVM)

  8. 选择合适的垃圾收集器

  9. 设置合适的启动参数

  10. 选择合适的版本

  11. 基础组件性能优化

  12. 使用更高版本的第三方组件,可能会对性能有优化

  13. 使用更高性能的组建,比如数据库连接池可以使用 HikariCP 连接池

  14. 软件架构性能优化

  15. 缓存 对于读性能有很大提升

  16. 异步 异步主要优化写操作

  17. 集群 使很多台服务器对使用者而言看起像一台服务器

  18. 软件代码性能优化

  19. 并发编程,多线程与锁资

  20. 源复用,线程池与对象池

  21. 异步编程,生产者消费者

  22. 数据结构,数组、链表、hash 表、树


操作系统

程序运行时架构 程序是静态的,程序运行起来以后,被称作进程。 通过分时运行,服务器可以同时处理数以百计甚至数以千计的并发用户请求。


进程的运行期状态:

  1. 运行:当一个进程在 CPU 上运行时,则称该进程处于运行状态。处于运行状态的进程的数目小于等于 CPU 的数目。

  2. 就绪:当一个进程获得了除 CPU 以外的一切所需资源,只要得到 CPU 即可运行,则称此进程处于就绪状态,就绪状态有时候也被称为等待运行状态。

  3. 阻塞:也称为等待或睡眠状态,当一个进程正在等待某一事件发生(例如等待 I/O 完成,等待锁……)而暂时停止运行,这时即使把 CPU 分配给进程也无法运行,故称该进程处于阻塞状态。


进程与线程

不同进程轮流在 CPU 上执行,每次都要进行进程间 CPU 切换,代价非常大。 以前进程既是资源分配又是 CPU 调度的基本单位,后来为了更好的利用高性能的 CPU,将资源分配和 CPU 调度分开。 因此,出现了线程因此服务器应用通常是单进程多线程。


进程和线程的关系:


  1. 一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。

  2. 资源分配给进程,同一进程的所有线程共享该进程的所有资源。

  3. 处理机分给线程,即真正在处理机上运行的是线程。

  4. 线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。线程是指进程内的一个执行单元,也是进程内的可调度实体.


进程与线程的区别:


  1. 调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位

  2. 并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行

  3. 拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源.

  4. 系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销。

  5. 通信方式 进程拥有各自独立的地址空间,进程间的通信需要依靠 IPC;线程共享进程资源,线程间可以通过访问共享数据进行通信。


线程栈

线程中方法调用会使用栈来传递参数和结果,正在执行的函数放在栈顶,当执行结束后将移除栈顶继续执行之前的函数。


线程安全

当某些代码修改内存堆(进程共享内存)里的数据的时候,如果有多个线程在同时执行,就可能会出现同时修改数据的情况,比如,两个线程同时对一个堆中的数据执行 +1 操作,最终这个数据只会被加一次,这就是人们常说的线程安全问题,实际上线程的结果应该是依次加一,即最终的结果应该是 +2。


多个线程访问共享资源的这段代码被称为临界区,解决线程安全问题的主要方法是使用锁,将临界区的代码加锁,只有获得锁的线程才能执行临界区代码。 比如上述问题,可以对数据+1 的操作加锁,使其不能同时修改数据,这样就能得到正确的结果。


锁是用来保证临界区数据一致性的一种机制,


锁分类

从不同的维度看其有不同的分类。


是否会有其他线程修改数据


悲观锁认为对于同一个数据的并发操作,一定是会发生修改的,哪怕没有修改,也会认为修改。因此对于同一个数据的并发操作,悲观锁采取加锁的形式。悲观的认为,不加锁的并发操作一定会出问题。


乐观锁则认为对于同一个数据的并发操作,是不会发生修改的。在更新数据的时候,检 查是否已经被修改过,如果修改过,就放弃。


是否按照顺序获取锁


公平锁 多个线程按照申请锁的顺序来获取锁的


非公平锁 多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁,可能会造成饥饿现象


是否可访问其他同步方法


可重入锁 线程拥有对象的同步方法锁后可访问其他同步方法 ,java 中 synchronized 和 ReentrantLock 都是可重入锁


不可重入锁 当线程拥有对象的同步方法锁后再访问其他同步方法也需要排队或等待


Java 内置加锁机制

1.6 之中,为了提升 Synchronized 的性能, Java 增加了自适应自旋、锁消除、锁粗化、轻量级锁、偏向锁等来高效地共享数据,解决竞争问题。Java 通过 CAS 原语在对象头中修改 Mark Word 实现加锁。


自旋锁 指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗 CPU。


自适应自旋 是对自旋锁的优化,自旋锁的缺点就是如果锁占用的时间很长,那么就会浪费处理器资源,并且还对处理器有要求。加入自适应自旋就是自旋的时间不再固定,而是由前一个在同一个锁上的自旋时间以及锁的拥有者的状态决定,如果在同一个锁对象上,自旋等待刚刚成功获取过锁,并且持有锁的线程正在运行中,那么虚拟机会认为这次自旋很可能再次成功,应此可能允许等待时间更长;如果某一个锁上,很少自旋成功,那么将跳过自旋过程,避免资源浪费。


偏向锁:指一段同步代码一直被一个线程所访问,那么该线程会自动获取锁,降低获取锁的代价


轻量级锁:指当锁是偏向锁时,被另一个线程所访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,提高性能


重量级锁:指当锁是轻量级锁时,另一个线程虽然自旋,但自旋不会一直持续下去,当自旋到一定次数时,还没获取到锁,就会进入阻塞,该锁膨胀为重量级锁,重量级锁会让其他申请的线程进入阻塞,性能降低


发布于: 2021 年 02 月 14 日阅读数: 24
用户头像

引花眠

关注

还未添加个人签名 2018.06.11 加入

还未添加个人简介

评论

发布
暂无评论
架构师训练营 4 期 第7周