【HDC.Cloud】Web應用在鯤鵬上的性能優(yōu)化及加速技術實踐

隨著互聯(lián)網(wǎng)的興起,Web技術逐漸成為主流,各種技術流派蓬勃發(fā)展,當Web遇上鯤鵬又會發(fā)生哪些事情?

金蝶天燕作為中國領先的軟件基礎設施提供商,其業(yè)務主要涵蓋政府財政財務應用、政務大數(shù)據(jù)服務、云基礎設施等領域,在共建“鯤鵬生態(tài)”的過程中,如何才能提供更高的效能,將由金蝶天燕首席架構師馬震為大家?guī)砭史窒怼?/p>

一、     Web服務器架構分解

Connector和Engine是Tomcat最核心的兩個組件。

Connector負責處理網(wǎng)絡通信,以及應用層協(xié)議(HTTP,AJP)的解析,生成標準的ServletRequest和ServletResponse對象,然后傳遞給Engine處理。每個Connector監(jiān)聽不同的網(wǎng)絡端口。

Connector支持多種 I/O 模型:

· NIO:使用Java NIO實現(xiàn)

· NIO.2:異步I/O,使用JDK NIO.2實現(xiàn)

·  APR:使用了Apache Portable Runtime (APR)實現(xiàn)

Engine代表整個Servlet引擎,可以包含多個Host,表示它可以管理多個虛擬站點。Host代表的是一個虛擬主機,而一個虛擬主機下可以部署多個Web應用程序,Context表示一個Web應用程序。Wrapper表示一個Servlet,一個Web應用程序中可能會有多個Servlet。

二、     Web調優(yōu)與加速技術

對于跑在Web容器里的應用進行調優(yōu),首先要對應用的性能進行剖析。Linux平臺性能分析的技術和工具可以分為以下四類:

1、 Counter:

內(nèi)核維護各種統(tǒng)計信息就會被稱為Counter,它用于對事件進行計數(shù),例如網(wǎng)絡接收數(shù)據(jù)包的數(shù)據(jù)量,發(fā)出的磁盤I/O請求,以及執(zhí)行的系統(tǒng)調用次數(shù),均用作統(tǒng)計次數(shù),而常用工具是vmstat、mpstat、iostat、netstat。 

2、 Tracing:

是收集每個事件的數(shù)據(jù)進行分析,Tracing會捕捉所有事件進行分析,對CPU的開銷消耗較大,例如常用的TCPdump會把網(wǎng)絡通訊包根據(jù)設置的條件全部抓包,包括blktrace對block進行Tracing,包括strace對系統(tǒng)調用進行的Tracing,屬于常用的Tracing工具。

3、Profiling:

Tracing會抓取所有數(shù)據(jù),而Profiling只進行采樣。Profiling 是通過收集目標行為的樣本或快照,來了解目標的特征。Profiling可以從多個方面對程序進行動態(tài)分析,如CPU、Memory、Thread、I/O等,其中對CPU進行Profiling的應用最為廣泛。

CPU Profiling原理是基于一定頻率對運行的程序進行采樣,來分析消耗CPU時間的代碼路徑??梢曰诠潭ǖ臅r間間隔進行采樣,例如每10毫秒采樣一次。也可以設置固定速率采樣,例如每秒采集100個樣本。

CPU Profiling經(jīng)常被用于分析代碼的熱點,比如“哪個方法占用CPU的執(zhí)行時間最長”、“每個方法占用CPU的比例是多少”等等,然后我們就可以針對熱點瓶頸進行分析和性能優(yōu)化。

Linux上常用的CPU Profiling工具有:perf的 record 子命令和BPF profile。

4、Monitoring:

系統(tǒng)性能監(jiān)控會記錄一段時間內(nèi)的性能統(tǒng)計信息,以便能夠基于時間周期進行比較。這對于容量規(guī)劃,了解高峰期的使用情況都很有幫助。歷史值還為我們理解當前的性能指標提供了上下文。

監(jiān)控單個操作系統(tǒng)最常用工具是sar(system activity reporter,系統(tǒng)活動報告)命令。sar通過一個定期執(zhí)行的agent來記錄系統(tǒng)計數(shù)器的狀態(tài),并可以使用sar命令查看它們。

