ITPub博客

首页 > 应用开发 > Java > 大型网站背后的高性能系统架构设计

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

原创 Java 作者:lihong 时间:2019-05-06 15:57:26 0 删除 编辑

1. 性能测试

1.1. 性能指标

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

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

1.2. 性能测试方法

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

1.3. 性能测试报告

性能测试报告示例:

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 支持。


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/69917606/viewspace-2643472/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
毕业于西安电子科技大学,曾任职于中国电信的上市子公司号百控股担任项目经理,超过十年java开发经验,具备多个行业项目产品开发经验,精通Java,熟悉分布式技术,大数据,搜索引擎技术,对MySQL/Oracle等主流数据库的优化及调优有丰富的经验。

注册时间:2019-04-23

  • 博文量
    105
  • 访问量
    116198