百度學術改版與 CPU 100% 有關係麼?
個人有個依賴百度學術的服務叫 AnyPaper,它具體是什麼,感興趣的朋友可以去了解下。
最近百度學術換了一張新面孔,這一換不要緊,我的整個網站經常出現無響應的情況,登陸伺服器發現系統 CPU 穩定在 100%左右,這到底是怎麼回事?
先列一下網站環境:
尋找問題
由於網站執行一直很穩定,所以基本可以排除是程式碼上的問題,CPU 佔用很高,我的反應可能有以下幾種原因:
- 系統中毒 了,被植入了挖礦程式(網站程式停止後,CPU 立馬恢復正常,可以排除系統中毒可能);
- 網站漏洞 ,被植入挖礦指令碼(低版本的 Hutool 存在 ZipUtil 以及 FileUtil 的 slip 漏洞,貌似低版本的 SpringBoot 也有一些安全隱患);
- 使用者 請求量非常高 (實際上訪問人數可憐兮兮)。
綜上,首先對 SpringBoot 和 Hutool 進行了版本升級,然後在本地開始除錯執行,發現使用 AnyPaper 進行文獻搜尋的時候系統卡住了,單步進行除錯,發現程式卡在了正則匹配(匹配內容為百度學術搜尋結果的原始碼): <h3 class="t c_font">[\s\S]+?target="_blank">([\s\S]+?)</a>\s*</h3>([\s\S]+?)(?:(?:publish'}"\s*title="([^"]+)[\s\S]+?)|(?:<span>([^<]+)</span>[^<]+<span class="sc_time"\s*))data-year="(\d+)[\S\s]+?被引量: \s*(?:(\d+)|(?:<a[^>]+>\s*(\d+)))[\s\S]+?c_abstract">\s+([\s\S]+?)(?:\s*<div class="sc_allversion">[\s\S]+?</span>\s*(<a class="v_source" title="[\s\S]+?)</div>[\s\S]+?sc_subject">\s+([\s\S]+?))?\s*<div class="sc_other">
,正常情況下匹配結果如圖所示:

修復正則匹配
由於卡在了正則匹配,所以懷疑是百度學術頁面結構發生變化了,遂開啟百度學術看了一下,果然換了一張面孔,不過調整不是很大(部分元素被移除了,而且元素的位置發生了調整),很快就改好了新的正則匹配表示式: h3\s*class="t c_font"[\s\S]+?_blank">([\s\S]+?)</a>\s*</h3>[\s\S]+?c_abstract">\s+([\s\S]+?)\s+</div>([\s\S]+?)publish'}"\s*title="([^"]+)[\s\S]+?被引量: \s*(?:<a[^>]+>)?\s*(\d+)[\S\s]+?data-year="(\d+)[\S\s]+?<div class="sc_allversion">[\s\S]+?</span>\s*(<a class="v_source" title="[\s\S]+?)</div>[\s\S]+?class="sc_other">
,使用新的正則匹配後,程式恢復了正常,程式碼更新後,網站釋出了新版本。


深入問題
網站新版本釋出後,特意點選了常用的服務,執行正常,一切恢復如初。
然而,過了沒多久(不到 10 分鐘),整個系統又出現了無響應的情況,登陸伺服器檢視後,發現還是 CPU 100%,這就非常詭異了,當時真的是一度懷疑程式有類似 Java 反序列化的漏洞,被植入了挖礦程式;不過這種可能性很低,所以決定深入挖掘一下原因。
在百度上搜索: windows 排查 cpu 佔用
,看到一篇文章: ofollow,noindex">如何在 windows 下查詢 java 應用佔用 CPU 過高 ,非常契合目前的困境。
Windows 下排查 Java 應用佔用 CPU 過高
上述的文章已經敘述的比較詳細了,不過有一部分比較冗餘,個人在做一個小小的總結。
安裝 Process Explorer
從微軟官方網址 technet.microsoft.com/en-us/sysin… 下載安裝包,安裝包是一個 zip 壓縮檔案,解壓到自定義的資料夾即可。
解壓完成後,直接執行 procexp64.exe
,執行介面如下所示:

查詢佔用 CPU 的執行緒
從上圖可以看到程式已經佔用了 50% 左右的 CPU 了,因為 CPU 是雙核的所以目前有一個請求卡住了所以佔用了大概一半,選中程式,點選右鍵,然後選擇 Properties
選單,即可開啟程式屬性介面,在屬性介面可以看到程式的全部執行緒所佔用的資源。

使用 jstack 匯出堆疊資訊
jstack 是 java 虛擬機器自帶的一種堆疊跟蹤工具,某些情況下(jdk 的 bin 目錄沒有配置到系統環境變數 PATH 時)jstack 不能直接在命令列使用,最直接的使用方法就是去 java 的安裝目錄下的 bin 目錄,然後執行下面的命令: jstack.exe 2380 >c:/stack.log
,2380 是網站程式的 pid,最後的是堆疊日誌儲存的路徑。

從堆疊中查詢問題程式碼
如圖我們看到熱點執行緒 id 為:3952(0xf70)、5016(0x1398),開啟堆疊日誌 c:/stack.log
,搜尋 0xf70
以及 0x1398
:

解決問題
看到問題程式碼,果然還是正則匹配的問題,不過這個正則確實是沒有問題呀,搞了很久也沒有找到正則表示式的問題。
最終發現問題的根本原因:**百度學術的介面有時候是新版,有時候是舊版,**兩種正則表示式都可以應用到兩種頁面,但是對於不是正確的頁面需要耗費很久才可能匹配到結果,真的是坑到了極點呀。
在找到問題之前,個人採用的方案是把上面很長的正則簡化,簡化就是說之前一句話把全部元素都匹配出來了,現在就分步匹配:先匹配單條記錄,然後在單條記錄裡面匹配文章標題、年份、摘要等;採用分步匹配後,就不存在 CPU 佔用過高的問題了。