航母哥

读完需要

2

分钟

速读仅需 1 分钟

目前就职于 58 研发中心担任资深架构师,负责消息中间件与全链路压测的实施与落地。前阿里巴巴消息中间件资深研发,架构师。擅长 Java 编程,对主流中间件 RocketMQ、Dubbo、ElasticJob、Netty、Sentienl、Mybatis、Mycat 等中间件有深入研究。

前几天跟某互联网主题旅游网架构师聊起性能调优的话题,那个时候正好遇到一些线上调优的一些困惑,希望一起探讨一下。

他跟我说,他们公司的系统从来没有经过性能调优,功能测试完成后就上线了,线上也没有出现过什么性能问题呀,为什么要进行调优呢??

可谓底气十足啊!!!无知者无畏啊;就不怕为公司埋雷,到时候追究他的责任?

当时我一脸懵逼,既然不做性能优化就直接上线,相当于给系统埋了一个定时炸弹,一旦到某个临界点,说炸就炸,到时候回天乏力。

因此我就回答了他一句,“我去,如果你们公司做的是淘宝,京东,12306 这样的网站,不做系统性能优化就上线,试试看会是什么情况”。

今天,我们就从这个话题聊起,希望能跟你一起弄明白这几个问题:我们为什么要做性能调优?什么时候开始做?做性能调优是不是有标准可参考?

1

为什么要做性能调优?

在互联网项目开发中,总是不断针对新的需求去研发新的系统,而很多系统的设计都是可以触类旁通的,在系统架构设计中,我们必须遵循一些原则:

海恩法则:

  • 事故的发生是量的积累的结果 (并发量,数据量,服务量…….)

  • 再好的技术、再完美的规章, 在实际操作层面也无法取代人自身的素质和责任心 。

墨菲定律:

  • 任何事情都没有表面看起来那么简单 。

  • 所有事情的发展都会比你预计的时间长 。

  • 会出错的事总会出错。

  • 如果你担心某种情况发生,那么它更有可能发生。

这些原则警示我们,在互联网公司里,对生产环境发生的任何怪异现象和问题 都不要轻易忽视,对于其背后的原因一定要彻查。

同样,海恩法则也强调任何严重事故的背后 都是多次小问题的积累,积累到一定的量级后会导致质变,严重的问题就会浮出水面 。

那么,我们需要对线上服务产生的任何征兆,哪怕是一个小问题,也要刨根问底。

这就需要我们有技术攻关的能力,对任何现象都要秉着以下原则:为什么发生?发生了怎么应对?怎么恢复?怎么避免?对问题要彻查,不能因为问题的现象不明显而忽略 。

一款线上产品如果没有经过性能测试,那它就好比是一颗定时炸弹,你不知道它什么时候会出现问题,你也不清楚它能承受的极限在哪儿。

性能测试的目的在于验证软件系统是否能够达到用户提出的性能指标,同时发现软件系统中存在的性能瓶颈,以优化软件。

有些性能问题是时间累积慢慢产生的,到了一定时间自然就爆炸了;而更多的性能问题是由访问量的波动导致的,例如,活动或者公司产品用户量上升。

当然也有可能是一款产品上线后就半死不活,一直没有大访问量,所以还没有引发这颗定时炸弹。

现在假设你的系统要做一次促销活动,产品经理或者老板告诉你预计有几十万,几百万,甚至更多的用户访问量,询问系统能否承受得住这次活动的压力。

如果你不清楚自己系统的性能情况,也只能战战兢兢地回答老板,有可能大概没问题吧。

所以,要不要做性能调优,这个问题其实很好回答。所有的系统在开发完之后,多多少少都会有性能问题,我们首先要做的就是想办法把问题暴露出来,例如进行压力测试、模拟可能的操作场景等等,再通过性能调优去解决这些问题。

好的系统性能调优不仅仅可以提高系统的性能,还能为公司节省资源,实现降本增效。这也是我们做性能调优的最直接的目的。

2

什么时候开始介入调优?

解决了为什么要做性能优化的问题,那么新的问题就来了:如果需要对系统做一次全面的性能监测和优化,我们从什么时候开始介入性能调优呢?是不是越早介入越好?

其实,在项目开发的初期,我们没有必要过于在意性能优化,这样反而会让我们疲于性能优化,不仅不会给系统性能带来提升,还会影响到开发进度,甚至获得相反的效果,给系统带来新的问题。

我们只需要在代码层面保证有效的编码,同时在架构层面做好设计即可,具体架构设计可以参考如下几条行之有效的法则:

