Web 应用程序调优指南

来源:互联网 发布:linux激活网卡命令 编辑:程序博客网 时间:2024/06/09 14:30

 

 

 

一.成功的应用都是相似的,失败的应用各有各的失败

对于Web应用来说,影响性能的集中体现在网络/CPU/内存/IO/数据库/缓存这6个环节的处理上。一个稳定应用的特征应该包括:

1.       网络流量平稳,连接数保持稳定

2.       CPU负载

3.       内存曲线平稳

4.       IO高响应

5.       数据库的低负载,高响应

简单的来说,对于每个不稳定的应用来说,都会有一个瓶颈,通过以上的工具分析,加上自己的判断,找到那个瓶颈,解决它!

我们可以通过以下监控工具可监控到应用的各项指标

1.       网络监控工具 Cacti ,可以监控到整个服务器的流量/硬盘/CPU负载等情况

 

2.       JVM 监控 JConsole (JDK 1.5 以上版本自带), %JAVA_HOME%/bin/jconsole

Java 启动加上一下参数:

-Dcom.sun.management.jmxremote.port=5004 (监控端口)

-Dcom.sun.management.jmxremote.ssl=false

-Dcom.sun.management.jmxremote.authenticate=false

 

3.       Visual VM (JDK 1.6_07 以上版本自带) %JAVA_HOME%/bin/jvisualvm

配置方法同JConsole , Visual VM JConsole 多了一个实用功能Thead Dump.

 

4.       Kill -3 来获取 Thead Dump

TheadDump可以很清晰的告诉你JVM当前正在做什么,内存里有哪些进程,是否有死锁。重点观察RUNNABLE LOCK 是否有死锁。

 

5.       数据库查看

MySql show processlist命令

 

 

二.调优手段和策略

1.       网络层优化

不同类型的应用所能承受的网络负载各不相同,对于长连接应用来说,比如下载应用,所能承受的连接数就相对低,对于短链接应用,比如计数应用,所能承受的连接数就相对高,对于一般有数据库的应用来说,每秒的连接数保持在700以下都是没问题的。

这里调优的方面包括:

1)  Linux可以优化网络的TCP参数,提高网络的响应,

2)  增加服务器实现负载均衡,目的降低单台服务器流量

3)  优化程序,尽可能的减少处理的时间,如果一定有长时间处理的场景,可以采用异步方式处理。先返回一个请求ID,然后客户端再通过这个ID来获得结果。

 

2.       CPU优化

就目前的硬件环境来看,CPU都不会是一个瓶颈。如果CPU出现负载高,基本上都是程序处理不当引起,比如有深度递归或者循环或者频繁写磁盘,一旦出现高负载,会引起一系列的连锁反应,响应降低,连接数增加。

           这个环节主要是优化程序:

1)  减少循环和递归

2)  减少synchronized 的用法。对于多服务器场景,要实现锁机制,用synchronized 不一定适合。Synchronized 使用不当,极容易造成死锁。

3)  减少死锁发生的可能性。JConsole提供了一个检测死锁的方法,TheadDump 也可以分析死锁。

 

 

3.       内存优化

对于Java应用来说,内存调优是关键。先来认识一下Java内存的构成和垃圾回收的机制:

 

 

堆是应用程序使用的主要部分,一旦堆满,应用程序就会抛出Out Of Memory错误。具体关于堆的构成以及垃圾回收算法,可以参考文档:

http://aleung.blogbus.com/logs/4712392.html

这个环节的优化:

1)       增加JVM内存,使得可使用的堆内存尽可能多,延长垃圾回收的时间。需要注意的是,一般来说,回收1G内存所需要的时间是7秒左右,如果这个时间访问量比较高,极容易导致应用停止响应,所以并非是越大内存越好。

      通过增加 XX:+PrintGCDetails  参数可以观察到垃圾回收的频率和时间

2)       调整垃圾回收策略,加快JVM的回收,因为Web应用响应高,很多都是无用内存,加快回收可以保证有效堆会更多,这种方式会消耗更多的CPU

 

4.       IO 优化

为了提高IO的响应,尽可能的不要把所有文件写到同一个目录下,所有的请求集中在一个磁盘上。当一个目录下超过2000个文件,就会导致IO响应下降。

这个环节调优包括

1)       采用更快的IO设备,比如NAS 存储设备

2)       如果可能,将文件缓存到内存,或者先写内存,定时回写磁盘。

3)       将读和写操作分开来实现。比如一个线程只写,一个线程只读。

 

5.       数据库优化

这个环节可以优化的地方比较多,通常由以下几个方面:

1)   建立索引

2)   对于复杂的业务逻辑,采用存储过程实现

3)   对于大数据量,采用归档或者分表方式进行处理。比如 100万的数据要0.1秒就读取出来,如果采用分表,降低的数据规模,实现这个是不难的。

 

6.       缓存

这个的最终目的是为了保证以上各个环节顺畅。

缓存从架构上来分包括

1)  集中式缓存,如Memcached

2)  分布式缓存,如 OpenJPA 的二级缓存,采用JGroup 方式来同步

从类型上来分包括

1)  页面缓存,页面缓存可以定时更新

2)  数据缓存,可以先把数据缓存到内存,然后定时写入数据库。

 

 

三.构架一个稳定应用

 

1.       应用分类

首先要认识到,不同的应用需要的资源和处理的方式是不一样的,所以在开发一个应用之前,要认识到应用的特征及其可能的瓶颈。为每类应用定制一个解决套餐,是成功的基础。

2.       可重用的处理模型

要建立一个可重用的程序库,比如计数框架,缓存框架,模板框架。当你需要的时候,不是重新开发,而是拿过来直接使用就可以了。

3.       持续监控和改进

随着时间的推移,应用所需要的资源也会不同,有些应用可能比预想的差,需要减少资源,有些发展迅猛,需要增加资源。这些都需要我们建立一个可持续的监控机制。

 

 

四.常见不稳定问题处理办法

1.       内存只涨不降

查看一下网络流量,看是否是持续增加,如果网络流量正常,很可能你的程序有内存泄漏问题。

建议的办法:改程序/增加内存或者提高垃圾回收的频率。

 

 

更多有待完善中。。

 

    本指南不是一个教科读书,更多的是经验总结,目的是为了开发高响应/高并发的Web应用,会不断的补充完善,如果需要具体的帮助,可以Google一下。