目录

性能测试

不同视角下的网站性能

性能指标

性能测试

性能测试报告

性能优化策略

前端性能优化

开启缓存

启用压缩

改代码

后端性能优化

分布式缓存

异步操作(消息队列)

使用集群

代码优化

SQL性能优化

存储性能优化

使用SSD替代HDD

B+数 vs LSM树

RAID vs HDFS


大型网站中的一个重要要素,有人说性能就是访问速度的快慢,也是用户的真实体验。用户从输入网站到按下回车键,看到页面的快慢,这就是性能。

性能测试

性能测试是性能优化的前提和基础,也是性能优化结果的检查和度量标准。

不同视角下的网站性能

用户视角:关注网站打开时间

开发视角:关注应用程序的性能,如响应时间、吞吐量、并发处理能力

运维视角:关注基础设施性能和资源利用率,如带宽、服务器硬件配置

性能指标

响应时间:指应用执行一个操作所需的时间,从发出请求到最后得到响应的时间。=> 直观反映系统的快慢

并发数:指系统能够同时处理请求的数量 => 反映系统的负载。

网站用户数 >= 在线用户数 >= 并发用户数

吞吐量:指单位时间内系统处理的请求数量 => 体现系统整体处理能力

每秒请求数、TPS(每秒事务数)、HPS(每秒HTTP请求数)、QPS(每秒查询数)、每秒页面数、每天访问量、每小时处理业务量、

性能计数器:描述服务器或OS性能的数据指标

包括系统负载、对象与线程数、内存使用、CPU使用、网络与磁盘IO等指标

性能测试

性能测试是一个总称,其通过对系统不断添加访问压力,来获得系统性能指标、最大负载能力、最大压力承受能力的过程。具体细分如下四类:

  • 性能测试:初期是性能测试,查看系统性能指标是否符合要求;
  • 负载测试:继续加压,是负载测试,查看系统的负载能力;
  • 压力测试:继续加压,是压力测试,查看系统最大压力承受能力;继续加压,系统就凉凉;
  • 稳定性测试:在特定软硬件、网络环境下,给系统添加一定压力,使其运行一段时间,以检测系统是否稳定

响应时间与并发用户数的关系:

性能测试报告

给出并发数、响应时间、TPS(每秒事务数)、错误率、资源占用情况:

性能优化策略

性能分析(看日志、查监控、看代码、看SQL) =》性能优化(前端、后端、存储)

前端性能优化

先缓存、再压缩、最后改代码

开启缓存

浏览器缓存

利用HTTP协议的Cache-Control(缓存控制策略)和Expires(设置失效时间)头来控制缓存,这样在浏览器缓存后,下次直接从缓存中读取,即可加速访问速度。如下图所示的memory cache和disk cache:

Cache-Control - HTTP | MDN

Expires - HTTP | MDN

CDN加速

CDN(Content Distribute Network,内容分发网络):本质是一个缓存,部署在网络提供商的机房,使用户在请求网站服务时,可以从距离自己最近的网络提供商机房获取数据(指静态资源)。

反向代理缓存

在反向代理服务器缓存用户请求的静态资源:

启用压缩

对html、css、JavaScript启用Gzip压缩,压缩率很高,可以有效减少请求传输时间。

实现方式:

  • Nginx启用GZip压缩
  • 后端应用程序也可以启用压缩,比如pjl-comp-filter
  • SpringBoot 2.0.0+通过参数配置即可:server.compression.enabled

改代码

减少http请求次数

每次HTTP需建立连接才能传输,减少请求次数,即可提高访问性能。

主要手段:

  • 前端合并CSS、JavaScript、图片:就像webpack打包一样,最终只有几个JS、几个CSS、几张图片
  • 后端合并接口:有些接口设计不合理,相关数据可以考虑合并到一个接口中返回

CSS放在页面最上面,JS放在页面最下面

CSS放在最上面,可以快速进行页面渲染(用户更快看到页面显示出来);JS放在页面最下面,防止加载JS阻塞页面。

减少Cookie传输

Cookie会包含在request和reponse中,太大的Cookie会影响数据传输速度。

解决办法:

  • 慎重考虑Cookie中保存的数据,比如有些数据是不是可以存储来localStorage中
  • 避免静态资源请求时发送Cookie

后端性能优化

分布式缓存

网站性能优化第一定律:使用缓存优化性能。

可以考虑各种分布式缓存,比如Redis、Memcached、JBoss Cache等。

异步操作(消息队列)

使用消息队列将调用异步化,不仅可以改善系统性能,还能改善网站的扩展性。

正常流程:发送请求 -> 保存数据到数据库 -> 响应返回