系统的架构设计,如何在架构层面减少不必要的处理(网络请求,数据库操作等),例如:使用 Cache 来减少 IO 次数,使用异步来增加单服务吞吐量,使用无锁数据结构来减少响应时间。

网络拓扑优化减少网络请求时间、如何设计拓扑结构,分布式如何实现?

系统代码级别的代码优化,使用什么设计模式来进行工作?哪些类需要使用单例,哪些需要尽量减少 new 操作?

提高代码层面的运行效率、如何选取合适的数据结构进行数据存取?如何设计合适的算法?

任务执行方式级别的同异步操作,在哪里使用同步,哪里使用异步?

JVM 调优,如何设置 Heap、Stack、Eden 的大小,如何选择 GC 策略,控制 Full GC 的频率?

服务端调优(线程池,等待队列)。

数据库优化减少查询修改时间。数据库的选取?数据库引擎的选取?数据库表结构的设计?数据库索引、触发器等设计?是否使用读写分离?还是需要考虑使用数据仓库?

缓存数据库的使用,如何选择缓存数据库?是 Redis 还是 Memcache? 如何设计缓存机制?

数据通信问题,如何选择通信方式?是使用 TCP 还是 UDP,是使用长连接还是短连接?NIO 还是 BIO?netty、mina 还是原生 socket?

操作系统选取,是使用 winserver 还是 Linux?或者 Unix?

硬件配置?是 8G 内存还是 32G,网卡 10G 还是 1G?例如:增加 CPU 核数如 32 核,升级更好的网卡如万兆,升级更好的硬盘如 SSD,扩充硬盘容量如 2T,扩充系统内存如 128G。

在系统编码完成之后,我们就可以对系统进行性能测试了。这时候,产品经理一般会提供线上预期数据,我们在提供的参考平台上进行压测,通过性能分析、统计工具来统计各项性能指标,看是否在预期范围之内。

在项目成功上线后,我们还需要根据线上的实际情况,依照日志监控以及性能统计日志,来观测系统性能问题,一旦发现问题,就要对日志进行分析并及时修复问题。

在我们进行调优之前,必须对性能指标有一定的认知,否则我们调优就是空中楼阁,没有任何的可参考的依据,是无法实现调优的。

在我们了解性能指标之前,我们先来了解下哪些计算机资源会成为系统的性能瓶颈,这些东西各位应该都非常清楚,在系统上线后,无外乎就是 CPU、内存、磁盘、网络等等这些问题。

CPU:有的应用需要大量计算,他们会长时间、不间断地占用 CPU 资源,导致其他资源无法争夺到 CPU 而响应缓慢,从而带来系统性能问题。

例如,代码递归导致的无限循环,正则表达式引起的回溯,JVM 频繁的 FULL GC,以及多线程编程造成的大量上下文切换等,这些都有可能导致 CPU 资源繁忙。

大量线程抢占 CPU 资源,导致 CPU 占用率升高:

CPU 占用率情况排查:

内存:Java 程序一般通过 JVM 对内存进行分配管理,主要是用 JVM 中的堆内存来存储 Java 创建的对象。

系统堆内存的读写速度非常快,所以基本不存在读写性能瓶颈。但是由于内存成本要比磁盘高,相比磁盘,内存的存储空间又非常有限。

所以当内存空间被占满,对象无法回收时,就会导致内存溢出、内存泄露等问题。

磁盘 I/O:磁盘相比内存来说,存储空间要大很多,但磁盘 I/O 读写的速度要比内存慢,虽然目前引入的 SSD 固态硬盘已经有所优化,但仍然无法与内存的读写速度相提并论。

网络:网络对于系统性能来说,也起着至关重要的作用。如果你购买过云服务,一定经历过,选择网络带宽大小这一环节。

带宽过低的话,对于传输数据比较大,或者是并发量比较大的系统,网络就很容易成为性能瓶颈。

异常:Java 应用中,抛出异常需要构建异常栈,对异常进行捕获和处理,这个过程非常消耗系统性能。

如果在高并发的情况下引发异常,持续地进行异常处理,那么系统的性能就会明显地受到影响。

数据库:大部分系统都会用到数据库,而数据库的操作往往是涉及到磁盘 I/O 的读写。

大量的数据库读写操作,会导致磁盘 I/O 性能瓶颈,进而导致数据库操作的延迟性。

对于有大量数据库读写操作的系统来说,数据库的性能优化是整个系统的核心。

