亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

解決JAVA服務器性能問題研究分析(組圖)

2019-11-18 12:43:41
字體:
來源:轉載
供稿:網友

  項目團隊已經很熟悉如何組織一些具體的任務并完成他們。簡單的性能問題很輕易由一個開發人員分離并解決。然而大的性能問題,通常在系統處于高負載情況下發生,就不是這么簡單能處理的了。這些問題需要一個獨立的測試環境、一個模擬的負載,并且需要仔細地分析和跟蹤。
  
  在這篇文章中,我使用比較通用的工具和設備創建了一個測試環境。我會專注于兩個性能問題,內存和同步,他們很難用簡單的分析得到。通過一個具體的例子,我希望比較輕易地解決復雜的性能問題而且可以提供處理問題過程中的細節。
  
  改善服務器的性能
  
  服務器的性能改善是依靠于數據的。沒有可靠的數據基礎而更改應用或環境會導致更差的結果。分析器提供有用的java服務器應用信息,但由于從單用戶負載下的數據與多用戶負載下得到的數據是完全不同的,這導致分析器的數據并不精確。在開發階段使用分析器來優化應用的性能是一個好的方式,但在高負載下的應用分析可以取到更好的效果。
  
  在負載下分析服務器應用的性能需要一些基本的元素:
  
  1、可控的進行應用負載測試的環境。
  
  2、可控的人造負載使得應用滿負荷運行。
  
  3、來自監視器、應用和負載測試工具自身的數據搜集。
  
  4、性能改變的跟蹤。
  
  不要低估最后一個需求(性能跟蹤)的重要性因為假如不能跟蹤性能你就不能實際的治理項目。性能上10-20%的改善對單用戶環境來說并沒有什么不同,但對支持人員來說就不一樣了。20%的改善是非常大的,而且通過跟蹤性能的改善,你可以提供重要的反饋和持續跟蹤。
  
  雖然性能跟蹤很重要,但有時為了使后續的測試更加精確而不得不拋棄先前的測試結果。在性能測試中,改善負載測試的精確性可能需要修改模擬環境,而這些變化是必須的,通過變化前后的負載測試你可以觀察到其中的轉變。
  
  可控的環境
  
  可控的環境最少也需要兩臺獨立的機器和第三臺控制的機器。其中一臺用來生成負載,另一臺作為控制機與前一臺建立測試應用并接受反饋,第三臺機器運行應用。此外,負載和應用機器間的網絡應該與局域網分開??刂茩C接受運行應用機器的反饋如操作系統、硬件使用率、應用(非凡是VM)的狀態。
  
  負載模擬
  
  最精確的模擬通常用實際的用戶數據和WEB服務器端的訪問日志。假如你還沒有實際布署或者缺少實際的用戶數據,你可以通過構造類似的場景或詢問銷售和產品治理團隊或做一些有依據的猜想。協調負載測試和實際用戶體驗是一個持續的過程。
  
  在模擬中一些用戶場景是必須的。如在一個通用地址薄應用中,你應該區分更新和查詢操作。在我的測試應用中GrinderServlet類只有一個場景。單用戶連接10次訪問這個servlet(在每一次訪問間有一段暫停)。雖然這個應用很小,我認為這可以重復一些常見的東西。用戶通常不會連接給服務器請求而沒有間斷。假如沒有間斷,我們可能不能得到更精確的實際用戶上限。
  
  串行10個請求的另一個原因是實際應用中不會只有一個HTTP請求。單一而又分離的請求可以影響環境中的許多因素。對Tomcat來說,會為每一個請求創建一個會話,并且HTTP協議答應不同的請求重用連接。我會修改一下負載測試來避免混洧。
  
  GrinderServlet類不會執行任何排序操作,但這個需求在大部分應用中都很普通。在這些應用中,你需要創建模擬的數據集并且用他們來構造相關用例的負載測試。
  
  例如,假如用例涉及到用戶登錄一個WEB應用,從可能的用戶列表中選取隨機的用戶會只使用一個用戶更精確。否則,你可能不經意地使用了系統緩存或其他的優化或一些微妙的東西,而這會使得結果不正確。
  
  負載測試軟件
  
  負載測試軟件可以構造測試場景并且對服務進行負載測試。我會在下面的示例中使用OpenSTA測試軟件。這軟件簡單易學,結果也很輕易導出,并且支持參數化腳本,還可以監視信息的變化,他的主要缺點是基于Windows,但在這兒不是個問題。當然還有很多可選項如Apache的JMeter和Mercury的LoadRunner。
  
  The GrinderServlet
  
  列表1中顯示了GrinderServlet類,列表2中顯示了Grinder類
  
  Listing 1
  
  package 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, IOException {
  Grinderv1 grinder = Grinderv1.getGrinder();
  long t1 = System.currentTimeMillis();
  grinder.grindCPU(13);
  long t2 = System.currentTimeMillis();
  PrintWriter pw = res.getWriter();
  pw.print("<Html>/n< body> /n");
  pw.print("Grind Time = "+(t2-t1));
  pw.print("< body> /n< /html> /n");
  }}
  
  Listing 2
  
  package pub.capart;
  /*** This is a simple class designed to 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 I'm going to add up many many times";
  public static Grinderv1 getGrinder() {
  return singleton;
  }  public synchronized void grindCPU(int level) {
  StringBuffer sb = new StringBuffer();
  String s = randstr;
  for (int i=0;i<level;++i) {
  sb.append(s);
  s = getReverse(sb.toString());
  }
  }
  public String getReverse(String s) {
  StringBuffer sb = new StringBuffer(s);
  sb = sb.reverse();
  return sb.toString();
  }}
  
  類很簡單,但他們會產生兩個很常見的問題。咋一看瓶頸可能由grindCPU()方法的同步修飾符引起,但實際上內存消耗才是真正的問題所在。如圖1,我的第一個負載測試顯示了常見的負載變化。在這里負載變化很重要因為你正在模擬一個高的負載。這種熱身的方式也更精確因為避免了jsp編譯引起的問題。我通常習慣于在進行負載測試前先進行單用戶模擬。
  
 解決JAVA服務器性能問題研究分析(組圖)(圖一)
  Figure 1

  
  我在這篇文章中會使用相同的容量小結圖。在執行負載測試時還有更多的可用信息,但這里只用了有用的部分。最上面的面板包含每秒完成的請求數和請求時間信息。第二個面板包含活動用戶數和失敗率,我將超時、不正確的服務器應答和長于5秒的請求認為是失敗的。第三個面板包含JVM內存統計和CPU使用率。CPU值是所有處理器的用戶時間的平均值,這里所有的測試機器都是雙CPU的。內存統計圖包含垃圾回收表和每秒垃圾回收數。
  
  圖1中兩個最明顯的數據是50%的CPU使用率和大量內存使用和釋放。從列表2中可以看出這個原因。同步修飾符導致所有進程串行處理,就似乎只用了一個CPU,而算法導致大量內存消耗在局部變量上。
  
  通過CPU是個受限的資源,假如在這個測試中我可以完全利用到兩個CPU的話就可以提高一倍的性能。垃圾回收器運行得如此頻繁以致于不能忽略。在測試中每秒釋放的內存達到100M,很顯然這是個限制因素。失敗數這么大明顯這個應用是不可用的。
  
  監視
  
  在生成合理的用戶負載后,監視工具需要收集進程的運行狀況。在我的測試環境中可以收集到各種有用的信息:
  
  1、    所有計算機、網絡設備
  2、    等等的使用率
  3、    JVM的統計數據。
  4、    個別JAVA方法所花費的時間。
  5、    數據庫性能信息,6、    包括SQL查詢的統計。
  7、    其他應用相關的信息
  
  當然這些監視也會影響負載測試,但假如影響比較小也可以忽略?;旧霞偃缥覀兿氆@取所有上面的信息,肯定會影響測試的性能。但假如不是一次獲取所有信息還是有可能保證負載測試的有效性。僅對特定的方法設置定時器,僅獲取低負載的硬件信息和低頻率地獲取樣例數據。當然不加載監視器來做測試是最好的,然后和加載監視器的測試來做比較。雖然有時候侵入式監視是個好主意,但就不可能有監視結果了。
  
  獲取所有監視數據到一個中心控制器來做分析是最好的,但使用動態運行時工具也可以提供有用的信息。例如,命令行工具如PS、TOP、VMSTAT可以提供UNIX機器的信息;性能監視器工具可以提供WINDOWS機器的信息;而TeamQuest, BMC Patrol, SGI's Performance Co-Pilot, and ISM's PerfMan這樣的工具會在所有的測試環境中的機器安裝代理并且將需要的信息傳回中心控制機,這樣就可以提供文本或可視化的信息。在本文中,我使用開源的Performance Co-Pilot作為測試統計的工具。我發現他對測試環境的影響最小,并且以相對直接的方式來提供數據。
  
  JAVA分析器提供很多信息,但通常對負載測試來說影響太大而沒有太多的用處。工具甚至可以讓你在負載服務器上做一些分析,但這也很輕易便測試無效。在這些測試中,我激活了具體的垃圾收集器來收集內存信息。我也使用jconsole 和jstack工具(包含在J2SE 1.5中)來檢查高負載下的VM。我沒有保留這些測試用例中負載測試的結果因為我認為這些數據不是很正確。
  
  同步瓶頸
  
  在診斷服務器問題時線程的信息是非常有用的,非凡是對同步之類的問題。jstack工具可以連接到運行的進程并且保存每一個線程的堆棧信息。在UNIX系統可以用信號量3來保存線程的堆棧信息,在WINDOWS系統的控制臺中可以用Ctrl-Break。在第一項測試中,jstack指出許多線程在grindCPU()方法中被阻塞。
  
  你可以已經注重到列表2中grindCPU()方法的同步修飾符實際上并不必須。我在后一項測試中刪除了他,如圖2顯示
  
 解決JAVA服務器性能問題研究分析(組圖)(圖二)
  Figure 2

  
  在圖2中,你會注重到性能下降了。雖然我使用了更多的CPU,但吞吐量和失敗數都更差了。雖然垃圾回收周期變了,但每秒依然需要回收100M。顯然我們還沒有找到主要的瓶頸。
  
  非竟爭的同步相對于簡單的函數調用還是很費時的。竟爭性的同步就更費時了,因為除了內存需要同步外,VM還需要維護等待的線程。在這種狀況下,這些代價實際上要小于內存瓶頸。實際上,通過消除了同步瓶頸,VM內存系統承擔了更多的壓力最后導致更差的吞吐量,即使我使用了更多的CPU。顯然最好的方式是從最大的瓶頸開始,但有時這也不是很輕易確定的。當然,確保VM的內存處理足夠正常也是一個好的開始方向。
  
  內存瓶頸
  
  現在我會首先也定位內存問題。列表3是GrinderServlet的重構版本,使用了StringBuffer實例。圖3顯示了測試結果。
  
  Listing 3
  
  package pub.capart;
  /*** This is a simple class designed to simulate an application consuming* CPU, memory, and contending for a synchronization lock.*/public class Grinderv2 {
  private static Grinderv2 singleton = new Grinderv2();
  private static final String randstr =
  "this is just a random string that I'm going to add up many many times";
  private StringBuffer sbuf = new StringBuffer();
  private StringBuffer sbufrev = new StringBuffer();
  public static Grinderv2 getGrinder() {
  return singleton;
  }
  public synchronized void grindCPU(int level) {
  sbufrev.setLength(0);
  sbufrev.append(randstr);
  sbuf.setLength(0);
  for (int i=0;i<level;++i) {
  sbuf.append(sbufrev);
  reverse();
  }
  return sbuf.toString();
  }
  public String getReverse(String s) {
  StringBuffer sb = new StringBuffer(s);
  sb = sb.reverse();
  return sb.toString();  }}
  
 解決JAVA服務器性能問題研究分析(組圖)(圖三)
  Figure 3

  
  通常重用StringBuffer并不是一個好主意,但這里我只是為了重現一些常見的問題,而不量提供解決方案。內存數據已經從圖上消失了因為測試中沒有垃圾回收器運行。吞吐量戲劇性的增加而CPU使用率又回到了50%。列表3不只是優化了內存,但我認為主要了改善了過度的內存消耗。
  
  檢視同步瓶頸
  
  列表4另一個GrinderServlet類的重構版本,實現了一個小的資源池。圖4顯示了測試結果。
  
  Listing 4
  
  package pub.capart;/*** This is just a dummy class designed to simulate a process consuming* CPU, memory, and contending for a synchronization lock.*/public class Grinderv3 {
  private static Grinderv3 grinders[];
  private static int grinderRoundRobin = 0;
  private static final String randstr =
  "this is just a random string that I'm going to add up many many times";
  private StringBuffer sbuf = new StringBuffer();
  private StringBuffer sbufrev = new StringBuffer();
  static {
  grinders = new Grinderv3[10];
  for (int i=0;i<grinders.length;++i) {
  grinders[i] = new Grinderv3();
  }
  }
  public synchronized static Grinderv3 getGrinder() {
  Grinderv3 g = grinders[grinderRoundRobin];
  grinderRoundRobin = (grinderRoundRobin +1) % grinders.length;
  return g;
  }
  public synchronized void grindCPU(int level) {
  sbufrev.setLength(0);
  sbufrev.append(randstr);
  sbuf.setLength(0);
  for (int i=0;i<level;++i) {
  sbuf.append(sbufrev);
  reverse();
  }
  return sbuf.toString();
  }
  public String getReverse(String s) {
  StringBuffer sb = new StringBuffer(s);
  sb = sb.reverse();
  return sb.toString();  }}
  
 解決JAVA服務器性能問題研究分析(組圖)(圖四)
  Figure 4

  
  吞吐量有一定的增加,而且使用更少的CPU資源。竟爭和非竟爭性同步都是費時的,但通常最大的同步消耗是減少了系統的可伸縮性。我的負載測試不再滿足系統的需求了,因此我增加了虛擬的用戶數,如圖5 所示。
  
 解決JAVA服務器性能問題研究分析(組圖)(圖五)
  Figure 5

  
  在圖5 中吞吐量在負載達到飽和時下降了一些然后在負載減少時又提高了。此外注重到測試使得CPU使用率達到100%,這意味著測試超過了系統的最佳吞吐量。負載測試的一個產出是性能計劃,當應用的負載超過他的容量時會產生更低的吞吐量。
  
  水平可伸縮性
  
  水平伸縮答應更大的性能,但并不一定是費用相關的。運行在多個服務器上的應用通常比較運行在單個VM上的應用復雜。但水平伸縮支持在性能上的最大增加。
  
  圖6是我的最后一項測試的結果。我已經在三臺基本一致的機器上使用了負載平衡,只是在內存和CPU速度上稍有不同??偟耐掏铝恳哂谌兜膯螜C結果,而且CPU從來沒有完全利用。在圖6中我只顯示了一臺機器上的CPU結果,其他的是一樣的。
  
 解決JAVA服務器性能問題研究分析(組圖)(圖六)
  Figure 6

  
  小結
  
  我曾經花了9個月來布署一個復雜的JAVA應用,但卻沒有時間來做性能計劃。但差勁的性能使得用戶合約幾乎中止。開發人員使用分析器花了很長時間找到幾個小問題但沒有解決根本的瓶頸,而且被后續的問題完全迷惑了。最后通過負載測試找到解決方法,但你可以想到其中的處境。
  
  又一次我碰得更難的問題,應用只能達到所預期性能的1/100。但通過前期檢測到的問題和熟悉到負載測試的必要性,這個問題很快被解決了。負載測試相對于整個軟件開發的花費并不多,但其所歸避的風險就高多了。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产日韩中文字幕| 伊人久久大香线蕉av一区二区| 欧美与欧洲交xxxx免费观看| 97热精品视频官网| 疯狂做受xxxx欧美肥白少妇| 久久中文精品视频| 国产欧美va欧美va香蕉在线| 96pao国产成视频永久免费| 亚洲已满18点击进入在线看片| 2019中文字幕全在线观看| 日韩av高清不卡| 成人免费视频a| 日本精品久久电影| 日韩在线观看电影| 欧美大片在线看| 亚洲午夜久久久久久久| 亚洲女同性videos| 韩国精品美女www爽爽爽视频| 欧美性视频网站| 日韩亚洲成人av在线| 亚洲qvod图片区电影| 国产精品1区2区在线观看| 欧美黑人极品猛少妇色xxxxx| 亚洲精品一区久久久久久| 亚洲一区二区三区在线免费观看| 日韩成人在线视频| 最近2019好看的中文字幕免费| 国产精品成人av在线| 亚洲剧情一区二区| 日韩动漫免费观看电视剧高清| 日韩欧美aⅴ综合网站发布| 欧美电影在线观看| 国产精品美女久久| 久久国产精品偷| 中文字幕在线国产精品| 精品中文字幕久久久久久| 亚洲欧美另类在线观看| 91av成人在线| 在线观看不卡av| 久久亚洲精品网站| 国模吧一区二区| 亚洲成人精品av| 国产精品十八以下禁看| 久久中文字幕在线| 日韩av在线精品| 日韩欧美在线字幕| 亚洲精品国产精品自产a区红杏吧| 久久久久国产精品免费| 68精品国产免费久久久久久婷婷| 91精品国产91久久久久久吃药| 久久精品国产亚洲精品2020| 在线观看久久久久久| 精品二区三区线观看| 欧美视频在线观看 亚洲欧| 91九色单男在线观看| 国产一区二区三区在线观看视频| 亚洲理论在线a中文字幕| 亚洲xxxxx电影| 亚洲精品456在线播放狼人| 久久中国妇女中文字幕| 国产乱人伦真实精品视频| 亚洲影院污污.| 久久久亚洲欧洲日产国码aⅴ| 欧美中文字幕视频在线观看| 国产剧情久久久久久| 日韩av在线影视| 亚洲bt欧美bt日本bt| 国产精品精品久久久| 国产精品久久久久久婷婷天堂| 午夜精品久久久久久久久久久久| 国产精品久久久久不卡| 亚洲xxxxx性| 成人激情视频在线| 青青久久av北条麻妃海外网| 成人黄色av免费在线观看| 国产丝袜一区视频在线观看| 亚洲人精选亚洲人成在线| 中文字幕av一区中文字幕天堂| 欧美老女人在线视频| 中文日韩电影网站| 日韩高清电影免费观看完整版| 亚洲欧美激情精品一区二区| 久久夜精品香蕉| 午夜精品免费视频| 亚洲深夜福利网站| 国产91对白在线播放| 亚洲性线免费观看视频成熟| 成人在线视频网站| 国产欧美精品一区二区三区介绍| 欧美亚洲国产视频| 国产免费一区二区三区香蕉精| 国产精品男女猛烈高潮激情| 国产精品成人免费视频| 欧美性极品少妇精品网站| 一区二区三区视频免费| 亚洲欧美国产日韩天堂区| 992tv成人免费视频| 欧美成人黄色小视频| 久久久91精品国产一区不卡| 91免费观看网站| 国产免费久久av| 欧美另类69精品久久久久9999| 国产成人精品视| 亚洲欧美日韩中文在线制服| 毛片精品免费在线观看| 日韩av在线资源| 中文字幕精品一区二区精品| 亚洲无线码在线一区观看| 日韩精品一区二区视频| 日韩免费在线免费观看| 亚洲一区亚洲二区亚洲三区| 日韩中文字幕在线播放| 色妞色视频一区二区三区四区| 国产亚洲激情在线| 国产精品人人做人人爽| 播播国产欧美激情| 欧美日韩免费一区| 91精品国产乱码久久久久久蜜臀| 清纯唯美日韩制服另类| 日本视频久久久| 77777亚洲午夜久久多人| 成人午夜激情免费视频| 亚洲日本成人女熟在线观看| 欧美大荫蒂xxx| 国产精品久久久久久久久久免费| 欧美在线日韩在线| 伦伦影院午夜日韩欧美限制| 亚洲综合视频1区| 91情侣偷在线精品国产| 国产精品私拍pans大尺度在线| 伊人av综合网| 久久人人爽人人爽爽久久| 国产亚洲精品久久久久久777| 国产精品美女www爽爽爽视频| 国产精品96久久久久久又黄又硬| 亚洲久久久久久久久久| 精品国产欧美一区二区五十路| 国产精品男人的天堂| 91综合免费在线| 久久99国产精品自在自在app| 午夜精品美女自拍福到在线| 亚洲欧美日韩国产精品| 成人性生交大片免费观看嘿嘿视频| 成人在线观看视频网站| 日韩视频在线免费| 日韩欧美黄色动漫| 欧美中文字幕在线播放| 欧美激情videos| 日本精品久久久久久久| 亚洲男女自偷自拍图片另类| 欧美日韩午夜视频在线观看| 国产一区二区三区在线视频| 欧美激情视频三区| 亚洲成人免费在线视频| 欧美日韩成人在线观看| 亚洲一区二区三区香蕉| 91精品成人久久| 亚洲日本中文字幕免费在线不卡| 欧美日韩视频在线| 国产亚洲xxx| 日韩精品极品毛片系列视频| 欧美精品激情blacked18| 亚洲天堂男人的天堂| 欧美日韩国产页|