加消息队列的流程:发送请求 -> 进入消息队列 -> 响应返回,另外的进程消费消息队列中的消息

使用集群

使用负载均衡技术为一个应用构建由多态服务器组成的服务器集群,将并发访问请求分发到多台服务器上处理。

按照上图的负载均衡配置(假定为轮询方式),每台服务器只需要处理总并发请求的三分之一就可以了。

代码优化

合理优化业务代码,也可以很好的改善网站性能。

多线程

多用户并发访问是用户的基本需求,目前主要的Web应用服务器(比如Tomcat)都采用多线程的方式响应并发用户请求,因此网站开发天然就是多线程编程。

从资源利用的角度看,使用多线程的原因有两个:

  • IO阻塞:当前线程进行IO处理时,会被阻塞释放CPU以等待IO操作完成,由于IO操作(不管是磁盘IO还是网络IO)通常需要较长时间,这时CPU可以调度其它线程进行处理。这样即可最大程度利用CPU资源。
  • 多CPU:服务器多CPU的情况下,要想最大程度使用CPU,必须启用多线程

Web应用服务器和应用本身都可以创建多线程,那么创建多少线程合适呢?

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

最佳启动线程数和CPU内核数量成正比,和IO阻塞时间成反比。如果任务都是CPU计算型任务,那么线程数最多不超过CPU内核数量,因为启动更多线程,CPU也来不及调度;相反如果任务需要等待磁盘操作或网络响应,那么启动多线程有助于提高任务并发度,提高系统吞吐能力,改善系统性能。

资源复用

系统运行时,要尽量减少那些开销很大的系统资源的创建和销毁,比如线程、数据库连接、网络通信连接、复杂对象等。从编程角度,资源复用主要有俩种模式:

  • 单例模式:像Spring容器中的对象,默认都是单例
  • 对象池(Object Pool):复用对象实例,减少对象的创建和资源消耗。使用的时候从资源池中获取,使用完成后再放回到资源池中。比如线程池、数据库连接池等

数据结构

早期关于程序的定义是这样:程序 = 数据结构 + 算法。数据结构对程序的重要性不言而喻,在不同场景使用合适的数据结构,可以大大改善程序性能。

垃圾回收(JVM)

如果程序运行在JVM中,那么GC会对程序性能产生巨大影响。合理的对JVM参数进行调优,可以提高系统性能。

以JVM为例,其内存分为:

  • 堆(heap):存储对象,对象的创建和释放、垃圾回收都在这里
  • 堆栈(stack):存储线程上下文信息,如方法参数,局部变量等

JVM分代垃圾回收原理:

  1. 堆分成年轻代(Young Generation)和年老代(Old Generation)
  2. Young Generation分成Eden Space、From区和To区
  1. 新建对象总是在Eden Space,当Eden Space空间满后,就触发一次Young GC,并将还被使用的对象复制到From区,这样整个Eden去都是未被使用的空间
  2. 当Eden区再次用完,再次触发Young GC,将Eden Space和From区还在被使用的对象复制到To区,下一次Young GC则是将Eden区和To区还被使用的对象复制到From区【对吗?】
  1. 经过多次Young GC,某些对象会在From区和To区多次复制,如果超过某个阈值对象还没释放,则将该对象复制到Old Generation。
  2. 如果Old Generation空间也以用完,那么就会触发FULL GC,即所谓的全量回收。全量回收会对系统性能产生较大影响。因此需要合理设置年轻代和年老代的大小,以减少FULL GC的次数。

SQL性能优化

有时整个应用响应时间几乎接近于SQL执行时间,所以针对某些执行时间长的SQL,可以考虑作SQL优化。

  • 常规思路:使用EXPLAIN/DESCRIBE查看执行计划,根据执行计划添加索引
  • 索引失效的情况
    • LIKE关键字后面第一个字符就是%,所以一般都是start with方式匹配(以前老外就是这么做的)
    • 组合索引,没有按左子集匹配,按定义顺序来匹配
  • 优化数据结构

    • 数据冗余
    • 分离使用频度很少的字段
    • 创建中间表,直接查中间表,但需要维护中间表
  • 优化插入速度
    • 禁用索引
    • 禁用唯一性校验
  • 优化MySQL参数

参考《MySQL 5.5从零开始学》

存储性能优化

有时候,系统的瓶颈是磁盘读写能力。

使用SSD替代HDD

网站中大部分访问数据是随机的,这种情况下SSD具有更好的性能。

  • HDD:快速顺序读写、慢速随机读写、可能存在磁盘震动、不防摔、价格便宜
  • SSD :快速顺序读写、快速随机读写、磕碰不容易坏、价格稍贵