本文主要討論如何使用perf和BPF進行CPU Profiling。

perf:

perf最初是使用Linux性能計數(shù)器子系統(tǒng)的工具,因此perf開始的名稱是Performance Counters for Linux(PCL)。perf在Linux2.6.31合并進內(nèi)核,位于tools/perf目錄下。

隨后perf進行了各種增強,增加了tracing、profiling等能力,可用于性能瓶頸的查找和熱點代碼的定位。

perf是一個面向事件(event-oriented)的性能剖析工具,因此它也被稱為Linux perf events (LPE),或perf_events。

perf的整體架構如下:

perf 由兩部分組成:

·  perf Tools:perf用戶態(tài)命令,為用戶提供了一系列工具集,用于收集、分析性能數(shù)據(jù)。

·  perf Event Subsystem:Perf Events是內(nèi)核的子系統(tǒng)之一,和用戶態(tài)工具共同完成數(shù)據(jù)的采集。

內(nèi)核依賴的硬件,比如說CPU,一般會內(nèi)置一些性能統(tǒng)計方面的寄存器(Hardware Performance Counter),通過軟件讀取這些特殊寄存器里的信息,我們也可以得到很多直接關于硬件的信息。perf最初就是用來監(jiān)測CPU的性能監(jiān)控單元(performance monitoring unit, PMU)的。

perf支持多種性能事件:

這些性能事件分類為:

·   Hardware Events: CPU性能監(jiān)控計數(shù)器performance monitoring counters(PMC),也被稱為performance monitoring unit(PMU)

·   Software Events: 基于內(nèi)核計數(shù)器的底層事件。例如,CPU遷移,minor faults,major faults等。

·   Kernel Tracepoint Events: 內(nèi)核的靜態(tài)Tracepoint,已經(jīng)硬編碼在內(nèi)核需要收集信息的位置。

·   User Statically-Defined Tracing (USDT): 用戶級程序的靜態(tài)Tracepoint。

·   Dynamic Tracing: 用戶自定義事件,可以動態(tài)的插入到內(nèi)核或正在運行中的程序。Dynamic Tracing技術分為兩類:

    - kprobes:對于kernel的動態(tài)追蹤技術,可以動態(tài)地在指定的內(nèi)核函數(shù)的入口和出口等位置上放置探針,并定義自己的探針處理程序。

    - uprobes:對于用戶態(tài)軟件的動態(tài)追蹤技術,可以安全地在用戶態(tài)函數(shù)的入口等位置設置動態(tài)探針,并執(zhí)行自己的探針處理程序。

perf的功能強大,支持硬件計數(shù)器統(tǒng)計,定時采樣,靜態(tài)和動態(tài)tracing等。本文只介紹幾個常用的使用場景。

1. Couting Mode:

使用perf的stat命令可以收集性能計數(shù)器統(tǒng)計信息,精確統(tǒng)計一段時間內(nèi) CPU 相關硬件計數(shù)器數(shù)值的變化:

上圖所示,通過perf stat執(zhí)行一個命令,執(zhí)行完畢后,可以看到命令執(zhí)行時長12秒,同時顯示上下文切換次數(shù)、CPU周期次數(shù),以及多少指令和分支,可從中獲取更多幫助信息。

2. Sampling Mode

可以使用perf record以任意頻率收集快照。這通常用于CPU使用情況的分析。

·   sudo perf record -F 99 -a -g sleep 10

對所有CPU(-a)進行call stacks(-g)采樣,采樣頻率為99 Hertz(-F 99),即每秒99次,持續(xù)10秒(sleep 10)。

·   sudo perf record -F 99 -a -g -p PID sleep 10

對指定進程(-p PID)進行采樣。

·   sudo perf record -F 99 -a -g -e context-switches -p PID sleep 10

perf可以和各種instrumentation points一起使用,以跟蹤內(nèi)核調度程序(scheduler)的活動。其中包括software events和tracepoint event(靜態(tài)探針)。

上面的例子對指定進程的上下文切換(-e context-switches)進行采樣。

perf record的運行結果保存在當前目錄的perf.data文件中,采樣結束后,我們使用perf report查看結果。

交互查看模式:

