首页 > 代码库 > 网站应用服务器性能优化方案总结

网站应用服务器性能优化方案总结

<style>html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video { margin: 0; padding: 0; border: 0 } body { font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 1.6; color: #333; background-color: #fff; padding: 20px; max-width: 960px; margin: 0 auto } body>*:first-child { margin-top: 0 !important } body>*:last-child { margin-bottom: 0 !important } p,blockquote,ul,ol,dl,table,pre { margin: 15px 0 } h1,h2,h3,h4,h5,h6 { margin: 20px 0 10px; padding: 0; font-weight: bold } h1 tt,h1 code,h2 tt,h2 code,h3 tt,h3 code,h4 tt,h4 code,h5 tt,h5 code,h6 tt,h6 code { font-size: inherit } h1 { font-size: 28px; color: #000 } h2 { font-size: 24px; border-bottom: 1px solid #ccc; color: #000 } h3 { font-size: 18px } h4 { font-size: 16px } h5 { font-size: 14px } h6 { color: #777; font-size: 14px } body>h2:first-child,body>h1:first-child,body>h1:first-child+h2,body>h3:first-child,body>h4:first-child,body>h5:first-child,body>h6:first-child { margin-top: 0; padding-top: 0 } a:first-child h1,a:first-child h2,a:first-child h3,a:first-child h4,a:first-child h5,a:first-child h6 { margin-top: 0; padding-top: 0 } h1+p,h2+p,h3+p,h4+p,h5+p,h6+p { margin-top: 10px } a { color: #4183C4; text-decoration: none } a:hover { text-decoration: underline } ul,ol { padding-left: 30px } ul li>:first-child,ol li>:first-child,ul li ul:first-of-type,ol li ol:first-of-type,ul li ol:first-of-type,ol li ul:first-of-type { margin-top: 0px } ul ul,ul ol,ol ol,ol ul { margin-bottom: 0 } dl { padding: 0 } dl dt { font-size: 14px; font-weight: bold; font-style: italic; padding: 0; margin: 15px 0 5px } dl dt:first-child { padding: 0 } dl dt>:first-child { margin-top: 0px } dl dt>:last-child { margin-bottom: 0px } dl dd { margin: 0 0 15px; padding: 0 15px } dl dd>:first-child { margin-top: 0px } dl dd>:last-child { margin-bottom: 0px } pre,code,tt { font-size: 12px; font-family: Consolas, "Liberation Mono", Courier, monospace } code,tt { margin: 0 0px; padding: 0px 0px; white-space: nowrap; border: 1px solid #eaeaea; background-color: #f8f8f8 } pre>code { margin: 0; padding: 0; white-space: pre; border: none; background: transparent } pre { background-color: #f8f8f8; border: 1px solid #ccc; font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px } pre code,pre tt { background-color: transparent; border: none } kbd { background-color: #DDDDDD; background-image: linear-gradient(#F1F1F1, #DDDDDD); background-repeat: repeat-x; border-color: #DDDDDD #CCCCCC #CCCCCC #DDDDDD; border-style: solid; border-width: 1px; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; line-height: 10px; padding: 1px 4px } blockquote { border-left: 4px solid #DDD; padding: 0 15px; color: #777 } blockquote>:first-child { margin-top: 0px } blockquote>:last-child { margin-bottom: 0px } hr { clear: both; margin: 15px 0; height: 0px; overflow: hidden; border: none; background: transparent; border-bottom: 4px solid #ddd; padding: 0 } table th { font-weight: bold } table th,table td { border: 1px solid #ccc; padding: 6px 13px } table tr { border-top: 1px solid #ccc; background-color: #fff } table tr:nth-child(2n) { background-color: #f8f8f8 } img { max-width: 100% }</style> <style>.highlight { background: #ffffff } .highlight .c { color: #999988; font-style: italic } .highlight .err { color: #a61717; background-color: #e3d2d2 } .highlight .k { font-weight: bold } .highlight .o { font-weight: bold } .highlight .cm { color: #999988; font-style: italic } .highlight .cp { color: #999999; font-weight: bold } .highlight .c1 { color: #999988; font-style: italic } .highlight .cs { color: #999999; font-weight: bold; font-style: italic } .highlight .gd { color: #000000; background-color: #ffdddd } .highlight .gd .x { color: #000000; background-color: #ffaaaa } .highlight .ge { font-style: italic } .highlight .gr { color: #aa0000 } .highlight .gh { color: #999999 } .highlight .gi { color: #000000; background-color: #ddffdd } .highlight .gi .x { color: #000000; background-color: #aaffaa } .highlight .go { color: #888888 } .highlight .gp { color: #555555 } .highlight .gs { font-weight: bold } .highlight .gu { color: #aaaaaa } .highlight .gt { color: #aa0000 } .highlight .kc { font-weight: bold } .highlight .kd { font-weight: bold } .highlight .kp { font-weight: bold } .highlight .kr { font-weight: bold } .highlight .kt { color: #445588; font-weight: bold } .highlight .m { color: #009999 } .highlight .s { color: #d14 } .highlight .na { color: #008080 } .highlight .nb { color: #0086B3 } .highlight .nc { color: #445588; font-weight: bold } .highlight .no { color: #008080 } .highlight .ni { color: #800080 } .highlight .ne { color: #990000; font-weight: bold } .highlight .nf { color: #990000; font-weight: bold } .highlight .nn { color: #555555 } .highlight .nt { color: #000080 } .highlight .nv { color: #008080 } .highlight .ow { font-weight: bold } .highlight .w { color: #bbbbbb } .highlight .mf { color: #009999 } .highlight .mh { color: #009999 } .highlight .mi { color: #009999 } .highlight .mo { color: #009999 } .highlight .sb { color: #d14 } .highlight .sc { color: #d14 } .highlight .sd { color: #d14 } .highlight .s2 { color: #d14 } .highlight .se { color: #d14 } .highlight .sh { color: #d14 } .highlight .si { color: #d14 } .highlight .sx { color: #d14 } .highlight .sr { color: #009926 } .highlight .s1 { color: #d14 } .highlight .ss { color: #990073 } .highlight .bp { color: #999999 } .highlight .vc { color: #008080 } .highlight .vg { color: #008080 } .highlight .vi { color: #008080 } .highlight .il { color: #009999 } .pl-c { color: #969896 } .pl-c1,.pl-mdh,.pl-mm,.pl-mp,.pl-mr,.pl-s1 .pl-v,.pl-s3,.pl-sc,.pl-sv { color: #0086b3 } .pl-e,.pl-en { color: #795da3 } .pl-s1 .pl-s2,.pl-smi,.pl-smp,.pl-stj,.pl-vo,.pl-vpf { color: #333 } .pl-ent { color: #63a35c } .pl-k,.pl-s,.pl-st { color: #a71d5d } .pl-pds,.pl-s1,.pl-s1 .pl-pse .pl-s2,.pl-sr,.pl-sr .pl-cce,.pl-sr .pl-sra,.pl-sr .pl-sre,.pl-src,.pl-v { color: #df5000 } .pl-id { color: #b52a1d } .pl-ii { background-color: #b52a1d; color: #f8f8f8 } .pl-sr .pl-cce { color: #63a35c; font-weight: bold } .pl-ml { color: #693a17 } .pl-mh,.pl-mh .pl-en,.pl-ms { color: #1d3e81; font-weight: bold } .pl-mq { color: #008080 } .pl-mi { color: #333; font-style: italic } .pl-mb { color: #333; font-weight: bold } .pl-md,.pl-mdhf { background-color: #ffecec; color: #bd2c00 } .pl-mdht,.pl-mi1 { background-color: #eaffea; color: #55a532 } .pl-mdr { color: #795da3; font-weight: bold } .pl-mo { color: #1d3e81 } .task-list { padding-left: 10px; margin-bottom: 0 } .task-list li { margin-left: 20px } .task-list-item { list-style-type: none; padding-left: 10px } .task-list-item label { font-weight: 400 } .task-list-item.enabled label { cursor: pointer } .task-list-item+.task-list-item { margin-top: 3px } .task-list-item-checkbox { display: inline-block; margin-left: -20px; margin-right: 3px; vertical-align: 1px }</style>

最近阅读了《大型网站技术架构————核心原理与案例分析》,总结了其中的网站应用服务器性能优化的部分。
应用服务器的性能优化大体上可以从一下四个方向入手:

  1. 使用缓存
  2. 使用异步
  3. 进行服务器集群
  4. 进行代码优化

应用服务器性能优化(一)——缓存


一、使用缓存优化网站性能

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

缓存的本质是一个内存Hash表,网站应用中,数据缓存以一对Key,Value的形式存储在内存Hash表中。缓存主要用来存放那些读写比很高、很少变化的数据。

二八定律:80%的访问落在20%的数据上。

使用缓存需要注意的问题

  1. 把频繁修改的数据放入缓存。容易出现数据写入缓存后,应用还来不及读取缓存,数据就已经失效的情形,徒增系统负担。一般来说,数据的读写比在2:1以上,缓存才有意义。
  2. 没有热点的访问。 缓存使用的内存资源非常宝贵,只能将最新访问的数据缓存起来,而把历史数据清理出缓存。即缓存资源应该留给20%的热点数据。
  3. 数据不一致与脏读。 一般会对缓存设置失效时间,超过失效时间,就要从数据库重新加载。因此应用要忍受一定时间的数据不一致。另一种策略是数据更新时立即更新缓存,不过这也会带来更多的系统开销和事务一致性的问题。
  4. 缓存可用性。 业务发展到一定阶段时,缓存会承担大部分数据访问的压力,数据库已经习惯了有缓存的日子,所以当缓存服务器崩溃时,数据库会因为完全不能承受如此大的压力而宕机,进而导致整个网站不可用。这种情况被称作缓存雪崩,发生这种故障,甚至不能简单地重启缓存服务器和数据库服务器来恢复网站访问。 解决方式:1、缓存热备(当某台服务器宕机时,将缓存访问切换到热备服务器上。);2、缓存服务器集群
  5. 缓存预热。 缓存中存放的是热点数据,热点数据是缓存系统用LRU对不断访问的数据筛选出来的,这个过程需要较长的时间。新启动的缓存系统没有任何数据,此时系统的性能和数据库负载都不太好。因此可以选择在启动缓存是就把热点数据预加载好。
  6. 缓存穿透。 因为不恰当的业务或恶意攻击,持续高并发地访问某一个不存在的数据,如果缓存不保存该数据,就会有大量的请求压力落在数据库上。简单的解决方式是把请求的不存在的数据也放进缓存,其value是null。

二、分布式缓存

分布式缓存架构

分布式缓存有两种架构方式,一种是以JBoss Cache为代表的需要更新同步的分布式缓存,另一种是以Memchached为代表的不互相通信的分布式缓存。

应用服务器性能优化(二)——异步操作


使用消息队列“削峰”

使用消息队列将调用异步化,可改善网站的扩展性和网站的性能。
在不使用消息队列的情况下,用户的请求数据直接写入数据库,在高并发地情况下,会对数据库造成巨大的压力,同时使得响应延迟加剧。
在使用消息队列后,用户请求的数据发送给消息队列后立即返回,再由消息队列的消费者进程(通常情况下,该进程通常独立部署在专门的服务器集群上)从消息队列获取数据,异步写入数据库。

注意使用消息队列,由于数据写入消息队列后立即返回给用户,数据在后续的业务校验写数据库等操作可能失败,因此在使用消息队列进行业务异步处理后,需要适当修改业务流程进行配合。

任何可以晚点做的事,都应该晚点再做。

应用服务器性能优化(三)——集群


  • 使用负载均衡技术为一个应用构建一个由多台服务器组成的服务器集群

应用服务器性能优化(四)——代码优化


一、多线程

由于网站应用程序一般都被web服务器容器管理,用户请求的多线程也通常被web容器管理,但不管是web容器管理的线程还是应用程序自己创建的线程,一台服务器上启动多少线程合适呢?假设服务器上执行的都是相同类型任务,针对该类任务启动的线程数有个简化的估算方式可供参考:

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

最佳启动线程数和cpu内核数量成正比,和io等待时间成正比。

多线程编程需要注意线程安全问题。
编程上解决线程安全的主要手段有以下几点:

  1. 把对象设计为无状态对象。
  2. 使用局部对象。
  3. 并发访问资源时使用锁。

二、 资源复用

资源复用主要有两种模式单例对象池
单例模式的应用:目前web开发中主要使用贫血模式,从Service到Dao都是些无状态对象,无需重复构建,自然而然用单例模式。
对象池:复用对象实例。在实践中,应用程序的数据库连接基本都使用连接池的方式。数据库连接对象创建好以后,将连接对象放入对象池容器中,应用程序要连接的时候,就从对象池中获取一个空闲的连接使用,使用完毕再将该对象归还到对象池中即可,不需要创建新的连接。

三、 数据结构

灵活组合使用各种数据结构。

四、 垃圾回收

JVM分代垃圾回收机制,将应用程序可用的堆空间分为年轻代和年老代,又将年轻代分为Eden区,From区和To区。
如果Old Generation空间用完,就会触发Full GC,就是所谓的全量回收,全量回收会对系统性能产生较大影响,因此应根据系统业务特点和对象生命周期,合理设置Young Generation和Old Generation大小,尽量减少Full GC。


《大型网站技术架构————核心原理与案例分析》是一本非常不错的书籍,对经验不够丰富的程序员来说,是从整体上认识如何去构建起一个大型网站的非常好的科普型书籍,在这里安利一波。

参考文献:《大型网站技术架构————核心原理与案例分析》(李智慧 著)

 

 

 

 

 

 

 

网站应用服务器性能优化方案总结