B+数 vs LSM树

为了改善数据访问性能,文件系统或数据库系统通常会对数据排序后存储,以加快数据检索速度,这就需要保证数据在不断更新、插入、删除后依然有序,传统关系数据库的做法是使用B+数。

B+树是一种专门针对磁盘存储而优化的N叉排序树,以树节点为单位存储在磁盘中,从根节点查询所需数据所在的节点编号和磁盘位置,将其加载到内存中后继续查找,知道找到所需的数据。

目前数据库多采用两级索引的B+树,树的层次最多三层。因此可能需要5次磁盘访问才能更新一条记录(三次磁盘访问获得数据索引及行ID,然后再进行一次数据文件度操作以及一次数据文件写操作)。

但是由于每次磁盘访问是随机的,而传统机械硬盘在随机访问时性能较差,每次数据访问都需要多次访问磁盘从而影响数据访问性能。

目前许多NoSQL产品采用LSM树作为主要数据结构,LSM树可以看作是一个N阶合并树。数据写操作(插入、修改、删除)都在内存中进行,并且都会创建一个新记录(修改会记录新的数据值,而删除会记录一个删除标志),这些数据在内存中仍然还是一颗排序树,当数据超过设定的内存阈值后,会将这颗排序树和磁盘上最新的排序树合并。当这颗排序树的数据量也超过设定阈值后,和磁盘上下一级的排序树合并。合并过程中,会用最新更新的数据覆盖旧的数据(或者记录为不同版本)。

在需要进行读操作,总是先从内存中的排序树开始搜索,如果没有找到再去磁盘中的排序树上顺序查找。在LSM树上进行一次数据更新不需要磁盘访问,在内存即可完成,速度远快于B+树。当数据访问以写操作为主,而读操作集中在最近写入的数据上时,使用LSM树可以极大程度地减少磁盘访问次数,加快访问速度。

RAID vs HDFS

RAID(廉价磁盘冗余阵列)技术主要是为了改善磁盘的访问延迟,增强磁盘的可用性和容错能力。常用RAID技术上有如下几种(假设服务器有N块磁盘,要存储的数据就是Data):

  • RAID0:数据分成N份,每个磁盘存一份,写入速度是原来的N倍,读取也是。但是没做备份,随便哪一个磁盘损坏,那么整体数据损坏。
  • RADI1:数据总是写双份,可靠性极高
  • RAID10:集合RAID0和RAID1,在RAID0基础上总是写双份数据。即提高的速度,又改善了性能,但是磁盘利用率低,有一半都是备份。
  • RAID3:一般情况下,一台服务器不会同时出现损坏两块磁盘的情况,在只损坏其中一块磁盘的情况下, 如果能利用其它磁盘的数据恢复损坏磁盘,这样在保证可靠性和性能的同时,磁盘利用率也得到大幅提升。在数据写入时,把数据分成N-1块,并发写入到N-1块磁盘,并在第N块盘上记录校验数据,任何一块磁盘损坏(包括数据检验盘),都可以利用其它N-1块磁盘的数据恢复。N盘一直使用,可能会经常损坏,实际情况中,很少使用RAID3。
  • RAID5:在RAID3的基础上,校验数据不写入到第N块磁盘,二是螺旋式写入所有磁盘中,这样就比较平均,避免了RAID3中频繁写入第N块盘,从而导致第N块盘损坏的问题。
  • RAID6:在RAID5的基础上,数据只写入N-2块盘,并螺旋式地在两块磁盘中写入校验信息(使用不同算法生成)。这样可以在RAID5基础上提高可靠性,比如两台磁盘都坏了。

各个RAID的比较:

HDFS以块(Block)为单位管理文件内容,一个文件被分割成若干个Block,当应用程序写文件时,没写完一个Block,HDFS就将其自动复制到另外两台机器上,保证每个Block都有三个副本,即使有台服务器宕机,数据依然可以访问,相当于实现了RAID1的数据复制功能。

当对文件进行处理计算时,通过MapReduce并发计算任务框架,可以启动多个计算子任务(MapReduce Task),同时读取文件的多个Block,并发处理,相当于实现了RAID0的并发访问功能。