直接執(zhí)行perf report,將采樣數(shù)據(jù)進行加載,此時運行的是交互式模式,針對不同的代碼路徑,統(tǒng)計出百分比,前綴帶+號的可通過回車進行路徑的展開。

通過交互模式進行分析,可先從占用CPU時間最多的代碼路徑開始分析,看哪里占用的CPU時間多,是否能夠進行優(yōu)化。

統(tǒng)計模式:

使用--stdio選項打印所有輸出。運行結束后,會將所有的代碼路徑展開,每一個代碼路徑上的CPU的消耗時間都會顯示出來。

BPF:

BPF作為系統(tǒng)級的性能分析工具,最初是為BSD開發(fā),是用來改進網(wǎng)絡數(shù)據(jù)包捕獲性能的工具。

BPF是運行在內(nèi)核級進行過濾,無需將數(shù)據(jù)包拷貝到用戶空間,因為它在內(nèi)核可以直接過濾,所以提高了數(shù)據(jù)包過濾的性能。常用的tcpdump內(nèi)部使用的就是BPF。

2013年BPF被重寫,被稱為Extended BPF (eBPF),于2014年包含進Linux內(nèi)核中。改進后的BPF成為了通用執(zhí)行引擎,可用于多種用途,包括創(chuàng)建高級性能分析工具。

BPF允許在內(nèi)核中運行mini programs,來響應系統(tǒng)和應用程序事件(例如磁盤I/O事件)。這種運作機制和JavaScript類似:JavaScript是運行在瀏覽器引擎中的mini programs,響應鼠標點擊等事件。BPF使內(nèi)核可編程化,使用戶(包括非內(nèi)核開發(fā)人員)能夠自定義和控制他們的系統(tǒng),以解決實際問題。

BPF可以被認為是一個虛擬機,由指令集,存儲對象和helper函數(shù)三部分組成。BPF指令集由位于Linux內(nèi)核的BPF runtime執(zhí)行,BPF runtime包括了解釋器和JIT編譯器。BPF是一種靈活高效的技術,可以用于networking,tracing和安全等領域。我們重點關注它作為系統(tǒng)監(jiān)測工具方面的應用。

BPF的優(yōu)勢:

由于BPF的迷你程序是運行在內(nèi)核,所以可在內(nèi)核進行計算的統(tǒng)計匯總,以此大幅減少復制到用戶空間的數(shù)據(jù)量。

BPF已經(jīng)內(nèi)置在Linux內(nèi)核中,因此你無需再安裝任何新的內(nèi)核組件,就可以在生產(chǎn)環(huán)境中使用BPF。

BCC和bpftrace:

直接使用BPF指令進行編程非常繁瑣,因此很有必要提供高級語言前端方便用戶使用,于是就出現(xiàn)了BCC和bpftrace。

BCC(BPF Compiler Collection) 提供了一個C編程環(huán)境,使用LLVM工具鏈來把 C 代碼編譯為BPF虛擬機所接受的字節(jié)碼。此外它還支持Python,Lua和C++作為用戶接口。

bpftrace 是一個比較新的前端,它為開發(fā)BPF工具提供了一種專用的高級語言。bpftrace適合單行代碼和自定義短腳本,而BCC更適合復雜的腳本和守護程序。

BCC已經(jīng)包含70多個BPF工具,用于性能分析和故障排查。這些工具都可以直接使用,無需編寫任何BCC代碼。

BCC已經(jīng)自帶了CPU profiling工具:

一般的CPU profiling都是分析on-CPU,即CPU時間都花費在了哪些代碼路徑。off-CPU是指進程不在CPU上運行時所花費的時間,進程因為某種原因處于休眠狀態(tài),比如說等待鎖,或者被進程調度器(scheduler)剝奪了 CPU 的使用。這些情況都會導致這個進程無法運行在 CPU 上,但是仍然花費了時間。

off-CPU是針對on-CPU的補充,on-CPU分析的是什么正在CPU上運行,off-CPU分析的是進程由于某種原因處于休眠狀態(tài),如磁盤阻塞、等待網(wǎng)絡事件、被鎖阻塞或時間片用完而被切換。此時雖然沒有在CPU上運行,但仍然花費時間,如果通過off-CPU跟on-CPU相結合,即可了解線程所有的時間花費,更為全面地了解程序的運行情況。

