性能调优案例

  1. 性能分析案例
    1. 程序分析案例
  1. 用jconse做监控,发现内存持续的不释放,波谷或者波峰呈现持续上升的趋势,并且监控tomcat日志的时候发现有outofmemory:java  heap space的错误日志,就用jmap区定位这个问题,找到了在JVM内存堆中占用最大的一个类。然后和开发沟通后,对这个方法进行修改后,再次用jconse进行监控,发现内存增长,回收波动变得比较有规律。
  2. 用JDK自带的jconse做监控,发现JVM线上机器经常出现卡顿现象,JVM在一个小时内会出现一次FULL GC,怀疑是线上JVM老年代,伊甸园区设置不合理,然后看了下配置文件,并把老年代调小,新生代适当的调大。因为一般对象都是在新生代进行频繁的创建。这样设置后尽量让对象在年轻带进行回收,尽量进行YOUNG gc,减少FULL GC次数,调整后,发现FULL GC时间间隔明显增长。对用户的感知影响也变小。
    1. 中间件分析案例

   用lr做300用户的并发,在control里面看到有大量的502,503错误,这时候去查看负载机的网络情况正常,cpu,内存等各项指标均正常,查看数据库连接数也都正常,并且应用服务和数据库服务中均没有错误日志抛出。初步判断这种情况应该是tomcat没有接收到这些并发产生的请求,直接将请求摒弃,所以怀疑是不是进程,线程数设置不合理。于是开始查看tomcat配置文件中的进程,线程数,并尝试将配置文件中的线程数调大,然后再加压时,发现仍有大量的502,203错误,但是比以前稍微少点。那我想是不是进程数太小了,服务器来不及创建进程,就直接把请求摒弃掉了。于是就试着去调初始的进程数,将进程数调大后,再去加压,发现OK,不再出现502,503错误,问题得到解决。

    1. 数据库分析案例

      测试过程中发现数据库服务器的CPU占用经常达到100,于是用show processlist查看mysql的行为。发现大部分的sql都处于睡眠连接状态,严重消耗mysql服务器的资源。并可能导致mysql的崩溃。于是修改了数据库配置文件,将wait_timeout(睡眠连接超时时间,如果连接超时,会被mysql自然终止)值适当的调小(由原来的28800改为600s)。再观察数据库服务器CPU稍微降低到90左右,但是还是会很高。那就再用show processlist 查看mysql行为。发现出现比较频繁的两个sql语句为一个左连接查询,然后再分别查看了下这个sql语句涉及到的三个表的结构,又发现其中有两个表只是建了主键,并没有添加索引,然后分别给这两个表添加索引,并调整了sql语句由左连接改为普通sql查询。再反复的查看数据库的行为,又发现了两个表存在同样的问题,于是都改为走索引,然后再观察数据库服务器CPU,cpu立刻降了下来,一直在50%~70%之间。

    1. 综合分析案例

