【从0-1成为架构师】性能优化的手段

性能优化步骤

1.性能分析

用户从浏览器放出请求到数据库访问数据完成事务,中间要经过很多步骤,如果测试或者用户反应访问速度慢,那么有可能是中间的任何一个环节慢,反过来也可以说任何一个环节都有优化的可能。排查手法就是检查请求处理中的日志,分析那个环节的响应时间不合理,然后监控数据,分析影响性能的因素是内存,磁盘,网络还是cpu,是代码问题还是架构问题或者是系统资源不足。

2.性能优化

定位产生性能问题的具体原因后,就需要进行性能优化,根据网络分层架构,可分为web前端优化,应用服务器性能优化和存储服务器性能优化。

Web前端优化

浏览器访问优化

1.减少http请求

http协议是无状态的应用层协议,意味这每次HTTP请求都需要建立通信连接,进行数据传输,而在服务端,每个http请求都需要启动独立的线程去处理,这些通信和服务的开销都很昂贵,减少http请求的数目可以有效的减少性能损耗。
减少HTTP请求的手段通常就是合并css,合并js,合并图片,将浏览器一次访问需要的js,css合并成一个文件,这样浏览器就只需要一次请求。

2.使用浏览器缓存

对于一个网站而言,js,css,图片这些静态资源更新的频率都比较低,而这些资源又是http请求时必要的,所以可以把这些静态资源缓存到浏览器中,减少http请求中的数据量来减少损耗,通过设置http头中的cache-control和expires属性,可设定缓存,缓存可以是几天或者几个月。
有的时候需要更新静态资源,这个时候可以上传一个新名称的js文件,然后再html里引用新的js文件,而不是在旧的文件上修改。
使用浏览器缓存策略的网站在批量更新静态资源的时候应该避免同时更新多个资源,而是一个资源一个资源的更新,避免更新多个资源造成网络堵塞的情况。

3.启用压缩

在服务端对文件进行压缩,在浏览器对文件进行解压缩,可有效减少文件传输的数据量,因此css,js,html文件进行gzip压缩可以达到很好的效果,但是要注意,压缩会对服务器和浏览器造成一定的压力,在实际使用中要结合服务器的性能和带宽综合考虑。

4.css放最上面,js放最下面

浏览器会加载完所有的css之后在对界面进行渲染,因此最好的办法是将css放在最上面,让浏览器尽早的下载完css,反之js是浏览器加载完之后立刻执行,因此应该放在页面最下面,不然可能会阻塞整个页面。

5.减少cookie传输

一方面,cookie包含在每次的请求和响应中,太大的cookis会严重影响数据传输,因此哪些数据需要写入cookie需要慎重考虑。

6.cdn加速

cnd(内容分发网络),本质上就是一个缓存,并且将数据缓存到离用户最近的地方,使用户可以最快的获取到数据。
由于cdn部署在网络服务商的机房,所以当用户一请求就会到达cdn服务器,当cdn中有资源会直接放回给用户,减少数据请求损耗

7.反向代理

传统服务代理是假设在浏览器一侧,代理浏览器会将http请求发到互联网上,而反向代理服务假设在机房测,代理网站web接收http请求。
反向代理一个也可以缓存静态资源,当需要静态资源时直接从缓存中拿,如果缓存中没有再去服务器请求,可以减少请求的损耗,另一方面反向代理可以支持负载均衡,通过负载均衡可以将服务器变成集群来更好的提供访问请求能力。

应用服务器性能优化

缓存

回顾网站优化的历史进程,当网站遇到瓶颈的时候,第一个想到的方案就是缓存,在整个网站应用中,缓存几户无处不在。合理利用缓存对性能优化意义重大。

1.缓存基本原理

缓存是将数据存储到可以高速访问的介质中,例如内存,一方面缓存的存储读取速度快,另一方面可以将计算好的数据存储到缓存中,这样再次获取的时候就可以避免二次计算。
缓存的本质就是一个内存中的hash表,数据缓存是由key,value的键值对存放在hash表中,hash表的数据存储时间复杂度为O(1)。计算kv中的key的hashcode指向hash表的索引,可以快速访问hash表的数据,许多语言都支持获得任意对象的hashcode,可以把hashcode理解为对象的唯一标识符。jaba语言中的hashcode方法在object中,其返回值是一个int,然后通过hashcode找到hash表中的下表,最简单的就是余数法,
缓存主要用来存放那些很少变化,读的频率很高的数据,应用程序读取数据的时候先从缓存中读取,如果获取不到在从数据库中读取。网站的数据遵从28定律,既80%的请求都是获取20%的数据,将这20%的数据缓存起来,可以有效的提高网站的性能。

