大型网站背后的高性能系统架构设计

1. 性能测试

1.1. 性能指标

网站性能测试的主要指标有:前端

  • 响应时间 - 响应时间(RT)是指从客户端发一个请求开始计时,到客户端接收到从服务器端返回的响应结果结束所经历的时间,响应时间由请求发送时间、网络传输时间和服务器处理时间三部分组成。
  • 并发数 - 系统同时处理的请求、事务数。
  • 吞吐量 - TPS(每秒事务数)、HPS(每秒 HTTP 请求数)、QPS(每秒查询数)。
  • 性能计数器 - 系统负载、对象与线程数、内存使用、CPU 使用、磁盘与网络 IO 等。这些指标也是系统监控的重要参数。

1.2. 性能测试方法

  • 性能测试
  • 负载测试
  • 压力测试
  • 稳定性测试

1.3. 性能测试报告

性能测试报告示例:sql

1.4. 性能优化策略

  1. 性能分析 - 若是请求响应慢,存在性能问题。须要对请求经历的各个环节逐一分析,排查可能出现性能瓶颈的地方,定位问题。检查监控数据,分析影响性能的主要因素:内存、磁盘、网络、CPU,多是代码或架构设计不合理,又或者是系统资源确实不足。
  2. 性能优化 - 性能优化根据网站分层架构,大体可分为前端性能优化、应用服务性能优化、存储服务性能优化。

2. 前端性能优化

2.1. 浏览器访问优化

  1. 减小 HTTP 请求 - HTTP 请求须要创建通讯链路,进行数据传输,开销高昂,因此减小 HTTP 请求数能够有效提升访问性能。减小 HTTP 的主要手段是合并 Css、JavaScript、图片。
  2. 使用浏览器缓存 - 由于静态资源文件更新频率低,能够缓存浏览器中以提升性能。设置 HTTP 头中的 Cache-Control 和 Expires 属性,能够设定浏览器缓存。
  3. 启用压缩 - 在服务器端压缩静态资源文件,在浏览器端解压缩,能够有效减小传输的数据量。因为文本文件压缩率可达 80% 以上,因此能够对静态资源,如 Html、Css、JavaScrip 进行压缩。
  4. CSS 放在页面最上面,JavaScript 放在页面最下面 - 浏览器会在下载彻底部的 Css 后才对整个页面进行渲染,因此最好的作法是将 Css 放在页面最上面,让浏览器尽快下载 Css;JavaScript 则相反,浏览器加载 JavaScript 后当即执行,可能会阻塞整个页面,形成页面显示缓慢,所以 JavaScript 最好放在页面最下面。
  5. 减小 Cookie 传输 - Cookie 包含在 HTTP 每次的请求和响应中,太大的 Cookie 会严重影响数据传输。

2.2. CDN

CDN 通常缓存的是静态资源。数据库

CDN 的本质仍然是一个缓存,并且将数据缓存在离用户最近的地方,使用户已最快速度获取数据,即所谓网络访问第一跳。编程

2.3. 反向代理

传统代理服务器位于浏览器一侧,代理浏览器将 HTTP 请求发送到互联网上,而反向代理服务器位于网站机房一侧,代理网站服务器接收 HTTP 请求。浏览器

反向代理服务器能够配置缓存功能加速 Web 请求,当用户第一次访问静态内容时,静态内容就会被缓存在反向代理服务器上。缓存

反向代理还能够实现负载均衡,经过负载均衡构建的集群能够提升系统整体处理能力。安全

由于全部请求都必须先通过反向代理服务器,因此能够屏蔽一些攻击 IP,达到保护网站安全的做用。性能优化

3. 应用服务性能优化

3.1. 分布式缓存

网站性能优化第必定律:优先考虑使用缓存优化性能。服务器

缓存原理

缓存指将数据存储在相对较高访问速度的存储介质中,以供系统处理。一方面缓存访问速度快,能够减小数据访问的时间,另外一方面若是缓存的数据是通过计算处理获得的,那么被缓存的数据无需重复计算便可直接使用,所以缓存还起到减小计算时间的做用。网络

缓存的本质是一个内存 HASH 表。

缓存主要用来存放那些读写比很高、不多变化的数据,如商品的类目信息,热门词的搜索列表信息、热门商品信息等。

合理使用缓存

缓存数据的选择:

  • 不要存储频繁修改的数据
  • 不要存储非热点数据

数据不一致和脏读:

  • 缓存有有效期,因此存在必定时间的数据不一致和脏读问题。若是不能接受,能够考虑使用数据更新当即更新缓存策略

须要考虑缓存问题:缓存雪崩、缓存穿透、缓存预热

3.2. 异步操做

异步处理通常是经过分布式消息队列的方式。

异步处理能够解决一下问题:

  • 异步处理
  • 应用解耦
  • 流量削锋
  • 日志处理
  • 消息通信

3.3. 使用集群

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

3.4. 代码优化

多线程

从资源利用的角度看,使用多线程的缘由主要有两个:IO 阻塞和多 CPU。

线程数并不是越多越好,那么启动多少线程合适呢?

有个参考公式:

启动线程数 = (任务执行时间 / (任务执行时间 - IO 等待时间)) * CPU 内核数

最佳启动线程数和 CPU 内核数成正比,和 IO 阻塞时间成反比。若是任务都是 CPU 计算型任务,那么线程数最多不要超过 CPU 内核数,由于启动再多线程,CPU 也来不及调度;相反若是是任务须要等待磁盘操做,网络响应,那么多启动线程有助于任务并罚赌,提升系统吞吐量。

线程安全问题

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

资源复用

应该尽可能减小那些开销很大的系统资源的建立和销毁,如数据库链接、网络通讯链接、线程、复杂对象等。从编程角度,资源复用主要有两种模式:单例模式和对象池。

数据结构

根据具体场景,选择合适的数据结构。

垃圾回收

若是 Web 应用运行在 JVM 等具备垃圾回收功能的环境中,那么垃圾回收可能会对系统的性能特性产生巨大影响。当即垃圾回收机制有助于程序优化和参数调优,以及编写内存安全的代码。

4. 存储性能优化

4.1. 机械键盘和固态硬盘

考虑使用固态硬盘替代机械键盘,由于它的读写速度更快。

4.2. B+数和 LSM 树

传统关系数据库的数据库索引通常都使用两级索引的 B+ 树结构,树的层次最多三层。所以可能须要 5 次磁盘访问才能更新一条记录(三次磁盘访问得到数据索引及行 ID,而后再进行一次数据文件读操做及一次数据文件写操做)。

因为磁盘访问是随机的,传统机械键盘在数据随机访问时性能较差,每次数据访问都须要屡次访问磁盘影响数据访问性能。

许多 Nosql 数据库中的索引采用 LSM 树做为主要数据结构。LSM 树可视为一个 N 阶合并树。数据写操做都在内存中进行。在 LSM 树上进行一次数据更新不须要磁盘访问,速度远快于 B+ 树。

4.3. RAID 和 HDFS

HDFS(分布式文件系统) 更被大型网站所青睐。它能够配合 MapReduce 并发计算任务框架进行大数据处理,能够在整个集群上并发访问全部磁盘,无需 RAID 支持。

相关文章
相关标签/搜索