抓取的采樣如何更好地展示與分析——火焰圖:

火焰圖是Brendan Gregg發(fā)明的將stack traces可視化展示的方法?;鹧鎴D把時間和空間兩個維度上的信息融合在一張圖上,將頻繁執(zhí)行的代碼路徑以可視化的形式,非常直觀的展現(xiàn)了出來。

火焰圖可以用于可視化來自任何profiler工具的記錄的stack traces信息,除了用來CPU profiling,還適用于off-CPU,page faults等多種場景的分析。本文只討論 on-CPU 和 off-CPU 火焰圖的生成。

要理解火焰圖,先從理解Stack Trace開始。

1、 何為Stack trace:

Stack Trace是程序執(zhí)行過程中,在特定時間點的函數(shù)調用列表。例如,func_a()調用func_b(),func_b()調用func_c(),此時的Stack Trace可寫為:

func_c

func_b

func_a

2、 profilingStack trace的含義是什么:

我們做CPU profiling時,會使用perf或bcc定時采樣Stack Trace,這樣會收集到非常多的Stack Trace。前面介紹了perf report會將Stack Trace樣本匯總為調用樹,并顯示每個路徑的百分比?;鹧鎴D是怎么展示的呢?

考慮下面的示例,我們用perf定時采樣收集了多個Stack Trace,然后將相同的Stack Trace歸納合并,統(tǒng)計出次數(shù)。

如圖右側所示,共采集了10個樣本,第一個代碼路徑func_a調用func_b調用func_c,有7個樣本。第二個路徑a調用b有2個樣本,第三個路徑有1個樣本。

此時,將相同的Stack trace進行歸納合并,統(tǒng)計成圖右側格式,即可使用火焰圖工具生成火焰圖。

火焰圖具有以下特性:

·   每個長方塊代表了函數(shù)調用棧中的一個函數(shù)

·   Y 軸顯示堆棧的深度(堆棧中的幀數(shù))。調用棧越深,火焰就越高。頂層方塊表示 CPU 上正在運行的函數(shù),下面的函數(shù)即為它的祖先。

·   X 軸的寬度代表被采集的樣本數(shù)量,越寬表示采集到的越多,即執(zhí)行的時間長。需要注意的是,X軸從左到右不代表時間,而是所有的調用棧合并后,按字母順序排列的。

拿到火焰圖,尋找最寬的塔并首先了解它們。頂層的哪個函數(shù)占據(jù)的寬度最大,說明它可能存在性能問題。

如何使用系統(tǒng)工具分析Java的CPU Profiling:

雖然有很多Java專用的profiler工具,但這些工具一般只能看到Java方法的執(zhí)行,缺少了GC,JVM的CPU時間消耗,并且有些工具的Method tracing性能損耗比較大。

perf和BCC profile的優(yōu)點是它很高效,在內(nèi)核上下文中對堆棧進行計數(shù),并能完整顯示用戶態(tài)和內(nèi)核態(tài)的CPU使用,能看到native libraries(例如libc),JVM(libjvm),Java方法和內(nèi)核中花費的時間。

profiling圖:

如果使用傳統(tǒng)的java profiling工具,可能只看到中間部分,即Java的調用棧的情況,而對于GC、JVM以及內(nèi)核的運行情況無法抓取。

如果使用系統(tǒng)工具即可抓取進程全貌,而進行更全面的分析。

但是,perf和BCC profile不能很好地與Java配合使用:

它們識別不了Java方法和stack traces

具體原因:

·  JVM的JIT(just-in-time)沒有給系統(tǒng)級profiler公開符號表。

·   VM還使用幀指針寄存器(frame pointer register)作為通用寄存器,打破了傳統(tǒng)的堆棧遍歷。

目前有兩種解決方案:

1、 使用perf-map-agent:

使用JVMTI agent perf-map-agent,生成Java符號表,供perf和bcc讀取(/tmp/perf-PID.map)。同時要加上-XX:+PreserveFramePointer JVM 參數(shù),讓perf可以遍歷基于幀指針(frame pointer)的堆棧。

2、 使用async-profiler:

使用async-profiler,該項目將perf的堆棧追蹤和JDK提供的AsyncGetCallTrace結合了起來,同樣能夠獲得mixed-mode火焰圖。同時,此方法不需要啟用幀指針,所以不用加上-XX:+PreserveFramePointer參數(shù)。

