同步操作将从 turnon/blog 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
title: 系统高性能架构
date: 2018-07-05 15:11:00
categories:
- 设计
- 架构
- 综合
tags:
- 架构
- 性能
permalink: /pages/a49605/
要设计高性能的系统架构,应该有以下的思维步骤:
首先,要明确影响性能的因素有哪些?性能的指标有哪些?——做到有的放矢。
其次,要了解如何测试性能指标?性能优化,必须要有前后的效果对比,才能证明性能确实有改善。
接下来,学习针对不同场景下,不同性指标的优化策略以及具体实施方案。——见招拆招。
了解性能指标前,需要先知道哪些计算机资源会影响性能。一般来说,影响性能的计算机资源包括:
性能测试的主要指标有:
响应时间(RT)是指从客户端发一个请求开始计时,到客户端接收到从服务器端返回的响应结果结束所经历的时间,响应时间由请求发送时间、网络传输时间和服务器处理时间三部分组成。
响应时间越短,性能越好,一般一个接口的响应时间是在毫秒级。
响应时间可以进一步细分:
并发数是指系统能同时处理的请求、事务数。
系统自身的 CPU 处理能力、内存、以及系统自身的线程复用、锁竞争等都会影响并发数。
吞吐量计算公式:
吞吐量 = 并发数 / 平均响应时间
吞吐量越大,性能越好。
一般,系统呈现给外部的最常见的吞吐量指标,就是:
QPS(每秒查询数)
- 即系统每秒可以处理的读请求。TPS(每秒事务数)
- 即系统每秒可以处理的写请求。而在系统内部,存在以下吞吐量:
通常由 CPU 占用率、内存使用率、磁盘 I/O、网络 I/O 、对象与线程数来表示资源使用率。这些指标也是系统监控的重要参数。
性能测试手段:
对于 Java 应用而言,最简单的,可以使用 Jmeter 进行性能测试。
性能测试报告示例:
性能测试时,需要注意一些问题:
网站性能优化第一定律:第一优先考虑使用缓存提升性能。
缓存是用于存储数据的硬件或软件的组成部分,以使得后续更快访问相应的数据。缓存中的数据可能是提前计算好的结果、数据的副本等。
缓存解决方案请参考:缓存基本原理
高并发需要根据两个条件划分:连接数量,请求数量。
单服务器高性能的关键之一就是服务器采取的并发模型
以上两个设计点最终都和操作系统的 I/O 模型及进程模型相关。
PPC 是 Process Per Connection 的缩写,其含义是指每次有新的连接就新建一个进程去专门处理这个连接的请求,这是传统的 UNIX 网络服务器所采用的模型。基本的流程图是:
这种模式的缺点:
PPC 模式中,当连接进来时才 fork 新进程来处理连接请求,由于 fork 进程代价高,用户访问时可能感觉比较慢,prefork 模式的出现就是为了解决这个问题。
顾名思义,prefork 就是提前创建进程(pre-fork)。系统在启动的时候就预先创建好进程,然后才开始接受用户的请求,当有新的连接进来的时候,就可以省去 fork 进程的操作,让用户访问更快、体验更好。prefork 的基本示意图是:
prefork 的实现关键就是多个子进程都 accept 同一个 socket,当有新的连接进入时,操作系统保证只有一个进程能最后 accept 成功。但这里也存在一个小小的问题:“惊群”现象,就是指虽然只有一个子进程能 accept 成功,但所有阻塞在 accept 上的子进程都会被唤醒,这样就导致了不必要的进程调度和上下文切换了。幸运的是,操作系统可以解决这个问题,例如 Linux 2.6 版本后内核已经解决了 accept 惊群问题。
prefork 模式和 PPC 一样,还是存在父子进程通信复杂、支持的并发连接数量有限的问题,因此目前实际应用也不多。Apache 服务器提供了 MPM prefork 模式,推荐在需要可靠性或者与旧软件兼容的站点时采用这种模式,默认情况下最大支持 256 个并发连接。
TPC 是 Thread Per Connection 的缩写,其含义是指每次有新的连接就新建一个线程去专门处理这个连接的请求。与进程相比,线程更轻量级,创建线程的消耗比进程要少得多;同时多线程是共享进程内存空间的,线程通信相比进程通信更简单。因此,TPC 实际上是解决或者弱化了 PPC fork 代价高的问题和父子进程通信复杂的问题。
TPC 的基本流程是:
注意,和 PPC 相比,主进程不用“close”连接了。原因是在于子线程是共享主进程的进程空间的,连接的文件描述符并没有被复制,因此只需要一次 close 即可。
TPC 虽然解决了 fork 代价高和进程通信复杂的问题,但是也引入了新的问题,具体表现在:
除了引入了新的问题,TPC 还是存在 CPU 线程调度和切换代价的问题。因此,TPC 方案本质上和 PPC 方案基本类似,在并发几百连接的场景下,反而更多地是采用 PPC 的方案,因为 PPC 方案不会有死锁的风险,也不会多进程互相影响,稳定性更高。
TPC 模式中,当连接进来时才创建新的线程来处理连接请求,虽然创建线程比创建进程要更加轻量级,但还是有一定的代价,而 prethread 模式就是为了解决这个问题。
和 prefork 类似,prethread 模式会预先创建线程,然后才开始接受用户的请求,当有新的连接进来的时候,就可以省去创建线程的操作,让用户感觉更快、体验更好。
由于多线程之间数据共享和通信比较方便,因此实际上 prethread 的实现方式相比 prefork 要灵活一些,常见的实现方式有下面几种:
Apache 服务器的 MPM worker 模式本质上就是一种 prethread 方案,但稍微做了改进。Apache 服务器会首先创建多个进程,每个进程里面再创建多个线程,这样做主要是为了考虑稳定性,即:即使某个子进程里面的某个线程异常导致整个子进程退出,还会有其他子进程继续提供服务,不会导致整个服务器全部挂掉。
prethread 理论上可以比 prefork 支持更多的并发连接,Apache 服务器 MPM worker 模式默认支持 16 × 25 = 400 个并发处理线程。
I/O 多路复用技术归纳起来有两个关键实现点:
select
、epoll
、kqueue
等。I/O 多路复用结合线程池,完美地解决了 PPC 和 TPC 的问题
Reactor 模式的核心组成部分包括 Reactor 和处理资源池(进程池或线程池),其中 Reactor 负责监听和分配事件,处理资源池负责处理事件。初看 Reactor 的实现是比较简单的,但实际上结合不同的业务场景,Reactor 模式的具体实现方案灵活多变,主要体现在:
最终 Reactor 模式有这三种典型的实现方案:
异步处理不仅可以减少系统服务间的耦合度,提高扩展性,事实上,它还可以提高系统的性能。异步处理可以有效减少响应等待时间,从而提高响应速度。
异步处理一般是通过分布式消息队列的方式。
异步处理可以解决以下问题:
在高并发场景下,使用负载均衡技术为一个应用构建一个由多台服务器组成的服务器集群,将并发访问请求分发到多台服务器上处理,避免单一服务器因负载压力过大而响应缓慢,使用户请求具有更好的响应延迟特性。
高性能集群的复杂性主要体现在需要增加一个任务分配器,以及为任务选择一个合适的任务分配算法。
缓存解决方案请参考:负载均衡
从资源利用的角度看,使用多线程的原因主要有两个:IO 阻塞和多 CPU。
线程数并非越多越好,那么启动多少线程合适呢?
有个参考公式:
启动线程数 = (任务执行时间 / (任务执行时间 - IO 等待时间)) * CPU 内核数
最佳启动线程数和 CPU 内核数成正比,和 IO 阻塞时间成反比。
线程安全问题时指多个线程并发访问某个资源,导致数据混乱。
解决手段有:
应该尽量减少那些开销很大的系统资源的创建和销毁,如数据库连接、网络通信连接、线程、复杂对象等。从编程角度,资源复用主要有两种模式:单例模式和对象池。
根据具体场景,选择合适的数据结构。
如果 Web 应用运行在 JVM 等具有垃圾回收功能的环境中,那么垃圾回收可能会对系统的性能特性产生巨大影响。立即垃圾回收机制有助于程序优化和参数调优,以及编写内存安全的代码。
读写分离的基本原理是将数据库读写操作分散到不同的节点上
详细解决方案参考:读写分离
数据分片指按照某个维度将存放在单一数据库中的数据分散地存放至多个数据库或表中以达到提升性能瓶颈以及可用性的效果。
详细解决方案参考:分库分表
关系型数据库的优势在于:存储结构化数据,有利于进行各种复杂查询。
但是,它也存在一些缺点:
为了解决上述问题,分别诞生了解决不同问题的 Nosql 数据库。
常见的 NoSQL 数据库可以分为四类:
详情参考:Nosql 技术选型
考虑使用固态硬盘替代机械键盘,因为它的读写速度更快。
传统关系数据库的数据库索引一般都使用两级索引的 B+ 树 结构,树的层次最多三层。因此可能需要 5 次磁盘访问才能更新一条记录(三次磁盘访问获得数据索引及行 ID,然后再进行一次数据文件读操作及一次数据文件写操作)。
由于磁盘访问是随机的,传统机械键盘在数据随机访问时性能较差,每次数据访问都需要多次访问磁盘影响数据访问性能。
许多 Nosql 数据库中的索引采用 LSM 树 作为主要数据结构。LSM 树可视为一个 N 阶合并树。数据写操作都在内存中进行。在 LSM 树上进行一次数据更新不需要磁盘访问,速度远快于 B+ 树。
RAID 是 Redundant Array of Independent Disks 的缩写,中文简称为独立冗余磁盘阵列。
RAID 是一种把多块独立的硬盘(物理硬盘)按不同的方式组合起来形成一个硬盘组(逻辑硬盘),从而提供比单个硬盘更高的存储性能和提供数据备份技术。
HDFS(分布式文件系统) 更被大型网站所青睐。它可以配合 MapReduce
并发计算任务框架进行大数据处理,可以在整个集群上并发访问所有磁盘,无需 RAID 支持。
HDFS 对数据存储空间的管理以数据块(Block)为单位,默认为 64 MB。所以,HDFS 更适合存储较大的文件。
Cache-Control
和 Expires
属性,可设定浏览器缓存。CDN 一般缓存的是静态资源。
CDN 的本质仍然是一个缓存,而且将数据缓存在离用户最近的地方,使用户已最快速度获取数据,即所谓网络访问第一跳。
传统代理服务器位于浏览器一侧,代理浏览器将 HTTP 请求发送到互联网上,而反向代理服务器位于网站机房一侧,代理网站服务器接收 HTTP 请求。
反向代理服务器可以配置缓存功能加速 Web 请求,当用户第一次访问静态内容时,静态内容就会被缓存在反向代理服务器上。
反向代理还可以实现负载均衡,通过负载均衡构建的集群可以提高系统总体处理能力。
因为所有请求都必须先经过反向代理服务器,所以可以屏蔽一些攻击 IP,达到保护网站安全的作用。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。