2.合理的运用缓存

使用缓存可以提高网站的性能,但是使用缓存也需要有些注意事项。不合理的理由缓存不止不能提高性能,还有可能成为累赘。

  1. 频繁修改的数据
    如果缓存中存的是频繁修改的数据,可能会出现数据写入缓存后,应用还来不及读取,缓存就更新了,徒增系统负担,一般来说缓存的读写比至少是2:1,这样缓存才有存在的意义,实际情况中读写比会比这个还要高很多
  2. 没有热点的访问
    没有热点的访问数据存在缓存中一个是会增加系统的负担,另外也会将有价值的数据挤出缓存
  3. 数据不一致和脏读
    一般会对缓存进行过期时间的设定,一旦超过过期时间,就会从数据库里重新读取数据到缓存,因此要容忍一定时间的数据不一致性。例如卖家将商品发货了,买家需要等一会才能收到通知,这种在互联网场景中一般是可以接受的,但是如果涉及到改价格,那么就需要考虑考虑了。
  4. 缓存雪崩
    缓存是用来提高网站性能的,缓存不可用或者丢失不会影响到服务的运行,因为可以从数据库重新读取,但是随着业务的发展,服务可能会越来越依靠缓存,如果这个这个时候缓存挂掉,数据全部打到数据库上,服务可能会因为接收不了这么多请求而崩溃,这种情况成为缓存雪崩。
  5. 缓存穿透
    如果因为不恰当的业务或者恶意攻击持续的高并发的请求某一个不存在的缓存,由于缓存没有存储该数据,所有的请求都会打到数据库上,会对数据库造成很大的压力,甚至崩溃,所以可以把不用的数据也缓存下来存个空之类的。
异步

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6t0lfSCx-1661258448535)(evernotecid://DED20B32-7319-43F6-995F-0BB020671E91/appyinxiangcom/22603206/ENResource/p909)]

在不使用消息队列的时候,用户的请求直接打到数据库上,在高并发的情况下会对数据库产生很大的压力,同时也是响应时间加剧,在使用消息队列后,将消息发送到消息队列后立即返回,再由消息队列的消费者进程从消息队列获取消息,异步写入数据库,由于消息队列服务器处理速度远快于数据库,因此对响应速度有很大的提升。
需要注意的是消息发送到消息队列就会立即返回,并不能保证消息真正的消费成功,所以在消费端成功消费了消息之后要通过接口或者其他的形式通知到生产者。

集群

在网站高并发的情况下,使用负载均衡技术为一个应用创建一个由多个服务器组成的服务器集群,将并发访问请求分发到多台服务器上,避免单一服务器因压力过大而响应缓慢,使用户请求具有更好的响应延迟特性。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xOVV24eX-1661258448537)(evernotecid://DED20B32-7319-43F6-995F-0BB020671E91/appyinxiangcom/22603206/ENResource/p910)]

代码优化
多线程

从资源利用的角度来看,开启多线程的原因主要有两个:io阻塞和多cpu,当前线程在进行io处理的时候,会被组阻塞释放cpu以等待io操作完成,由于io操作通常需要大量的时间,这是cpu可以调度其他的线程进行处理。利用多线程IO阻塞和执行之间交替,可以最大限度的利用cpu。使用多线程的另外一个原因是服务器有多个cpu,想要最大限度的利用cpu就必须开启多线程。
启动线程数=[(任务执行时间/任务执行时间-io等待时间)*CPU内核数]
多线程编程一个需要注意的问题就是线程安全问题,即多线程并发对同一个资源进行修改,造成数据混乱。解决这个问题的方案有如下几种:

  • 将对象设置为无状态对象
  • 使用局部对象
  • 并发访问的时候使用锁
资源复用

系统运行的时候,要尽量减少那些开销很大的系统资源的创建和销毁,比如数据库连接,线程,复杂对象等。解决办法主要有两种:线程池和单例模式。

相关文章

学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习...
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面...
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生...
Can’t connect to local MySQL server through socket \'/v...
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 ...
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服...