关于性能优化

本贴最后更新于 2740 天前,其中的信息可能已经事过境迁

文章目录:
1.为什么要做性能优化
2.性能优化之前,先定位问题
3.Nginx 和 Tomcat
4.Controller 和 Service 又做了什么
5.Memcache 和 DB 做了什么
6.听说他们久经沙场

一 为什么要做性能优化

“这破网站慢死了。”果冻咬着牙说,“这些程序员都是干嘛吃的 ?”
毛毛看着果冻笑,没说话,毕竟果冻说的破网站是“修真院自己的官网”,毕竟果冻说的这些“干嘛吃的”程序员就在他们 UE 组对面。果冻是一个萌妹子,怎么说都行,毛毛做为一个 PM,可是经常注意培宇桌子下面常备两块板砖的。

培宇有一点点脸红,果冻对培宇是一直有偏见的,毕竟当众表白被拒是谁都难以接受的。自那以后,本着“没有打击培宇的机会,就创造打击培宇的机会”的原则,果冻让培宇生生见识到了什么叫做“由爱生恨两重天”。

旁边的小马哥不干了,当场就“哐“的一下拍桌子,整个二楼的人都吓了一跳,看着小马哥。
果冻也一样吓了一跳,回过神来之后就当场发飚了:”伟江你要死吗?“

伟江本来想说”你行你上啊“,但是看了看果冻渐渐变冷的眼神,终究还是说不出口,可是气氛一度很尬啊,只好小声说了一句:”我去找老大解决去。。。。。。“

所有人:”。。。。。“
培宇笑的不行:”伟江就该这么有霸气,在果冻的淫威下终于爆发了,一怒而起,然后一溜烟的跑去找老大了~“

二 性能优化之前,先定位问题

说到性能之前,先谈量化。

说网站慢,那是普通用户的说的话。
而对程序员来讲,必须是到多少 MS。

多少 MS 才算慢?通常来说,人的眼睛对于 200MS 以上的时延是有反应的,所以一般而言,一整个页面都应该在 200MS 之内完成。
对于复杂的请求,可以再稍微慢一点,毕竟大家还能忍,能忍的程度跟网站的价值成正比。反正我看小黄片的时候是挺能忍的~

简单的用户个人信息这种请求,应该在 50MS 左右,List 的数据,差不多在 100MS 左右。这是比较正常的数据。

以上这些全是暗灭大人骂伟江的原话。

”所以你做为一个程序员,过来跟我说网站慢?你应该直接告诉我说现在哪一个请求慢,慢到多少 MS,应该达到多少 MS。“
暗灭大人一边狠狠的骂了伟江一顿,一边继续在 QQ 上教小师妹学习:“小师妹啊,我听说最近刚上映了一部电影叫做《人民的名义》,我看了看,感觉对于写代码很有帮助啊,强烈推荐给你看,这样,刚好有人买了两张电影票给我,我带你一起去学习一下吧。”

伟江赶紧的拿出手机来,两张票买后,然后截图发给老大。
暗灭大人看到截图,这才满意,跟小师妹又回了句:“稍等啊,我要开个董事会。”

“拿白板来!”老大说。

首先,果冻朝你设了一箭。你接到了果冻射过来的这支爱之箭,看了看箭上附的小纸条,写的是什么内容,按果冻的指示把她想要做的事给做完了,然后把结果又放到小纸条上,再扔回给了果冻,果冻收到箭之后,打开看完。
这是一个完整的 Http 请求过程。

然后老大在白板上这么画了一下。


这表示,对于一个网络请求来说,第一个层面,你需要知道的时间的损耗可以分解成三大部分。