五、系统架构 - 高性能架构设计及性能优化相关推荐

  1. mysql优化十:从架构角度全局理解mysql性能优化

    从架构角度全局理解mysql性能优化 MySQL性能优化其实是个很大的课题,在优化上存在着一个调优金字塔的说法: 很明显从图上可以看出,越往上走,难度越来越高,收益却是越来越小的.比如硬件和 OS调优 ...

  2. DB2设计与性能优化:原理、方法与实践

    DB2设计与性能优化:原理.方法与实践 王飞鹏  陈辉  张广舟  成孜论  编著 ISBN 978-7-121-13094-6 2011年4月出版 定价:89.80元(含光盘1张) 16开 416 ...

  3. 一、数据库设计与性能优化--概述

    前言 我1998年第一次接触SQL Server 6.5 for Windows NT 4.0,当时的感觉就认为SQL Server只是一个功能强大的Excel文件.现在回想起来,当年抱着这样一种态度 ...

  4. 高性能Mysql之查询性能优化

    高性能Mysql之查询性能优化 为什么查询速度会慢 慢查询基础:优化数据访问 重构查询的方式 MySQL查询优化器的局限性 优化特定类型的查询 即使我们设计了一个最优的库表结构,建好了最好的索引,如果 ...

  5. 资深架构师手把手教你性能优化

    图片来源:pexels.com 孔庆龙,一线架构师,具有多年的金融架构经验,具备 SOA 服务化.服务治理.系统优化.分布式系统项目经验.目前关注于互联网金融技术架构设计.分布式架构.微服务架构.De ...

  6. 云时代架构阅读笔记二——Java性能优化(二)

    承接上文Java性能优化(一)https://www.cnblogs.com/guo-xu/p/11019267.html 4)尽量确定StringBuffer的容量 在说和这个标题相关之前,先说一下 ...

  7. 阿里Java架构师精通资料:性能优化+亿级并发架构汇总+架构选型

    分布式并发架构 微服务.Docker容器的基本原理.架构设计,以及应用场景. 缓存:Redis.Memcached.CDN.本地缓存 搜索引擎的选型:Lucene.Solr等选型与比较 应用服务器雪崩 ...

  8. 并行算法设计与性能优化 刘文志 第2章 现代处理器特性

    程序的最终性能由运行它的处理器实现,只有了解目标处理器的特性,才能写出高效的代码. 现代处理器利用了指令集并行技术,同一时刻存在多条指令同时执行,并且处理器执行的顺序无须和汇编代码给出的指令顺序完全一 ...

  9. 并行算法设计与性能优化 刘文志 第4章 串行代码性能优化

    一方面,串行代码优化有时能获得成千上万倍的加速:另一方面因为单个并行控制流的内部依旧是串行的. 一般而言,不同算法上的优化是最有效的.假设你已经有了一个能得到正确结果的程序,需要在此基础上进行优化,本 ...

最新文章

  1. CZoneSoft出品: 音频视频在线录制系列之 AV留言本 简介
  2. oracle中怎么查看存储过程的源码
  3. Data Structures with C++ Using STL Chapter 3算法概述---笔记
  4. C++中函数指针的运用
  5. php定时爬虫,thinkphp5使用workerman定时器定时爬取站点内容的代码
  6. 使用Spring AOP,自定义注释和反射为您的应用审核基础架构
  7. 双子星IPTV管理系统源码
  8. mro python_Python新式类的方法解析顺序MRO与Super
  9. excel设置默认值_职场办公必备的7个Excel应用技巧解读,易学易懂,收藏备用!...
  10. ORACLE学习之绑定变量
  11. 数据的转换(shp sde mdb 之间的转换)
  12. CompoundButton调用setChecked多次触发onCheckedChanged
  13. Win10怎么去除桌面快捷方式图标左下角的小箭头
  14. php控制梯形图,如何画梯形图? plc梯形图怎么画?如何画plc梯形图
  15. 鲁大师2021年度PC硬件报告:AMD跑分超神,华米OV入局笔记本
  16. [技巧]WIN10笔记本生成电池损耗报表,与笔记本电池损耗恢复方法
  17. 刚刚涉足神经网络,基于TensorFlow2.0以实现鸢尾花分类为例总结神经网络代码实现的几个步骤,附代码详细讲解
  18. 【java】企业微信机器人消息推送
  19. Java版本企业招投标采购管理系统源码 一站式全流程采购招标系统
  20. css写√的图标_CSS - 图标列表的写法

热门文章

  1. 预习:中国计算机设计大赛赛事统计
  2. 为智能家居赋能,雄迈信息发布4G消费类安防模组
  3. python风轮绘制_python 的绘制图形库 turtle
  4. Ubuntu 解决wps缺乏字体
  5. 小学计算机课玩的游戏,小学电脑课上偷偷玩儿过的5款游戏,又一个会引来围观...
  6. pyinstaller 打包项目及使用UPX压缩
  7. HCIP-4.OSPF
  8. 阿里云9月1日安骑士升级故障真相
  9. 系列 | 漫谈数仓第四篇NO.4 『数据应用』(BIOLAP)
  10. GAT学习:PyG实现multi-head GAT(二)