锁竞争:在并发编程中,我们经常会需要多个线程,共享读写操作同一个资源,这个时候为了保持数据的原子性(即保证这个共享资源在一个线程写的时候,不被另一个线程修改),我们就会用到锁。

锁的使用可能会带来上下文切换,从而给系统带来性能开销。JDK1.6 之后,Java 为了降低锁竞争带来的上下文切换,对 JVM 内部锁已经做了多次优化,例如,新增了偏向锁、自旋锁、轻量级锁、锁粗化、锁消除等。

而如何合理地使用锁资源,优化锁资源,就需要你了解更多的操作系统知识、Java 多线程编程基础,积累项目经验,并结合实际场景去处理相关问题。

了解了上面这些基本内容,我们可以得到下面几个指标,来衡量一般系统的性能。

2.1

响应时间

响应时间是衡量系统性能的重要指标之一,响应时间越短,性能越好,一般一个接口的响应时间是在毫秒级。

在系统中,我们可以把响应时间自下而上细分为以下几种:

  • 数据库响应时间:数据库操作所消耗的时间,往往是整个请求链中最耗时的。

  • 服务端响应时间:服务端包括 Nginx 分发的请求所消耗的时间以及服务端程序执行所消耗的时间。

  • 网络响应时间:这是网络传输时,网络硬件需要对传输的请求进行解析等操作所消耗的时间。

  • 客户端响应时间:对于普通的 Web、App 客户端来说,消耗时间是可以忽略不计的,但如果你的客户端嵌入了大量的逻辑处理,消耗的时间就有可能变长,从而成为系统的瓶颈。

2.2

吞吐量

在测试中,我们往往会比较注重系统接口的 TPS(每秒事务处理量),因为 TPS 体现了接口的性能,TPS 越大,性能越好。

在系统中,我们也可以把吞吐量自下而上地分为两种:

  • 磁盘吞吐量

  • 网络吞吐量

我们先来看磁盘吞吐量,磁盘性能有两个关键衡量指标:

  • 一种是 IOPS(Input/Output Per Second),即每秒的输入输出量(或读写次数),这种是指单位时间内系统能处理的 I/O 请求数量,I/O 请求通常为读或写数据操作请求,关注的是随机读写性能。适应于随机读写频繁的应用。

  • 另一种是数据吞吐量,这种是指单位时间内可以成功传输的数据量。对于大量顺序读写频繁的应用,传输大量连续数据。

接下来看网络吞吐量,这个是指网络传输时没有帧丢失的情况下,设备能够接受的最大数据速率。

网络吞吐量不仅仅跟带宽有关系,还跟 CPU 的处理能力、网卡、防火墙、外部接口以及 I/O 等紧密关联。

而吞吐量的大小主要由网卡的处理能力、内部程序算法以及带宽大小决定。

2.3

计算机资源分配使用率

通常由 CPU 占用率、内存使用率、磁盘 I/O、网络 I/O 来表示资源使用率。

这几个参数好比一个木桶,如果其中任何一块木板出现短板,任何一项分配不合理,对整个系统性能的影响都是毁灭性的。

2.4

负载承受能力

当系统压力上升时,你可以观察,系统响应时间的上升曲线是否平缓。这项指标能直观地反馈给你,系统所能承受的负载压力极限。

例如,当你对系统进行压测时,系统的响应时间会随着系统并发数的增加而延长,直到系统无法处理这么多请求,抛出大量错误时,就到了极限。

本文首发于 51CTO 技术栈(blog51cto )编辑:陶家龙,经授权转载发布

- EOF -

想要加入中生代架构群的小伙伴,请添加群合伙人大白的微信

申请备注(姓名+公司+技术方向)才能通过哦!

蚂蚁集团技术专家山丘:性能优化的常见模式及趋势

Java线程池实现原理及其在美团业务中的实践

蚂蚁集团技术专家山丘:性能优化常见压测模型及优缺点

一个思维习惯,让你成为架构师

美团大咖:程序员35岁前应做好的技术积累

阿里云MVP乔帮主:五大类型负载均衡的原理场景详解(文末赠书)

   END
#架构师必备#点分享点点赞点在看

