1. 程式人生 > >使用spring非同步請求處理以及執行緒池所帶來的坑以及利用visualvm監測執行緒及效能【草稿】

使用spring非同步請求處理以及執行緒池所帶來的坑以及利用visualvm監測執行緒及效能【草稿】

前言

在開始前,請先看看:

因為涉及到執行緒,估計肉眼是沒辦法觀測的了只能用工具了。

預設執行緒池的坑

非同步web開發專題及tomcat下的spring非同步請求配置勘誤
當你按照上文高高興興地配置好非同步支援然後想要開啟高併發的人生,我只能說你圖樣圖森破了。。
第一,spring中對callable或者deffered這些action是不是都用同一個執行緒池呢?
請看下文:
謹慎使用Spring 配置標籤之任務配置標籤

好了,
在這裡插入圖片描述

上文作者用血一般的經歷告訴我們,不配置執行緒池的話,會使用預設的simpleAsyncTaskExecutor來敷衍了事的。。
這個當然不行!所以要自行配置執行緒池,使用執行緒池!

配置執行緒池

好了,我們立刻可以找到一篇文章配置執行緒池的。

好了,我們可以美滋滋地直接按照上文配置了。。

執行緒池作用測試

為了能夠得到沒有配置執行緒池以及配置執行緒池情況下,執行緒數量的變化規則,於是我們來做一個試驗。
本機環境:jdk8+win10

首先,開啟本機的jdk的bin目錄:

在這裡插入圖片描述

看到了jvisualvm這個程式沒有?開啟:

在這裡插入圖片描述

可以看到現在本地的java程式執行情況,包括idea也沒被放過。

好了,

第一種情況,不配置執行緒池然後直接多次訪問一個阻塞執行緒

在這裡插入圖片描述

註釋執行緒池的配置,

action這樣寫—對了,設定sleep是為了模擬耗時操作。

在這裡插入圖片描述

解釋一下使用callable的原因。原因是,callable直接執行在當前執行緒下面的,如果用DeferredResult
那麼形式可能就是:

在這裡插入圖片描述

然後執行網站:
你會看到visual vm已經監控到tomcat了,

在這裡插入圖片描述

然後先記錄一下當前的執行緒數量:
在這裡插入圖片描述

在這裡插入圖片描述

好了,執行緒數量49.。。然後我們要測試多次頻繁大量呼叫剛才的action----當然不是用人手了。。。現在沒工具,直接寫個js來模擬呼叫就好了。

var Ajax={
  get: function(url, fn) {
    // XMLHttpRequest物件用於在後臺與伺服器交換資料   
    var xhr = new XMLHttpRequest();            
    xhr.open('GET', url, true);
    xhr.onreadystatechange = function() {
      // readyState == 4說明請求已完成
      if (xhr.readyState == 4 && xhr.status == 200 || xhr.status == 304) { 
        // 從伺服器獲得資料 
        fn.call(this, xhr.responseText);  
      }
    };
    xhr.send();
  },
  // datat應為'a=a1&b=b1'這種字串格式,在jq裡如果data為物件會自動將物件轉成這種字串格式
  post: function (url, data, fn) {
    var xhr = new XMLHttpRequest();
    xhr.open("POST", url, true);
    // 新增http頭,傳送資訊至伺服器時內容編碼型別
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");  
    xhr.onreadystatechange = function() {
      if (xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 304)) {
        fn.call(this, xhr.responseText);
      }
    };
    xhr.send(data);
  }
};
var __call_times=0;
var _call_interval=setInterval(function(){ 
__call_times++;
Ajax.get('/api/region/getChildrenByCallable.do',function(){ console.log('呼叫中...');});
if(__call_times>1000){
clearInterval(_call_interval);
}
 }, 10);

有了這段程式碼就能測試了–這段程式碼意思是,在瀏覽器中,每10毫秒訪問一次一個url地址,當訪問到1000次時候就不重複這個過程了,退出來。
好了,這段程式碼怎麼執行呢?
這個屬於前端的範疇了,這樣應用:
用瀏覽器開啟網頁:
在這裡插入圖片描述
按f12跳出控制檯,按標籤console,
然後複製程式碼到console下面,再點標籤network看請求。

在這裡插入圖片描述

在這裡插入圖片描述

點選network標籤看看,已經自動發起很多次訪問請求了:
在這裡插入圖片描述

然後隔一段時間觀測一次visual vm的引數:

在這裡插入圖片描述

在這裡插入圖片描述

在這裡插入圖片描述

在這裡插入圖片描述

好了,可以停止了,一直在增加執行緒。

第二種情況,配置執行緒池然後直接多次訪問一個阻塞執行緒

設定執行緒池:

在這裡插入圖片描述

其他都一樣,然後重啟tomcat:
在這裡插入圖片描述

留意到沒有,新tomcat例項的pid是不一樣的,記錄新tomcat例項的執行緒數量:
在這裡插入圖片描述

然後,瀏覽器模擬頻繁呼叫:

在這裡插入圖片描述

瀏覽器開始幹活。

在這裡插入圖片描述

在這裡插入圖片描述

不對。。這結果不是預想中的,執行緒一直在增加。。

試驗暫停,尋找原因。

在這裡插入圖片描述

。。。。我還以為自動配置執行緒池之後會聰明到只能匹配上去呢。。原來還是要這樣配置的。

第三次試驗

好了,根據上面的參考文章配置非同步executor。
在這裡插入圖片描述

然後重啟—抱歉,一個壞訊息,還是同樣結果,配置的執行緒池不起作用。。。

這篇文章將作為草稿留存,稍後將新增總結文章以及解決方案。