解决java负载平衡问题

上传人:第*** 文档编号:33537197 上传时间:2018-02-15 格式:DOC 页数:12 大小:207KB
返回 下载 相关 举报
解决java负载平衡问题_第1页
第1页 / 共12页
解决java负载平衡问题_第2页
第2页 / 共12页
解决java负载平衡问题_第3页
第3页 / 共12页
解决java负载平衡问题_第4页
第4页 / 共12页
解决java负载平衡问题_第5页
第5页 / 共12页
点击查看更多>>
资源描述

《解决java负载平衡问题》由会员分享,可在线阅读,更多相关《解决java负载平衡问题(12页珍藏版)》请在金锄头文库上搜索。

1、解决 JAVA 服务器性能问题研究分析说明改善 JAVA 服务器的性能需要模拟负载下的服务器。创建一个模拟环境、搜集数据并且分析结果可能是对许多开发人员的挑战。这篇文章中的示例介绍了 JAVA 服务器性能分析的概念和工具。作者使用这个示例来研究超额请求次数下内存使用和同步竟争的影响。作者 Ivan Small项目团队已经很熟悉如何组织一些具体的任务并完成他们。简单的性能问题很容易由一个开发人员分离并解决。然而大的性能问题,通常在系统处于高负载情况下发生,就不是这么简单能处理的了。这些问题需要一个独立的测试环境、一个模拟的负载,并且需要仔细地分析和跟踪。在这篇文章中,我使用比较通用的工具和设备创

2、建了一个测试环境。我会专注于两个性能问题,内存和同步,他们很难用简单的分析得到。通过一个具体的例子,我希望比较容易地解决复杂的性能问题而且可以提供处理问题过程中的细节。改善服务器的性能服务器的性能改善是依赖于数据的。没有可靠的数据基础而更改应用或环境会导致更差的结果。分析器提供有用的 JAVA 服务器应用信息,但由于从单用户负载下的数据与多用户负载下得到的数据是完全不同的,这导致分析器的数据并不精确。在开发阶段使用分析器来优化应用的性能是一个好的方式,但在高负载下的应用分析可以取到更好的效果。在负载下分析服务器应用的性能需要一些基本的元素:1、可控的进行应用负载测试的环境。2、可控的人造负载使

3、得应用满负荷运行。3、来自监视器、应用和负载测试工具自身的数据搜集。4、性能改变的跟踪。不要低估最后一个需求(性能跟踪)的重要性因为如果不能跟踪性能你就不能实际的管理项目。性能上 10-20%的改善对单用户环境来说并没有什么不同,但对支持人员来说就不一样了。20%的改善是非常大的,而且通过跟踪性能的改善,你可以提供重要的反馈和持续跟踪。虽然性能跟踪很重要,但有时为了使后续的测试更加精确而不得不抛弃先前的测试结果。在性能测试中,改善负载测试的精确性可能需要修改模拟环境,而这些变化是必须的,通过变化前后的负载测试你可以观察到其中的转变。可控的环境 可控的环境最少也需要两立的机器和第三台控制的机器。

4、其中一台用来生成负载,另一台作为控制机与前一台建立测试应用并接受反馈,第三台机器运行应用。此外,负载和应用机器间的网络应该与局域网分开。控制机接受运行应用机器的反馈如操作系统、硬件使用率、应用(特别是 VM)的状态。负载模拟最精确的模拟通常用实际的用户数据和 WEB 服务器端的访问日志。如果你还没有实际布署或者缺少实际的用户数据,你可以通过构造类似的场景或询问销售和产品管理团队或做一些有依据的猜想。协调负载测试和实际用户体验是一个持续的过程。在模拟中一些用户场景是必须的。如在一个通用地址薄应用中,你应该区分更新和查询操作。在我的测试应用中 GrinderServlet 类只有一个场景。单用户连

5、接 10 次访问这个servlet(在每一次访问间有一段暂停) 。虽然这个应用很小,我认为这可以重复一些常见的东西。用户通常不会连接给服务器请求而没有间断。如果没有间断,我们可能不能得到更精确的实际用户上限。串行 10 个请求的另一个原因是实际应用中不会只有一个 HTTP 请求。单一而又分离的请求可以影响环境中的许多因素。对 Tomcat 来说,会为每一个请求创建一个会话,并且HTTP 协议允许不同的请求重用连接。我会修改一下负载测试来避免混洧。GrinderServlet 类不会执行任何排序操作,但这个需求在大部分应用中都很普通。在这些应用中,你需要创建模拟的数据集并且用他们来构造相关用例的

6、负载测试。例如,如果用例涉及到用户登录一个 WEB 应用,从可能的用户列表中选取随机的用户会只使用一个用户更精确。否则,你可能不经意地使用了系统缓存或其他的优化或一些微妙的东西,而这会使得结果不正确。负载测试软件负载测试软件可以构造测试场景并且对服务进行负载测试。我会在下面的示例中使用OpenSTA 测试软件。这软件简单易学,结果也很容易导出,并且支持参数化脚本,还可以监视信息的变化,他的主要缺点是基于 Windows,但在这儿不是个问题。当然还有很多可选项如 Apache 的 JMeter 和 Mercury 的 LoadRunner。The GrinderServlet列表 1 中显示了

7、GrinderServlet 类,列表 2 中显示了 Grinder 类Listing 1package pub.capart;import java.io.*;import java.util.*;import javax.servlet.*;import javax.servlet.http.*;public class GrindServlet extends HttpServlet protected void doGet(HttpServletRequest req, HttpServletResponse res)throws ServletException, IOExcepti