案例一:动态内容为主的网站。

  • 网站运行环境说明
    • 1台IBMx3850服务器, 单颗双核Xeon 3.0G CPU,2G内存,3块72G SCSI磁盘
    • 操作系统 CentOS 5.4
    • 应用基于LAMP架构,所有服务都在一台服务器上
  • 性能问题现象以及处理措施
    • 表现:早晨和下午访问高峰时,服务器频繁宕机,重启后的一段时间内能正常服务,过一会以后又变的响应缓慢,然后又宕机。
    • 检查:发现宕机前系统负载高,内存基本耗尽,Apache httpd.conf 配置最大用户数为2000,并且开启了KeepAlive
    • 处理:修改 httpd.conf 配置文件,降到最大 1500个用户数,仍然频繁宕机,又降到 1024个用户数,系统不宕机了,但是负载很高,站点访问极慢
  • 初次优化

   既然是系统资源耗尽导致的网站服务失去响应,那么深入分析系统资源使用情况,通过uptime、vmstat、top、ps等命令联合使用 

    • 结论:通过uptime命令查看到系统load average值都是在10以上,CPU资源时常耗尽,这是造成响应缓慢或者长时间没有响应的主要原因,而导致系统资源消耗过道主要是用户进程消耗资源严重。
    • 原因:通过top命令发现apache每个子进程消耗8M内存,正常是1M左右,观察apache日志,发现网站首页访问频率最高,网站首页是个PHP程序,图片很多,每次用户访问都要多次查询数据库,查询数据非常耗CPU,首页代码也没有用缓存机制,导致每个用户都要重新信息数据库查询操作,导致CPU资源耗尽
    • 处理:改写网站首页、减少图片量,对部分频繁访问的程序增加cache机制,减少数据库访问。
  • 第二次优化

    一段时间后,系统又开始不稳定,访问高峰时站点无法正常访问

    • 分析系统资源使用状况,发现这次是系统内存资源消耗过大,并且有I/O问题。
    • 原因:内存消耗过大,肯上是用户访问进程太多导致,上次优化前发现每个apache子进程消耗在8M,如果设置apache最大用户数为1024,内存耗尽是比如的,当物理内存耗尽,虚拟内存就会使用,频繁使用虚拟内存,肯定会造成I/O等待问题
    • 处理:优化代码,使每个apache子进程占用的内存保持在1-2M左右,把Apache配置中的 KeepAlive 特性关闭,把apache最大用户数调成600,这样apache进程数大量减少,基本保持在500个左右,虽然还是会使用交换内存,但是服务正常了。
  • 第三次优化

    一段时间后,系统又开始不稳定,访问高峰时站点无法正常访问

    • 分析发现还是CPU资源耗尽导致的原因。
    • 原因:程序频繁访问数据库,大量的SQL语句中有 where, order by 等子句,且大部分都是复制查询,需要便利全表,而大量的表没有建索引,导致MySQL数据库负荷过高,消耗CPU资源过高。
    • 处理:优化程序中的SQL语句,where和order by子句上的字段建索引,程序增加Cache机制, 
    • 这样服务基本处于正常状态,再也没有出现宕机现象 
  • 网站结构的优化

第3次优化后,网站在程序代码、操作系统、apache等方面优化的空间越来越小,为了避免以后出现服务器宕机问题,可以从网站结构进行优化 

    • 增加了一台专用数据库服务器,使应用于数据库分离
    • 若单台数据库服务器仍然不满足性能要求,可以继续增加一条数据库服务器,将数据库进行读写分离(主库负责写,从库负责读),采用主从同步保证数据的一致性,并且采用冗余切换进行灾备 
    • 如果随着访问量的增加,前端应用无法满足性能要求,可以增加多台web服务器,web服务器之间进行负载均衡部署,解决前端性能瓶颈

案例二:动态,静态内核结合的网站。

  • 该网站系统结构说明
    • 硬件环境:两台IBMx385服务器, 单个双核Xeon 3.0G CPU,4G内存,3块73G SCSI磁盘
    • 操作系统 :CentOS 5.4
    • 网站架构:web应用基于I2EE架构的电子商务应用,web端应用服务器是tomcat,采用mysql数据库,web和数据库独立部署在两台服务器上 
  • 性能问题现象以及处理措施
    • 表现:访问高峰,网页无法打开,重启java服务后,网站可以正常运行一段时间,过一会后又变得响应缓慢,最后无法打开网页
    • 检查:java进程占用99%的CPU,内存占用不大,tomcat为默认配置 
    • 处理:修改 tomcat配置参数,增大最大线程数、超时时间,修改后服务器宕机间隔增长,但是java进行仍然占用大量CPU
  • 初次优化

   通过netstat、lsof命令发现有大量的java请求等待信息,查看tomcat日志,发现大量错误信息,错误信息提示数据库连接超时,同时访问网站静态资源也无法访问 

    • 结论:tomcat本身是一个java容器,主要用于处理jsp、servlet动态应用,当时处理静态资源效率很低。主要原因是tomcat无法及时响应客户端的请求,从而导致请求队列积压,导致tomcat彻底崩溃
    • 原因:通过top命令发现apache每个子进程消耗8M内存,正常是1M左右,观察apache日志,发现网站首页访问频率最高,网站首页是个PHP程序,图片很多,每次用户访问都要多次查询数据库,查询数据非常耗CPU,首页代码也没有用缓存机制,导致每个用户都要重新信息数据库查询操作,导致CPU资源耗尽
    • 处理:引入apache,由apache处理静态资源,tomcat处理动态请求,apache与tomcat之间用Mod_JK模块进行通信,这样大幅度提高tomcat应用性能
  • 第2次优化

   经过前面的优化后,在高并发时候,java进程有时还会出现资源上升无法下降的情况 

    • 处理:进行tomcat负载均衡,前端由apache负载用户请求的调度,后面多个tomcat进行动态的应用解析操作,通过负载均衡,网站性能得到质的提升