以上兩種方式均可畫出完整的Java火焰圖。

下面我們就分別演示這兩種方式。

perf-map-agent+perf :

用perf-map-agent為perf生成符號表,同時perf-map-agent也提供了perf-java-flames腳本,可以一步生成火焰圖。

perf-java-flames接收perf record命令參數(shù),它會調用perf進行采樣,然后使用FlameGraph生成火焰圖,一步完成,非常方便。

perf-map-agent+ bcc profile :

同樣使用perf-map-agent生成符號表,然后調用bcc profile進行采樣,生成火焰圖。因為bcc提供了off-cpu的分析,也可以生成off-cpu的火焰圖。

async-profiler:

async-profiler將perf的堆棧追蹤和JDK提供的AsyncGetCallTrace結合了起來,做到同時采樣Java棧與Native棧,因此也就可以同時分析Java代碼和Native代碼中存在的性能熱點。

async-profile提供命令行工具,只需指定持續(xù)的時間以及進程ID,即可一步生成火焰圖。

async-profiler繪制的火焰圖:

如圖所示,綠色代表Java的調用棧,同時可以看到內(nèi)核調用棧以及本地庫的調用棧,同時顯示在一張圖上,可以更全面的分析Java程序的CPU使用情況。

Java CPU Profiling——總結

為Java進程生成CPU火焰圖基本流程的三步:

·   使用工具采集樣本;

·  不論perf或BCC,完成樣本采集后使用火焰圖項目中提供的腳本,將樣本進行歸納合并,統(tǒng)計出Stack trace的出現(xiàn)頻率,將Stack trace進行匯總;

·   匯總完成后使用腳本根據(jù)上一步的結果繪制出火焰圖。

以下兩種方式可繪制出Java Stacks和native stacks的完整火焰圖

·  如果只對javaprofiler進行on-CPU分析,async-profiler更為方便,可一步生成火焰圖;

·   如果需要全面了解Java進程運行情況,不僅要分析on-CPU,且同時分析系統(tǒng)鎖的開銷、I/O的開銷以及scheduler的工作,此時還需使用perf和BCC工具做分析。

三、     基于鯤鵬的深度優(yōu)化

CPU與內(nèi)存:

·   NUMA的優(yōu)化,即盡量減少跨NUMA的內(nèi)存訪問;

·   修改CPU的預取開;

·  定時器機制調整, 減少不必要的時鐘中斷;

·   調整內(nèi)存頁的大小為64K,translation目前是4k的,調整到64K以后,可以提高TLB的命中率;

·  調整線程并發(fā)數(shù)

以上是對CPU還有內(nèi)存的調優(yōu)。

磁盤:

·   調整臟數(shù)據(jù)刷新策略,減小磁盤的IO壓力;

·   調整磁盤文件預讀參數(shù);

·   優(yōu)化磁盤IO調度方式,I/O調度需要根據(jù)具體的應用情況選擇合適的磁盤I/O調度算法;

·   文件系統(tǒng)參數(shù)優(yōu)化;

·   使用異步文件操作libaio提升系統(tǒng)性能

以上是對磁盤部分的調優(yōu)。

·  PCIE Max Payload Size大小配置;

·  網(wǎng)絡NUMA綁核,減少跨CPU庫的訪問;

·  中斷聚合參數(shù)調整;

·  開啟TSO,把TCP分段的卸載處理交給網(wǎng)卡,減少CPU的運算;

·   使用epoll代替select

以上是對網(wǎng)絡部分的優(yōu)化方法。

我們做性能測試時候具體用到的幾種優(yōu)化:

·   配置虛擬機獨占NUMA,即盡量減少跨CPU庫的訪問;

·   配置了增強型的大頁內(nèi)存;

·  關閉透明大頁;

·   配置高精度的虛擬機;

·  最后一個是JDK對GC葉子節(jié)點的優(yōu)化,這個是鯤鵬JDK特有的優(yōu)化。

操作系統(tǒng)的TCP協(xié)議站配置:

主要是調整了發(fā)送和接收的緩沖器的大小,調整backlog隊列,避免隊列不夠的情況發(fā)生。

文件進程及網(wǎng)卡調整:

