架构师第二期 第 7 周总结
性能测试的主要指标
响应时间:完成一次任务花费的时间。
并发数:同时处理的任务数。
吞吐量:单位时间完成的任务数。
性能计数器:System load、线程数、进程数、CPU、内存、硬盘、网络使用率
性能优化的一般方法
性能测试、获得性能指标。
指标分析、发现性能与资源瓶颈点
架构与代码分析,寻找性能与资源瓶颈关键所在
架构与代码及其他优化,优化关键技术点,平衡资源利用
性能测试,进入性能优化闭环
系统性能优化的分层思想
机房与骨干网络性能优化
服务器与硬件性能优化
操作系统性能优化
虚拟机性能优化
基础组件性能优化
软件架构性能优化
软件代码性能优化
机房与骨干网络性能优化
异地多活的多机房架构
专线网络与自主CDN建设
服务器与硬件性能优化
使用更好的CPU,磁盘、内存、网卡等。比如机械硬盘替换传统硬盘
虚拟机性能优化
垃圾回收算法选择
基础组件性能优化
修改基础组件、中间件(常见的比如apache 、jetty等)的版本,或者换上更优秀的组件。
软件架构性能优化
缓存、异步、集群
缓存:主要优化读操作;缓存结果对象,而不是原始数据,减少CPU计算。
异步:及时响应,提供更好的用户体验。优化写操作。降低压力。
集群:技术目标是如何使多台服务器对使用者而言看起来像是一台机器。
软件代码性能优化
遵循面向对象的设计原则与设计模式编程,编写易于扩展、易于维护的代码。抛弃没必要的逻辑、业务、代码块,不要炫技。
软件代码性能优化:并发编程,多线程与锁;资源复用,线程池与对象池;异步编程,生产者与消费者;数据结构,数组,链表、HASH表,树。
操作系统多任务运行环境
计算机的CPU核心数是有限的,但服务器可以同时处理数以百计、甚至数以千计的并发用户请求。它是通过进程分时执行实现的。
Java web 应用多线程运行
1、操作系统把Java虚拟机启动起来。当Java虚拟机启动起来时,它要加载一个可执行的入口类。图中的案例为Tomcat提供的bootstrap执行类,这个类中一定有一个main方法。
2、Java去装载这个类到自己的JVM虚拟机内存中,然后找到类中的main入口函数,从该函数开始执行。从而启动JVM进程,应用程序就启动起来了。这里的应用程序不是指我们开发的应用程序,而是指tomcat提供的应用。Java看不到我们的应用,它看到的是Tomcat提供的。
3、进了这个main函数,Tomcat会初始化,比如监听80端口,或者其他配置的端口;接着启动多个用户线程,用于等待端口连接。
4、当远程端口连接进来的时候,就会为每个连接(图中用户)分配一个线程(由它处理这个连接)。端口连接传来的参数由Tomcat解析为request对象、response对象、session上下文,去完成主类的初始化。
5、初始化完成后,就去调应用程序的Servlet代码(doGet, doPost方法)。如果在执行的过程中,我们有些代码用到共享资源,需要加锁,就需要这些线程排队获取资源,所以我们通常不会在servlet里加一些锁操作,避免资源竞争。实际开发时是借助spring框架编程为主,处理好controller层代码即可。在这种场景下,用户请求进来后,会先执行spring的Servlet,由它去调用我们编写的controller类。这里面的调用,关键是请求路径到请求方法的映射,
线程安全问题
多线程共享变量,共同对变量进行数据变更时,会出现线程安全问题。
临界区指多个线程访问共享资源的这段代码。 临界区加锁的方法解决该问题。
锁会引起线程阻塞,既不能执行,也不能释放资源,高并发下,容易导致系统崩溃。
可以用限流、降级、反应式(异步;无临界区actor模型)的方法解决该问题。
CAS (compare and set)
在Java中 ,锁是记录在对象头上的,叫Mark Word
当我们在Java对象前加了synchronize时,表示synchronize this,表示当前对象的这个锁是否已经被获取了,如果已经被获取了,请求的线程就无法进入这个对象。
1、初始时没有锁。
2、一个线程进入临界区,通过CAS知道当前未加锁,于是将Mark word 设置为偏向锁,接着该线程就可以执行了。
3、此时,其他线程也想获得锁。它读出来是个偏向锁,已经被别人执行了,就知道不能进入临界区了。
这个时候,会进行锁升级,升级为轻量级的锁。这个轻量级锁会记录一个锁记录指针,这些其他的线程就持续的执行CAS(自旋,while循环),企图把自己的锁记录 set到这个地方。
4、如果某个线程持续的CAS依旧无法(指一段时间)SET锁记录指针,会再次触发锁升级,升级为重量级锁。重量级锁里面记录的是一个监视器,指向一个队列。此时当前线程不再进行CAS,它会进入队列排队,也意味进入了阻塞状态,等待监视器唤醒。
评论