案例三:动态内容+cache为主的网站。

  • 该网站系统结构说明
    • 多台Web前端服务器, 配置都为双核Xeon 3.0G CPU,4G内存,3块73G SCSI磁盘
    • 操作系统 CentOS 5.3
    • 多台MySQL数据库服务器
    • 基于PHP开发的应用 
  • 该应用的特点
    • 大量内容基于数据库,需要频繁访问数据库,并且数据更新很快
    • 采用页面cache机制缓解数据库压力,但页面cache只有5分钟有效期,需要频繁生成新的cache
    • Cache以文件形式存在磁盘上,都是小文件,最小不到1k,最大不超过128k
  • 问题描述
    • 访问高峰期时Web前端负载比较高,时常超过10
    • 访问高峰期时Web前端响应很慢
  • 性能分析
    • 负载比较高,时常会超过10,CPU Idel经常会小于30%,有时Idel为0,CPU io wait 很大,经常超过30%,磁盘读每秒不超过100k,磁盘写每秒1.5M左右,磁盘tps超过100
    • 访问高峰期时内存也有部分空闲,用于buffer和cache的内存基本占总内存60%以上,没有使用交换内存
  • 原因分析
    • 分析该应用的特点后发现,访问高峰期时,要频繁生成新的cache文件,或者更新以及过期的cache文件,cache文件目录为256x256的哈希结构,因此读写文件时磁盘随机寻址非常频繁
    • 该应用磁盘写远大于磁盘读的原因是系统cache命中率高,大量文件读过一次就cache住了,因此读的开销很小
    • 写磁盘的量并不算很大,平均每秒1.5M,但都是随机写,因此写磁盘速度会稍微慢,也因此会消耗大量CPU时间
    • 对比访问高峰期和访问量小时候的系统状态,磁盘写的tps提高了1倍以上,CPU io wait提高了3倍以上,因此认为主要性能瓶颈在磁盘写上
  • 优化办法
    • 减少磁盘写的次数,cache文件先写在内存中,超过一定访问次数时才写回磁盘,但由于要修改应用程序,因此执行难度大
    • 减少磁盘随机写的次数,前端不使用255x255的哈希目录,而是把多个cache文件写在一个大的cache文件中,并且只作追加写,这样就能把随机写变成了顺序写,cache过期后,整个大的cache文件可以一次删除。但由于要修改应用,因此执行难度大
    • 上面2个办法结合使用,听上去性能会更好,但是执行难度更大
  • 优化办法
    • 使用tmpfs作cache磁盘(ramdisk也可以),这样写都在访问内存,没有磁盘IO消耗,缺点是cache的空间不会很大,不能超过2G(该服务器是4G内存),但是不用修改应用程序,执行容易:
      • Mount –bind /dev/shm /var/www/cache
      • 写一个清cache的脚本程序,配置在cron中,30分钟执行一次,检查/dev/shm的使用率超过70%时,使用find命令找出太旧的cache文件删除掉

    最终采用了这个办法,高峰期系统负载小于5

你可能感兴趣的:(性能调优)