調整文件進程,開啟網(wǎng)卡多隊列。

四、     技術優(yōu)化方向與展望

后面我們將對數(shù)據(jù)庫連接池、EJB容器、線程池、日志模塊做進一步的優(yōu)化。

數(shù)據(jù)庫連接池優(yōu)化:

主要是增強連接池的監(jiān)控,簡化連接池的配置。

EJB容器優(yōu)化:

改進底層的IO模型,提高EJB遠程調用的性能。

應用服務器http線程池優(yōu)化:

HTTP線程池,與連接池類似,增加更詳盡的監(jiān)控特性,讓配置更簡化。

日志模塊優(yōu)化:

日志模塊同時進行一些優(yōu)化,以此提高性能。

提問&解答:

Q:統(tǒng)計動作可以在內(nèi)核完成嗎?

A:如果BPF的話,統(tǒng)計是可以的,因為我們可以理解為BPF run time就是運行在內(nèi)核態(tài)的一個虛擬機,小程序編譯成BPF字節(jié)碼加載到了內(nèi)核,然后可以運行統(tǒng)計以及計算。

Q:traceing的優(yōu)勢是什么?

A: traceing優(yōu)勢比較全面,因為它會抓取所有數(shù)據(jù)。采樣只會采集部分數(shù)據(jù),例如一秒鐘進行99次采樣,此時可能會出現(xiàn)采樣數(shù)據(jù)不全的問題,但采樣對程序的影響非常小,損失只在2、3%左右的樣子。如果對java進行traceing的話,影響非常大,可能不能真實地反映出這個程序的運行狀況,這就兩者之間的對比。

Q:我們用perf和BPF解決過哪些實際的問題?

A:我們在產(chǎn)品在發(fā)布之前都會做一些性能的測試,此時用perf或者BPF去抓取火焰圖,相當于對運行的進程拍了一個X光,內(nèi)部狀況一目了然??梢詫狳c代碼進行分析。例如有些地方中還在使用傳統(tǒng)的同步的數(shù)據(jù)結構,那我們可以換成并發(fā)數(shù)據(jù)結構,比如ConcurrentHashMap。還有一些對鎖的使用問題,由于使用方法不對,會拋出很多異常,這時在火焰圖里也能明顯地看到很寬的山峰,再去仔細分析代碼的時候就可以發(fā)現(xiàn)且容易定位到系統(tǒng)問題。

更多Web應用的優(yōu)化內(nèi)容:https://www.huaweicloud.com/kunpeng/


免責聲明:本網(wǎng)站內(nèi)容主要來自原創(chuàng)、合作伙伴供稿和第三方自媒體作者投稿,凡在本網(wǎng)站出現(xiàn)的信息,均僅供參考。本網(wǎng)站將盡力確保所提供信息的準確性及可靠性,但不保證有關資料的準確性及可靠性,讀者在使用前請進一步核實,并對任何自主決定的行為負責。本網(wǎng)站對有關資料所引致的錯誤、不確或遺漏,概不負任何法律責任。任何單位或個人認為本網(wǎng)站中的網(wǎng)頁或鏈接內(nèi)容可能涉嫌侵犯其知識產(chǎn)權或存在不實內(nèi)容時,應及時向本網(wǎng)站提出書面權利通知或不實情況說明,并提供身份證明、權屬證明及詳細侵權或不實情況證明。本網(wǎng)站在收到上述法律文件后,將會依法盡快聯(lián)系相關文章源頭核實,溝通刪除相關內(nèi)容或斷開相關鏈接。

2020-04-07
【HDC.Cloud】Web應用在鯤鵬上的性能優(yōu)化及加速技術實踐
隨著互聯(lián)網(wǎng)的興起,Web技術逐漸成為主流,各種技術流派蓬勃發(fā)展,當Web遇上鯤鵬又會發(fā)生哪些事情?金蝶天燕作為中國領先的軟件基礎設施提供商,其業(yè)務主要涵蓋政府財政財務應用、政務大數(shù)據(jù)服務、云基礎設施等領域,在共建“鯤鵬生態(tài)”的過程中,如何才能提供更高的效能,將由金蝶天燕首席架構師馬震為大家?guī)砭史窒怼?/div>

長按掃碼 閱讀全文