没做性能优化,系统说炸就炸...相关推荐

  1. 职场中接手了老项目,如何做性能优化?

    作为一名程序员,在工作中大概率都会遇到接手老项目的情况. 跳槽从一个坑跳到另一个坑,接手老项目 同事内部活水了,他手上的项目都交接给你 团队"核心"成员要上新项目or重点项目了,团 ...

  2. 一个95分位延迟要求5ms的场景,如何做性能优化

    组内的数据系统在承接一个业务需求时无法满足性能需求,于是针对这个场景做了一些优化,在此写篇文章做记录. 业务场景是这样:调用方一次获取某个用户的几百个特征(可以把特征理解为属性),特征以 redis ...

  3. 大规模 C++ 编译性能优化系统 OMAX 介绍

    导读:本文探索&研究了大规模C/C++服务编译性能优化相关技术,优化服务性能,降低机器成本,同时为了支持规模推广应用,降低业务线接入成本,保障优化效果,进行面向云上微服务,开展平台化优化服务系 ...

  4. 老板让你做性能优化,第一步如何定义指标?

    大厂技术  高级前端  Node进阶 点击上方 程序员成长指北,关注公众号 回复1,加入高级Node交流群 前言 项目的性能决定了用户对项目的整体感观度,优秀的性能可以保证项目的流畅与自然给用户愉快的 ...

  5. 【ELT.ZIP】OpenHarmony啃论文俱乐部——大数据框架性能优化系统

    本文出自ELT.ZIP团队,ELT<=>Elite(精英),.ZIP为压缩格式,ELT.ZIP即压缩精英. 成员: 上海工程技术大学大二在校生 合肥师范学院大二在校生 清华大学大二在校生 ...

  6. 第22.9节 性能篇-使用KdTree来做性能优化

    天下武功,唯快不破 最近网友问了关于点云.倾斜摄影数据的性能优化问题.本来想刀枪剑戟.斧钺勾叉给弄了,但是后来想性能其实是个系统问题,要在第22节分成数小节扎扎实实的讲一讲. 鸣谢 非常感谢王锐王大神 ...

  7. 性能全面超数据库专家,腾讯提基于机器学习的性能优化系统 | SIGMOD 2019

    腾讯与华中科技大学合作的最新研究成果入选了国际数据库顶级会议SIGMOD的收录论文,并将于6月30日在荷兰阿姆斯特丹召开SIGMOD 2019国际会议上公开发表. 入选论文的题目为"An E ...

  8. 微信小程序的底层架构原理,及如何做性能优化

    双线程模型 微信小程序的框架包含两部分 View 视图层.App Service逻辑层.View层用来渲染页面结构,App Service层用来逻辑处理.数据请求.接口调用,它们在两个线程(Webvi ...

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

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

最新文章

  1. 前端质量提升利器-马可代码覆盖率平台
  2. c语言 删除小写字母,c++ - 使用C字符串和指针。 删除除小写字母和空格以外的所有字符 - 堆栈内存溢出...
  3. 数据结构算法的引言+时间复杂度
  4. 混合云应用双活容灾实践
  5. MySQL 数据库热备的操作
  6. oc随笔四:NSString、NSNumber
  7. 本质矩阵 基础矩阵 单应矩阵 (1)
  8. 解决ie浏览器兼容ES6语法问题
  9. 那些只有程序员才能看懂的冷笑话
  10. 动手学深度学习 PyTorch版-Day3
  11. 电子计算机显示屏不亮了,电脑显示屏不亮怎么回事|电脑显示屏不亮如何处理...
  12. df -h 卡死解决方法
  13. 读书笔记:不可能的技艺,巅峰人生需要凶猛的起点
  14. Typora使用方法
  15. SQL语句merge into的用法
  16. 前端元素垂直水平居中的多个方法
  17. 017 | JavaWeb企业进销存管理系统源码附带毕业设计论文 | 大学生毕业设计 | 极致技术工厂
  18. 基于ajax毕业设计题目50例
  19. [HTML5CSS3]20 个酷炫 应用及源码
  20. HUT-XXXX 俄罗斯方块 dfs

热门文章

  1. ipad怎么连接电脑_苹果连接电脑没反应怎么办
  2. 宁夏小学三年级计算机下册教案,宁夏信息技术教案
  3. 计算机考研310分什么水平,知乎工学考研310是什么水平
  4. linux生成固定大小的文件夹的实现
  5. react回调函数_React中的回调中自动绑定ES6类函数
  6. 具体的压栈指令,例子
  7. squid的简单介绍
  8. Qt 自定义界面(实现无边框、可移动)
  9. Z-Stack Home Developer's Guide—4.Using the sample applications as base for new applications 中文翻译
  10. 【搜索引擎】全文索引数据结构和算法