第一部分前端的响应,一般包括解析和渲染,这部分的性能跟前端的代码,前端硬件有关系。
第二部分就是网络延迟,这部分的代码正常来讲是在 8~16MS 左右,是的,Http 请求就是差不多这个性能,如果是 WebSocket 几乎可以做到零延迟,有暗灭大人当年写的多人在线扫雷(http://game.ptteng.com 支持多人在线玩扫雷,一个人点错所有人完蛋的恶趣味)为证。
第三部分就是服务器端的响应,我们说的是网站慢,一般而言,也就是主要在这里,要做性能优化的地方,基本上也是看这里。

伟江听的正津津有味,突然间发现老大已经转身要走了,赶紧拿出手机来又订了一个烛光晚餐。
“老大,老大,我怎么才能知道每一段时间间隔多久呢?在哪可以看得到啊?”

“F12,Fiddle 都行啊,这种叫端到端的响应时间,服务器端的响应时间啊,要看 Nginx 的 Access.log.”老大满意的点了点头:“伟江的学习态度很好嘛,不像培宇,太笨,又不肯用心。”

“Access.log 里会记录服务器端自己的响应时间,这是后端查看性能的重要依据,也是找运维背锅的必备技能。一旦你发现服务器端的响应时间没问题,而端到端的响应有问题,那就百分百的是网络问题了,可以直接找运维同学背锅了。”

“这些是做性能优化之前必须要弄明白的,问题到底出在哪儿呢?否则怎么做性能优化?所以解决性能的问题,跟你泡妹子是一样的,要先脱掉妹子的外套,再脱掉外套里面的上衣,然后。。”

伟江擦了擦口水,说:“老大,如果确实是我们后端的问题呢,前端响应正常,网络传输也正常,就是后端响应出问题,该怎么解决?”

三 .Nginx 和 Tomcat

“为什么要在前端挂一个 Nginx,而不是直接用 Tomcat 呢?”
“你别管,总之好处多多了,不过是域名,还是跨域,还是防 Ddos 攻击,Nginx 都是利器,很好用。现在就照着来。”

Nginx 相当于是一个大的总管,所有的请求都是先到 Nginx 这里来,然后再发给后面的 Tomcat,或者是 Resin 什么的。
后面的 Tomcat 像当于是一个个漂亮女生宿舍的话:

所以 Nginx 就像当于是女生宿舍的门卫

对的。总之 Nginx 很赞,我很喜欢。Nginx 会记录有所有的出入时间。
如果 Nginx 的耗时比较长,一般而言,问题都不太会直接出在 nginx 身上,可以直接再去查 Tomcat/resin/jetty 这些女生宿舍的岗了,哦,不是,去查看这些服务器的日志响应时间了。

所以,Nginx 和 Tomcat 之间的图应该是这样的。

Tomcat 本身也会有一个日志记录,也是 Access.log,其他的叫别的什么日志无所谓了,反正从名字来看,就是进女生宿舍的时间和离开的时间--那群 Tomcat 的研发人员一定是做了很多的实地调研才能有如此神似的命名。

那么锅就继续甩给了 Tomcat。Tomcat 之后是什么呢?基本上就全部是 Java 人员写的代码了。所以我们要不要往女生宿舍里偷偷看一眼?
可是最关键的就是女生宿舍吧,哪能只偷偷看一眼就走!”伟江有点不满意。

四 .Controller 和 Service 又做了什么

说的没错,Tomcat 里的时间其实还可以再分解的更细一些。第一个接受到响应的就是 Controller,而之前说过,Controller 通常是用来控制 Service 的,你可以理解为,每一个 Service 就是一个漂亮妹子。

Controller 就是一个宿舍的宿管员。就是少林足球里的包租婆,她来负责管理这些小妹妹做什么事儿。

Controller 依次调用女生 Service1,女生 Service2,女生 Service3~然后再把结果返回给你。

所以 Tomcat 响应的时间可以分为:
1.Controller 的处理时间
2.Service 的调用时间
3.返回结果的处理时间

controller 本身的处理事情,一般都会是在开始和结束各打一条毫秒数这是所有的业务逻辑处理的总时间。调用各 Service 的时间包含网络传输和 Service 的响应时间。返回结果的时间一般都是解析成 Json 的时间。

生成 Json 的时间通常很短,很短,网络传输的时间说不好,RMI 的话,除第一次建立连接外,几乎可以忽略不计,但是一个 Controller 里调用上百次的话,速度就会慢起来。Http 无疑是最慢的,单纯建立就要花几 MS,对性能有更高要求的话,用 Thrift 和 ProtocolBuffer 等。

而我一般都喜欢用 RMI,不喜欢异构的东西,Http 又引入了额外的负担,所以比较喜欢用 Tuscany 直接调用 RMI。

所以性能优化的重点,就是要弄明白,如果一个大老爷们,比如说培宇,进了女生宿舍之后,总共花了 500 多 MS 的时间,他在包租婆那里花了多长时间?他跑到妹子 1 的床前花了多久?和妹子 1 在一起同几 MS?跑到妹子 2 的床前是多久?在妹子 2 那里花了几 MS?

这些数据都要清清楚楚,还是要用图来表明一下。

这个就是小培宇。如果他爬上每一个妹子的床之后都回来找包租婆登记一下,就是这样的。
如果他爬了一个妹子的床,然后赶紧的去爬了另一个妹子的床,这就是另一个服务调用服务的过程了。

这两种方式的优劣,我们随后再说。

如果他进去之后变成了 8 个小培宇,每个小培宇分别去上 8 个妹子的床,这就是多线程和异步。

如果他自己带了一个小黑板,啪啪啪写上自己的地址,然后就走。8 个妹子看到地址之后各自去找小培宇,这就是消息队列。

总之,先不讨论这么复杂的东西,我们就只说,培宇是一个妹子一个妹子的上。。。。。床。

那么,Controller 那里应该怎么统计时间呢?

一般而言,我们会手写一个 AOP 的 Util。并不会在 Controller 里手写 StartAt 和 EndAt。

这个 Aop 写起来很容易,正常来讲,会在代码里这么写:

如果超过了 50MS,记录日志,入参,时间。
如果不超过 50MS,不记录。

这个 50MS 依据每个人的身体情况,哦不,依据每个应用的情况来自行设置。

所以,到了这里,你就会知道了,我们把果冻射来的爱之箭,已经穿透了包租婆,到了女生宿舍,并且分解到了每一个床位的时间。

这就是一个分析和定位的过程,而通常就是在 Controller 的代码里,一般我们都叫做 WEB 工程,在这里去用 Aop 来记录第一个 Service 的响应时间。

如果我们发现了,培宇在 2 号女生那儿花费的时间特别长呢?

五.Memcache 和 DB 做了什么

“那就把培宇阉了!”伟江斩钉截铁的说。
“好的,现在就动手。” 老大满怀期待的看着他。

这得把培宇喊过来,问问他在 2 号女生那里做什么了。
写到这里我必须得说,这是公开版,公开版只能说,培宇在约 2 号女生看电影。

内部版,非公开发生的,培宇做的事情就比较多了。。

好了,先说看电影。

培宇说:乖,我们去看电影吧。
妹子说:好的,我要找找我的身份证。

这个时间发现身份证不在身边,在老家,于是妹子说,乖,你等着,我去老家把身份证拿过来。
这就叫做直接从 DB 里拿数据。

所以时间性能的损耗,就在于是:培宇和妹子说话,妹子回老家拿身份证。
大概的场景就是这样的。

培宇说:乖,我们看电影去吧。
妹子说:好啊,好啊,等我,我回老家拿身份证,然后一个月过去了。
培宇和妹子想了想,还是没办法看电影。

第二次培宇又说:乖,我们看电影吧。
妹子说;好啊,好啊,等我,我回家拿身份证,然后一个月又过去了。
培宇和妹子再见面之后,想了想,还是没办法看电影。

上一篇讲过 Dao。其实 Service 里对于 Dao 的访问时间分析,也是这么记录的。同理,如果你要用到多个 Dao,可能是先回老家拿身份证,再去商场买件衣服等等等等。

而我们统计妹子去拿身份证的时间,也是同理可以用刚刚说过的 Aop 的性能统计 Util.

这样一个 Service 处理事情的时间,就分成了本地运算和获取数据的时间。
通常本地运算的时间会比较快,而获取数据的时间会比较慢。

如果说你发现了妹子总是回老家,而且时间刚好是一个月,你怎么办?
给妹子提个醒,可不可以把身份证放到旁边的衣柜里?这样我们就可以直接从衣柜里拿身份证了啊。

这个衣柜,就叫做缓存。
而一般而言,我们的包租婆是不管妹子从哪拿身份证的,总之能接待好客人,呃,接待好培宇就行了。

所以如果要继续区分,性能问题。必须要知道,数据有没有走缓存?从缓存中的数据取出来要多久?正常情况下应该几 MS,为什么妹子花了 20 多 MS?是不是柜子前面的人比较多?还是从床到柜子中间的路坏了?柜子是在哪里放着的?

妹子回老家取身份证,会不会堵车?

这些都是需要靠日志来记录时间,也简单提醒一下,假设不是培宇一个人来呢。10000 个人同时来呢?你必须得在日志里记录一些关键信息,确保知道哪个时间是哪个老板,呃,哪个客户的。

六.听说他们久经沙场

其实性能优化有很多很多方案,不同的应用场景,解决方案是不同的。但是最根本的就是要明白,时间倒底损耗在什么地方?
对于果冻来说,就是简单的射了一支爱之箭,后面做了哪些,是不需要知道的。

可是伟江就必须得明白,培宇对每一个女生宿舍的妹子都做了什么。在保安那里花了多久,在包租婆那里花了多久,在每一个女生床上花了多久,妹子从柜子里取身份证要多久,从老家取身份证又要多久。

我们一直说的,一个程序员的真正工作的地方不在笔记本上,也不是在开发环境,也不是在测试环境,而是在线上环境,就是这个道理。
做为一个老程序员来说,对于线上有哪几台服务器,IP 是多少,内存是多大,硬盘是多大,CPU 是几核的,常用负载是多少,IO 有多少,每天增长的日志是多少,DB 里的数据库大小是多大,每天的增量是多少,系统中最慢的请求是什么,每天会访问多少次,最快的请求是什么,每天应该访问多少次,每次访问的时候正常应该是在多少 MS 内返回,一次会取多少条数据,分解到哪几个 Service,每个 Service 的不同时间请求是多少,有多少穿透 DB 的次数。

所有的这些数据都要了如指掌,这样才能够非常快的定位线上的问题。

我们不能说这样的程序员是一个水平多厉害的高手,但是他如果做到了这么一点,他就是一个久经沙场的老兵,这样才像是一个职业的工程师。

所以这篇文章的重点就在于是,简单的讲解一下时间之箭的运转,中间会有哪些环节,每个环节应该耗费多长时间。
简单说,只有先找到妹子,才会知道应该在妹子身上花多少时间,对吧?

** 技能树.IT 修真院 http://www.jnshu.com**

“我们相信人人都可以成为一个工程师,现在开始,找个师兄,带你入门,掌控自己的学习节奏,学习的路上不再迷茫”。

** 这里是技能树.IT 修真院,成千上万的师兄在这里找到了自己的学习路线,学习透明化,成长可见化,师兄 1 对 1 免费指导。**

  • 程序员

    程序员是从事程序开发、程序维护的专业人员。

    574 引用 • 3533 回帖
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3190 引用 • 8214 回帖 • 1 关注
  • 培宇
    1 引用 • 1 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • Linux

    Linux 是一套免费使用和自由传播的类 Unix 操作系统,是一个基于 POSIX 和 Unix 的多用户、多任务、支持多线程和多 CPU 的操作系统。它能运行主要的 Unix 工具软件、应用程序和网络协议,并支持 32 位和 64 位硬件。Linux 继承了 Unix 以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。

    946 引用 • 943 回帖
  • Oracle

    Oracle(甲骨文)公司,全称甲骨文股份有限公司(甲骨文软件系统有限公司),是全球最大的企业级软件公司,总部位于美国加利福尼亚州的红木滩。1989 年正式进入中国市场。2013 年,甲骨文已超越 IBM,成为继 Microsoft 后全球第二大软件公司。

    105 引用 • 127 回帖 • 370 关注
  • 链书

    链书(Chainbook)是 B3log 开源社区提供的区块链纸质书交易平台,通过 B3T 实现共享激励与价值链。可将你的闲置书籍上架到链书,我们共同构建这个全新的交易平台,让闲置书籍继续发挥它的价值。

    链书社

    链书目前已经下线,也许以后还有计划重制上线。

    14 引用 • 257 回帖
  • IBM

    IBM(国际商业机器公司)或万国商业机器公司,简称 IBM(International Business Machines Corporation),总公司在纽约州阿蒙克市。1911 年托马斯·沃森创立于美国,是全球最大的信息技术和业务解决方案公司,拥有全球雇员 30 多万人,业务遍及 160 多个国家和地区。

    17 引用 • 53 回帖 • 139 关注
  • gRpc
    11 引用 • 9 回帖 • 69 关注
  • C++

    C++ 是在 C 语言的基础上开发的一种通用编程语言,应用广泛。C++ 支持多种编程范式,面向对象编程、泛型编程和过程化编程。

    107 引用 • 153 回帖
  • BAE

    百度应用引擎(Baidu App Engine)提供了 PHP、Java、Python 的执行环境,以及云存储、消息服务、云数据库等全面的云服务。它可以让开发者实现自动地部署和管理应用,并且提供动态扩容和负载均衡的运行环境,让开发者不用考虑高成本的运维工作,只需专注于业务逻辑,大大降低了开发者学习和迁移的成本。

    19 引用 • 75 回帖 • 653 关注
  • 生活

    生活是指人类生存过程中的各项活动的总和,范畴较广,一般指为幸福的意义而存在。生活实际上是对人生的一种诠释。生活包括人类在社会中与自己息息相关的日常活动和心理影射。

    230 引用 • 1454 回帖
  • Ruby

    Ruby 是一种开源的面向对象程序设计的服务器端脚本语言,在 20 世纪 90 年代中期由日本的松本行弘(まつもとゆきひろ/Yukihiro Matsumoto)设计并开发。在 Ruby 社区,松本也被称为马茨(Matz)。

    7 引用 • 31 回帖 • 216 关注
  • Markdown

    Markdown 是一种轻量级标记语言,用户可使用纯文本编辑器来排版文档,最终通过 Markdown 引擎将文档转换为所需格式(比如 HTML、PDF 等)。

    167 引用 • 1520 回帖
  • Flume

    Flume 是一套分布式的、可靠的,可用于有效地收集、聚合和搬运大量日志数据的服务架构。

    9 引用 • 6 回帖 • 637 关注
  • 资讯

    资讯是用户因为及时地获得它并利用它而能够在相对短的时间内给自己带来价值的信息,资讯有时效性和地域性。

    55 引用 • 85 回帖
  • 面试

    面试造航母,上班拧螺丝。多面试,少加班。

    325 引用 • 1395 回帖
  • 微服务

    微服务架构是一种架构模式,它提倡将单一应用划分成一组小的服务。服务之间互相协调,互相配合,为用户提供最终价值。每个服务运行在独立的进程中。服务于服务之间才用轻量级的通信机制互相沟通。每个服务都围绕着具体业务构建,能够被独立的部署。

    96 引用 • 155 回帖
  • 设计模式

    设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

    200 引用 • 120 回帖
  • ActiveMQ

    ActiveMQ 是 Apache 旗下的一款开源消息总线系统,它完整实现了 JMS 规范,是一个企业级的消息中间件。

    19 引用 • 13 回帖 • 668 关注
  • WebComponents

    Web Components 是 W3C 定义的标准,它给了前端开发者扩展浏览器标签的能力,可以方便地定制可复用组件,更好的进行模块化开发,解放了前端开发者的生产力。

    1 引用 • 3 关注
  • PWA

    PWA(Progressive Web App)是 Google 在 2015 年提出、2016 年 6 月开始推广的项目。它结合了一系列现代 Web 技术,在网页应用中实现和原生应用相近的用户体验。

    14 引用 • 69 回帖 • 159 关注
  • DevOps

    DevOps(Development 和 Operations 的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。

    51 引用 • 25 回帖
  • iOS

    iOS 是由苹果公司开发的移动操作系统,最早于 2007 年 1 月 9 日的 Macworld 大会上公布这个系统,最初是设计给 iPhone 使用的,后来陆续套用到 iPod touch、iPad 以及 Apple TV 等产品上。iOS 与苹果的 Mac OS X 操作系统一样,属于类 Unix 的商业操作系统。

    85 引用 • 139 回帖
  • 开源

    Open Source, Open Mind, Open Sight, Open Future!

    407 引用 • 3578 回帖
  • WordPress

    WordPress 是一个使用 PHP 语言开发的博客平台,用户可以在支持 PHP 和 MySQL 数据库的服务器上架设自己的博客。也可以把 WordPress 当作一个内容管理系统(CMS)来使用。WordPress 是一个免费的开源项目,在 GNU 通用公共许可证(GPLv2)下授权发布。

    66 引用 • 114 回帖 • 223 关注
  • 机器学习

    机器学习(Machine Learning)是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能。

    83 引用 • 37 回帖
  • PWL

    组织简介

    用爱发电 (Programming With Love) 是一个以开源精神为核心的民间开源爱好者技术组织,“用爱发电”象征开源与贡献精神,加入组织,代表你将遵守组织的“个人开源爱好者”的各项条款。申请加入:用爱发电组织邀请帖
    用爱发电组织官网:https://programmingwithlove.stackoverflow.wiki/

    用爱发电组织的核心驱动力:

    • 遵守开源守则,体现开源&贡献精神:以分享为目的,拒绝非法牟利。
    • 自我保护:使用适当的 License 保护自己的原创作品。
    • 尊重他人:不以各种理由、各种漏洞进行未经允许的抄袭、散播、洩露;以礼相待,尊重所有对社区做出贡献的开发者;通过他人的分享习得知识,要留下足迹,表示感谢。
    • 热爱编程、热爱学习:加入组织,热爱编程是首当其要的。我们欢迎热爱讨论、分享、提问的朋友,也同样欢迎默默成就的朋友。
    • 倾听:正确并恳切对待、处理问题与建议,及时修复开源项目的 Bug ,及时与反馈者沟通。不抬杠、不无视、不辱骂。
    • 平视:不诋毁、轻视、嘲讽其他开发者,主动提出建议、施以帮助,以和谐为本。只要他人肯努力,你也可能会被昔日小看的人所超越,所以请保持谦虚。
    • 乐观且活跃:你的努力决定了你的高度。不要放弃,多年后回头俯瞰,才会发现自己已经成就往日所仰望的水平。积极地将项目开源,帮助他人学习、改进,自己也会获得相应的提升、成就与成就感。
    1 引用 • 487 回帖 • 2 关注
  • HBase

    HBase 是一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的 Google 论文 “Bigtable:一个结构化数据的分布式存储系统”。就像 Bigtable 利用了 Google 文件系统所提供的分布式数据存储一样,HBase 在 Hadoop 之上提供了类似于 Bigtable 的能力。

    17 引用 • 6 回帖 • 75 关注
  • jsDelivr

    jsDelivr 是一个开源的 CDN 服务,可为 npm 包、GitHub 仓库提供免费、快速并且可靠的全球 CDN 加速服务。

    5 引用 • 31 回帖 • 72 关注
  • Swagger

    Swagger 是一款非常流行的 API 开发工具,它遵循 OpenAPI Specification(这是一种通用的、和编程语言无关的 API 描述规范)。Swagger 贯穿整个 API 生命周期,如 API 的设计、编写文档、测试和部署。

    26 引用 • 35 回帖 • 5 关注