转载 分布式Java应用(二) 性能调优

caifengguo 2011-11-11

转载分布式Java应用(二)性能调优

2010年08月17日星期二19:50

From:http://hi.baidu.com/ygdu/blog/item/6817728dd318c11fb31bbaf6.html

性能调优

性能调优的第一步是寻找性能瓶颈,寻找瓶颈的方法是首先分析资源消耗,然后结合一些工具查找程序中资源消耗过多的代码。

CPU消耗分析

cpu的三个概念:上下文切换(不要过于频繁)、运行队列(每个核1-3个最好)、利用率

cpu状况的查看方式:

Top

pidstat,需安装sysstat

Jstack-l/[pid]|gerp'nid=0x4249',可根据pid列出子线程信息

vtune,商业软件,可查看整个线程内部执行的动作

文件IO消耗分析

Pidstat-d-t-p[pid],可查看线程的io消耗状况,kb_rd/s表示每秒读取kb数,kb_wr/s就是写了

Iostat,首先关注cpu中的iowait%,如果这是主要问题,再通过iostat-x查看具体情况

网络IO消耗分析

sar-nFULL12输出网络IO消耗信息

内存消耗分析

Jmap,jstat,mat,visualvm

Vmstat

Sar-r

Top

Pidstat-r-p[pid][interval][times]

程序执行慢的原因分析

如果资源消耗不多,程序仍然慢,一般原因分为三种:

锁竞争激烈

未充分使用硬件资源

数据量增长

调优

调优通常可从硬件、操作系统、JVM和程序四个方面入手

JVM调优

主要表现在降低GC所导致的应用暂停时间。不过如果不是有确切的理由证明是GC问题,不需要倾注太多的心思在GC调优上,JVM做得已经够好了。

程序调优

Cpuus高:一般是因为有线程不停地执行,cpu无机会调用其他线程,造成线程饿死,可在线程中增加Thread.sleep(1),如果这个线程需要等待其他线程改变了值后才能继续,则使用wait/notify。

Cpusy高:主要是因为线程运行状态经常要切换,最简单的优化办法是减少线程数。如果应用要支撑大量的并发,在减少线程数的情况下最好是增加一个缓冲队列,避免因为线程数的减少而造成的出错率上升。还有另外一种利用较少线程支撑较高并发量的方式:协程(coroutine)。目前Java有Kilim框架、JDK7、Scala的Actor可以支持协程。

文件IO消耗严重:主要是多个线程将大量数据写到同一文件,线程之间争夺文件锁,会造成系统写入速度很慢,有几种解决办法:

异步写文件,如Log4j提供的AsyncAppender

批量读写

限流

限制文件大小

网络IO消耗严重:限流——限制发送packet的频率

内存消耗严重:

找到内存消耗严重的代码,对代码本身进行优化

释放不必要的引用

使用对象缓存池

采用合理的缓存失效算法

合理使用WeakReference和SoftReference

资源消耗不多,但是程序执行慢:

锁竞争激烈:

使用并发包里的类

使用Treiber算法,实现无阻塞的Stack

用Michael-Scott、MCAS、WSTM等非阻塞队列算法

尽可能少用锁,将锁最小化

拆分锁,可以提高读写速度,但是全局性质的操作会变得比较麻烦,如ConcurrentHashMap

去掉读写操作的互斥锁

未充分使用硬件资源:

未充分使用cpu:

单线程的计算可改为多线程,最后再合并结果,jdk7中的fork-join可提供支持

未充分使用内存:

使用数据的缓存、耗时资源的缓存、页面片段的缓存等

构建高可用的系统

避免系统中出现单点

负载均衡技术:

分类:硬件/软件的负载均衡、去中心化负载均衡(谣言传播的方式)

均衡策略:随机选、Hash选、Round-Robin选、按权重选、按负载选、按连接选

响应返回方式:通过负载均衡机返回(基于NAT实现),

构建可伸缩的系统

垂直伸缩:增加单台机器的性能

水平伸缩:增加机器数量来提升总体性能

支撑大数据量:

分表,按主键ID,按时间等,根据业务而定,分表通常会带来开发的复杂,可以借助DAL解决,另外会带来分页查询、跨表查询的难题

缓存状态的水平伸缩方法:

广播同步,基于Multicast实现,JGroups提供支持,jetty,tomcat的session信息同步都用了它。广播不会给机器带来过多负担,不过可能会有一定延时

分布式缓存

文件的水平伸缩方法:

直连式存储

网络存储(Fabric-AttachedStorage),有NAS(通过网络协议),SAN(通过mount)两种方式

分布式文件系统,GFS,HDFS(基于GFS实现)

应用的水平伸缩方法:

按照业务领域拆分应用

水平伸缩带来的数据库问题解决方案:

缓存,页面静态化,页面片段缓存,数据缓存(适用于变化不大的数据)

分库,按业务领域拆分到不同的数据库服务器

异步数据库访问,减少连接数占用

DAL,开源的有Amoeba框架,可以透明化分库、分表对业务服务器的影响

支撑大数据量:

读写分离(master-slave库)

多master

提升计算能力

MapReduce,MPI,将任务拆解到多台机器执行

相关推荐