8、on Grinderv1 grinder = Grinderv1.getGrinder();long t1 = System.currentTimeMillis();grinder.grindCPU(13);long t2 = System.currentTimeMillis();PrintWriter pw = res.getWriter();pw.print(n n);pw.print(Grind Time = +(t2-t1);pw.print( n n);Listing 2package pub.capart;/* This is a simple class designed to

9、simulate an application consuming* CPU, memory, and contending for a synchronization lock.*/public class Grinderv1 private static Grinderv1 singleton = new Grinderv1();private static final String randstr =this is just a random string that Im going to add up many many times;public static Grinderv1 ge

10、tGrinder() return singleton;public synchronized void grindCPU(int level) StringBuffer sb = new StringBuffer();String s = randstr;for (int i=0;ilevel;+i) sb.append(s);s = getReverse(sb.toString();public String getReverse(String s) StringBuffer sb = new StringBuffer(s);sb = sb.reverse();return sb.toSt

11、ring(); 类很简单,但他们会产生两个很常见的问题。咋一看瓶颈可能由 grindCPU()方法的同步修饰符引起,但实际上内存消耗才是真正的问题所在。如图 1,我的第一个负载测试显示了常见的负载变化。在这里负载变化很重要因为你正在模拟一个高的负载。这种热身的方式也更精确因为避免了 JSP 编译引起的问题。我通常习惯于在进行负载测试前先进行单用户模拟。Figure 1 我在这篇文章中会使用相同的容量小结图。在执行负载测试时还有更多的可用信息,但这里只用了有用的部分。最上面的面板包含每秒完成的请求数和请求时间信息。第二个面板包含活动用户数和失败率,我将超时、不正确的服务器应答和长于 5 秒的请求

12、认为是失败的。第三个面板包含 JVM 内存统计和 CPU 使用率。CPU 值是所有处理器的用户时间的平均值,这里所有的测试机器都是双 CPU 的。内存统计图包含垃圾回收表和每秒垃圾回收数。图 1 中两个最明显的数据是 50%的 CPU 使用率和大量内存使用和释放。从列表 2 中可以看出这个原因。同步修饰符导致所有进程串行处理,就好像只用了一个 CPU,而算法导致大量内存消耗在局部变量上。 通过 CPU 是个受限的资源,如果在这个测试中我可以完全利用到两个 CPU 的话就可以提高一倍的性能。垃圾回收器运行得如此频繁以致于不能忽略。在测试中每秒释放的内存达到 100M,很显然这是个限制因素。失败数

13、这么大明显这个应用是不可用的。监视在生成合理的用户负载后,监视工具需要收集进程的运行状况。在我的测试环境中可以收集到各种有用的信息:1、 所有计算机、网络设备2、 等等的使用率3、 JVM 的统计数据。4、 个别 JAVA 方法所花费的时间。5、 数据库性能信息,6、 包括 SQL 查询的统计。7、 其他应用相关的信息当然这些监视也会影响负载测试,但如果影响比较小也可以忽略。基本上如果我们想获取所有上面的信息,肯定会影响测试的性能。但如果不是一次获取所有信息还是有可能保证负载测试的有效性。仅对特定的方法设置定时器,仅获取低负载的硬件信息和低频率地获取样例数据。当然不加载监视器来做测试是最好的,

14、然后和加载监视器的测试来做比较。虽然有时候侵入式监视是个好主意,但就不可能有监视结果了。获取所有监视数据到一个中央控制器来做分析是最好的,但使用动态运行时工具也可以提供有用的信息。例如,命令行工具如 PS、TOP、VMSTAT 可以提供 UNIX 机器的信息;性能监视器工具可以提供 WINDOWS 机器的信息;而 TeamQuest, BMC Patrol, SGIs Performance Co-Pilot, and ISMs PerfMan 这样的工具会在所有的测试环境中的机器安装代理并且将需要的信息传回中央控制机,这样就可以提供文本或可视化的信息。在本文中,我使用开源的 Performa

15、nce Co-Pilot 作为测试统计的工具。我发现他对测试环境的影响最小,并且以相对直接的方式来提供数据。JAVA 分析器提供很多信息,但通常对负载测试来说影响太大而没有太多的用处。工具甚至可以让你在负载服务器上做一些分析,但这也很容易便测试无效。在这些测试中,我激活了详细的垃圾收集器来收集内存信息。我也使用 jconsole 和 jstack 工具(包含在 J2SE 1.5 中)来检查高负载下的 VM。我没有保留这些测试用例中负载测试的结果因为我认为这些数据不是很正确。同步瓶颈在诊断服务器问题时线程的信息是非常有用的,特别是对同步之类的问题。jstack 工具可以连接到运行的进程并且保存每

16、一个线程的堆栈信息。在 UNIX 系统可以用信号量 3 来保存线程的堆栈信息,在 WINDOWS 系统的控制台中可以用 Ctrl-Break。在第一项测试中,jstack 指出许多线程在 grindCPU()方法中被阻塞。 你可以已经注意到列表 2 中 grindCPU()方法的同步修饰符实际上并不必须。我在后一项测试中删除了他,如图 2 显示Figure 2 在图 2 中,你会注意到性能下降了。虽然我使用了更多的 CPU,但吞吐量和失败数都更差了。虽然垃圾回收周期变了,但每秒依然需要回收 100M。显然我们还没有找到主要的瓶颈。非竟争的同步相对于简单的函数调用还是很费时的。竟争性的同步就更费时了,因为除了内存需要同步外,VM 还需要维护等待的线程。在这种状况下,这些代价实际上要小于内存瓶颈。实际上

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 办公文档 > 解决方案

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号