适用读者:3年如下的后端开发者前端
文章目录: 1.为何要作性能优化 2.性能优化以前,先定位问题 3.Nginx和Tomcat 4.Controller和Service又作了什么 5.Memcache和DB作了什么 6.据说他们久经沙场nginx
一 为何要作性能优化程序员
“这破网站慢死了。”果冻咬着牙说,“这些程序员都是干吗吃的 ?” 毛毛看着果冻笑,没说话,毕竟果冻说的破网站是“修真院本身的官网”,毕竟果冻说的这些“干吗吃的”程序员就在他们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的次数。
全部的这些数据都要了如指掌,这样才可以很是快的定位线上的问题。
咱们不能说这样的程序员是一个水平多厉害的高手,可是他若是作到了这么一点,他就是一个久经沙场的老兵,这样才像是一个职业的工程师。
因此这篇文章的重点就在因而,简单的讲解一下时间之箭的运转,中间会有哪些环节,每一个环节应该耗费多长时间。 简单说,只有先找到妹子,才会知道应该在妹子身上花多少时间,对吧?