高性能架构
一、不同视角下的网站性能。
- 用户视角:就是用户在浏览器上直观感受的网站响应速度快还是慢。
- 开发视角:应用程序本身及其子系统的性能,包括响应延迟、系统吞吐量、并发处理能力、系统稳定性等技术指标。
- 运维视角:基础设施性能和资源利用率。
二、相对应的优化手段。
- 前端架构优化手段(使浏览器尽快的显示用户感兴趣的内容、尽可能近的获取页面内容):
- 优化HTML页面样式。
- 利用浏览器端的并发和异步特性。
- 调整浏览器缓存策略。
- 使用CDN服务。
- 反向代理等。
- 后端架构优化手段:
- 使用缓存加速数据读取。
- 使用集群提高吞吐能力。
- 使用异步消息加快请求响应及实现削峰。
- 使用代码优化手段改善程序性能。
- 服务器优化手段:
- 建设优化骨干网。
- 使用高性价比定制服务器。
- 利用虚拟化技术优化资源。
三,常用的系统操作响应时间。(仅供参考)
操作 | 响应时间 |
L1缓存 | 1ns |
分支错误 | 3ns |
二级缓存 | 4ns |
互斥锁/解锁 | 17ns |
压缩1KB的Zippy | 2,000ns≈2μs |
通过商品网络发送2,000字节 | 88ns |
SSD随机读取 | 16,000ns≈16μs |
从存储器中顺序读取1,000,000字节 | 5,000ns≈5μs |
往返于同一数据中心 | 500,000ns≈500μs |
从SSD中顺序读取1,000,000字节 | 78,000ns≈78μs |
磁盘查找 | 3,000,000ns≈3ms |
从磁盘顺序读取1,000,000字节 | 1,000,000ns≈1ms |
将数据包往返于荷兰 | 150,000,000ns≈150ms |
从远程分布式缓存Redis读取一个数据 | 0.5ms |
机械磁盘一次寻址定位 | 4ms |
在数据库中查询一条记录(有索引) | 十几ms |
打开一个网站 | 几秒 |
https://people.eecs.berkeley.edu/~rcs/research/interactive_latency.html
四、吞吐量
指单位时间内系统处理的请求数量,体现系统的整体处理能力。
TPS:(每秒事务数)是吞吐量的一个常用量化指标。
HPS:(每秒HTTP请求数)。
QPS:(每秒查询数)。
五、性能测试方法
性能测试、负载测试、压力测试、稳定性测试。
测试目标:1、系统的最大负载点。2、系统的崩溃点。
六、性能分析
排查一个网站或者程序瓶颈的手法基本相同:检查请求处理的各个环节的日志,分析哪个环节响应时间不合理、超过预期;然后检查监控数据,分析影响性能的主要因素是内存、磁盘、网络还是CPU,
是代码问题还是架构设计不合理,或者系统资源确实不足。
七、优化方案:
1、Web前端性能优化
一:浏览器访问优化
- 减少http请求 HTTP协议是无状态的应用层协议,意味着每次HTTP请求都需要建立通信链路、进行数据传输,而在服务器端,每个HTTP都需要启动独立的线程去处理。这些通信和服务的开销都很昂贵,减少HTTP请求的数目可有效的提高访问性能。 eg::合并CSS、合并JavaScript、合并图片等。
- 使用浏览器缓存 对一个网站而言,css、js、logo等静态资源文件更新频率比较低,而这些文件又是每次HTTP请求都需要的,如果缓存在浏览器上,可以极好的改善性能。 eg:通过设置HTTP头中的Cache-Control和Expires属性,可设置浏览器缓存,时间可以是几天or几个月。 使用浏览器缓存策略的网站在更新静态资源时,应采用逐量更新 的方法,避免突然大量缓存失效。
- 启用压缩 在服务器端对文件进行压缩,在浏览器端对文件解压缩,可有效减少通信传输的数据量。 CSS放在页面最上面,javascript放在页面最下面。 浏览器会在下载完全部CSS之后才对整个页面进行渲染。 javacsript则相反,浏览器在加载js后立即执行,有可能会阻塞整个页面
- 减少cookie传输 Cookie包含在每次请求和响应中,太大的Cookie会严重影响数据传输。
二:CDN加速
CDN(Content Distribute Network,内容分发网络)的本质仍然是一个缓存,而且将数据缓存在离用户最近的地方,使用户以最快速度获取数据,即所谓网络访问第一跳。
三:反向代理
可以配置缓存加速web请求
2、应用服务器性能优化
网站性能优化第一定律:优先考虑使用缓存优化性能
一:分布式缓存
1、缓存的基本原理 缓存指将数据存储在相对较高访问速度的存储介质中,以供系统处理。 网站数据访问通常遵循二八定律,即80%的访问落在20%的数据上,因此利用Hash表和内存的高速访问特性,将这20%的数据缓存起来,可很好的改善系统性能。
2、合理使用缓存
频繁修改的数据:不宜使用缓存。
(数据的读写比在2:1以上,即写入一次缓存,在数据更新前至少读取两次,缓存才有意义)
没有热点的访问:不宜使用缓存。
(如果应用系统访问数据没有热点,不遵循二八定律,即大部分数据访问并没有集中在小部分数据上,那么缓存也就没有意义)
数据不一致与脏读:如果不能容忍一定时间的数据不一致,也不建议使用缓存。
缓存可用性:缓存是为了提高数据读取性能,缓存数据丢失或者缓存不可用不会影响到应用程序的处理,因为可以从数据库直接获取数据。
但当缓存服务崩溃时,数据库的压力会骤然增加,严重会导致宕机。
(所以需要避免 缓存雪崩)
缓存预热:缓存中存放的是热点数据,热点数据又是缓存系统利用LRU对不断访问的数据筛选淘汰数来的,这个过程需要花费较长的时间。如果是新启动的缓存系统,如果没有任何数据,在重建缓存数据的过程中
系统的性能和负载都不太好,那么最好在缓存系统启动时就把热点数据加载好。
缓存穿透:如果因为不恰当的业务或者恶意攻击持续高并发地请求某个不存在的数据,由于缓存没有保存该数据,所有的请求都会落在数据库上,会对数据库造成很大的压力,甚至崩溃。
(一个简单的对策是将不存在的数据也缓存起来)
3、分布式缓存架构
指缓存部署多个服务器组成的集群中,以集群方式提供缓存服务。
4、Memcached
(简单的通信协议、丰富的客户端程序、高性能的网络通信、高效的内存管理、互不通信的服务器集群架构)
二: 异步操作
任何可以晚点做的事情都应该晚点再做。
使用消息队列将调用异步话,通过异步处理,将短时间高并发产生的事务消息存储在消息队列中,从而削平高峰期的并发事务。 ----- 消息队列具有很好的削峰作用
三:使用集群
在高并发访问的场景下,使用负载均衡技术为一个应用构建一个由多台服务器组成的服务器集群,将并发访问请求分发到多台服务器上处理,避免单一服务器因负载压力过大而响应缓慢。
四:代码优化
1、多线程 使用多线程的原因主要有两个:IO阻塞与多CPU。 (理想的系统Load是既没有进程(线程)等待也没有CPU空闲)。 启动线程数=[任务执行时间/(任务执行时间-IO等待时间)] * CPU内核数 解决线程安全的主要手段: ①: 将对象设计为无状态对象(指对象本身不存储状态信息),这样多线程并发访问的时候就不会出现状态不一致,java web 开发中常用的servlet对象就设计为无状态对象。 ②:使用局部对象 ③:并发访问资源时使用锁 2、资源复用 从编程角度,资源复用主要两张模式:单例(Singleton) 和对象池 (Object Pool) 比如:数据库连接、网络通信连接、线程、复杂对象等。 3、数据结构 4、垃圾回收 合理设置堆大小,减少Full GC次数
3、存储性能优化
①、机械硬盘 & 固态硬盘
②、B+树 & LSM树
③、RAID & HDFS