前端學Serverless系列--性能調優

本文做者:IMWeb IMWeb團隊原文出處:IMWeb社區 未經贊成,禁止轉載html

導語:Serverless雲函數的優勢是不怕高併發,理論上無限自動擴容,缺點是冷啓動特性致使冷啓動的時延比較高。那麼實際上性能如何,而且是否還有性能優化的空間和手段呢?node

最近試點Serverless的一個項目是從原有的node服務遷移到騰訊雲函數Serverless的。既然是項目遷移,那麼就要對比一下遷移先後的性能了。python

壓測方案

從測試同事那很快就找到壓測大師這個工具,壓測大師配置和報告都還算比較完善,是騰訊出的,內部的話用企業微信登陸直接免費可使用。web

缺點是:發請求的時間間隔有限制,最大隻能隔1分鐘,那就沒法純測試雲函數的冷啓動了,不過每一個階段都有自動增長人數,頁能間接測試到冷啓動到性能,看到測試結果時不時飆升到高耗時,那就多數就是冷啓動的耗時冷。chrome

壓測大師連接:wetest.qq.com數據庫

若是要測200之內的併發人數的話,能夠直接測試了。若是須要測高於200人數的併發量的話,須要先進行域名驗證(具體能夠看壓測大師提示並操做便可),就是放一個key到你的域名根目錄下,可讓壓測大師能夠訪問到,否則讓你隨便壓別人的域名怎麼辦?後端

這又難倒了我。由於騰訊雲自動生成的api網關連接下必然會有http://yourdomain/release/這個環境的路徑,根本沒法將key放到根目錄下。api

騰訊雲也提供了一個路徑映射的功能,能夠將這個/release/的路徑去掉,可是這個功能綁定在了自定義域名中,就是說,首先你得有一個本身的域名。跨域

這個問題和騰訊雲的產品反饋以後,將這個需求加到了排期中。瀏覽器

暫時我從同事那借用了一個子域名先進行繼續將測試工做進行下去。

注意:須要在騰訊雲備案了的域名。能夠綁定一個子域名,在我的的域名管理界面中,經過cname指向騰訊雲的API網關域名便可。

若是你要支持https的話,還須要申請個證書。有免費的能夠申請,同一個主域名能夠申請20個。申請完成以後,將證書上傳到騰訊雲便可。

若是不須要https都話,直接選http就能夠了,準備工做都OK了。

評測及優化

選擇測試的CGI,初步是要比較二者的鏈路,因此選取一個簡單的邏輯,只有一個數據庫查詢的CGI。

壓力從低到高進行嘗試。

剛嘗試到200併發人數到時候,成功率就有點不對勁了,只有80%多

分析問題

後來查了一下雲函數的日誌,問題就比較明瞭了。

雖說是理論上能夠無限擴容,可是也要配置給不給你這個上限。

優化方案

若是有需求能夠聯繫騰訊雲的同事進行相關資源的申請。

在提升限額和初始化一個資源池待用以後,再來壓測一下:

從上圖能夠看到成功率上去了,可是平均耗時和耗時長的部分仍是很多。

分析問題

將耗時比較長的拿出來和雲函數的開發一塊兒分析一下,耗時耗在哪裏了。

一、 有資源池,冷啓動的狀況下:

1)資源申請:代碼比較大,代碼解壓+load代碼 約2.5s+(解壓2.4s),若是加上下載估計會在3s多。

    若是調用很頻繁,正常狀況會有二、3百個請求(資源池容器數量)資源申請時間在2.5-3s之間; 若是調用不頻繁,耗時2.5s-3s的請求數會更多一些。

    2)函數調用:代碼自己執行時間:70ms~115ms左右,路徑耗時從5ms~600ms不等
複製代碼

二、熱啓動:也就是代碼自己執行的時間,這個看代碼自己要作的邏輯。機器不是瓶頸,主要是邏輯和須要調用第三方應用的耗時。我這個壓測例子的耗時就會在50ms以內,20ms左右。

三、如今有一些大於5s的,那些耗時都在路徑上或者有可能在單節點處理能力上。具體消耗在哪裏暫時看不出來。

優化方案

一、設置實例保留,減小冷啓動。這個最有效,降幅最大,至關因而保留了一個進程隨時響應請求。

二、設置合適的資源池數量,能夠大大下降冷啓動的耗時。

三、減小代碼量,我這個例子代碼量從58M下降了26M,主要是將並不經常使用並且代碼量比較大的庫拆分紅一個單獨的雲函數服務。

理論上結果應該會好看不少了?

實際上耗時最大的請求的確有所改善,可是平均值和90%的值仍是被一些高耗時拉高。

可是實際上壓測大師測的結果依然沒有達到很理想,下面彙總一下截止目前階段的結果。

繼續分析問題:

理論上雲函數服務該作的優化都作了,並且理論表現不會這麼差纔對?

後來雲的同事用python寫了腳原本本身壓測,發現200併發的平均耗時在200ms以內,並且超過200ms的請求也在可數以內。

因爲兩個測試的結果不一致,從本身寫的腳本和wetest壓測方案兩方展開分析。

1)腳本儘可能去還原wetest的方案,如異地部署,階梯增長併發,而且每一個階段維持30s。

2)直接找到了wetest的後臺同事進行問題溝通,嘗試了長鏈接,短鏈接,多IP壓力源,去掉日誌打印等操做。

結果:這個壓測結果其實已經達到了咱們預設的優化目標,平均在200ms以內。

如下仍是wetest的壓測結果(短鏈接+多IP)。

其中還有一個頗有意思的結果,長鏈接下的壓測結果:

那麼究竟是什麼緣由致使了這個結果的差別呢?

「網絡鏈接耗時」

在這個例子中,將長鏈接改爲短鏈接,從一地壓測改爲多IP壓測,效果最爲明顯,去掉日誌打印也必定程度減小了壓測源的性能損耗。

用戶側對比評測

既然地域不一樣,網絡不一樣,耗時差別這麼大,那麼真實的用戶耗時到底如何呢?

紅色的是Serverless,黃色的是原來的NodeServer。

分析問題

一、5月5日針對Serverless作了優化:將非簡單請求改爲簡單請求,減小一次「預檢」請求,加上dns-prefetch;加上了NodeServer原來的請求耗時進行對比。

剛開始是由於設置了header頭,瀏覽器認爲這個是非簡單請求。

非簡單請求的CORS請求,會在正式通訊以前,增長一次HTTP查詢請求,稱爲"預檢"請求(preflight)。瀏覽器先詢問服務器,當前網頁所在的域名是否在服務器的許可名單之中,以及可使用哪些HTTP動詞和頭信息字段。只有獲得確定答覆,瀏覽器纔會發出正式的XMLHttpRequest請求,不然就報錯。更詳細能夠查閱:跨域資源共享 CORS 詳解

圖爲一個請求產生了兩個請求,第一個是預檢請求,其中method爲OPTION, 返回狀態碼是204。

若是要用到非簡單請求的時候,服務端響應CORS的設置要注意到:

若是單選具體的GET,POST,能夠在API網關中的API管理中設置是否支持CORS,若是須要支持多個的請求方法的話,就只能後端業務處理。

二、優化以後,發現Serverless的請求依然比NodeServer慢100ms左右。

繼續分析發現:Serverless的請求會比NodeServer請求多一個Initial connection和SSL的時間。

爲何NodeServer沒有呢,由於咱們測試的頁面和發請求的頁面是同域的,因此這部分時間省了。爲何以前Serverless沒有發現呢,由於socket鏈接以後沒有那麼快銷燬,在頁面重複刷新的時候,反而是看不到這個耗時的。

須要清理一下socket: chrome://net-internals/#sockets

就能夠復現了,那麼這個耗時差距的緣由就很明顯了。

我作了一個簡單頁面進行測試,發現這樣的結果。Serverless和NodeServer的全程耗時其實差不太多,可是TCP鏈接和SSL時間會長不少。

這是爲何呢?我測試的這個Serverless是部署在上海的,而我在深圳進行測試的。

我再作了一個測試,加了一個部署在廣州的雲函數。

結果也很明顯了。

異地訪問部署的問題,由於原有的NodeServer接入了STGW。

STGW全稱Secure Tencent Gateway,騰訊安全雲網關,是一套實現多網統一接入,支持自動負載均衡的系統。因爲STGW提供了就近接入和SSL加速,因此這兩部分時間都相應有很多的優化。

那麼Serverless能不能用多地部署,就近接入來解決這個問題呢。

目前Serverless的雲函數和API網關都是地域隔離的。也就是說廣州的API網關對應廣州的雲函數,不能一個網關對多個地域的雲函數。這個需求和騰訊雲的產品溝通以後,歸入到之後的規劃建設當中。

那麼咱們目前有沒有折中的方案呢?

咱們設想了一些中轉的方案:

最後咱們選擇了最右側的方案,主要是簡單。

並且還能夠繼續經過在header中設置preconnect減小TCP握手和SSL的時間。

<link rel="preconnect" href="//example.com">

preconnect的兼容性狀況:

使用以前:

使用了以後的效果:

能夠看到Initial connection 和 SSL的時間是能夠直接節省掉了,在網絡差的狀況下,這部分節省的時間更爲顯著。

小結一下

Serverless雲函數性能評測和優化結果:

通過優化以後,Serverless雲函數的響應性能已經達到了須要即時返回場景的可用狀態。

在API網關監控到到耗時(不包括網絡時間和握手時間)

一、壓測方案、問題分析

1)wetest是騰訊公司支持的通用壓測方案,要用好也要對裏面提供的設置瞭解清楚用法和用途。

2)測試不限於壓測工具,本地腳本,瀏覽器network分析,線上用戶test,等等均可以嘗試用來評測分析。
複製代碼

二、性能優化方案

雲方面的優化:

1)上限設置

2)專用資源池

3)實例保持

4)架構升級(測試中)

5)就近接入(待規劃)
複製代碼

代碼方面的優化:

1)代碼邏輯和第三方調用

2)拆分不經常使用功能,減小代碼量

3)使用預加載減小connect的時間(preconnect)

4)接入STGW進行轉發
複製代碼

咱們深刻一點從雲函數的啓動過程來分析一下耗時在哪裏,如何去針對這些具體的步驟進行優化。

函數發生調用,調度系統看函數實例是否存在,若是實例存在,那麼就能夠執行函數,返回結果。這個時間是很是短的,在毫秒級別。

若是不存在,那麼須要建立容器,下載部署代碼。這些過程耗時百毫秒到幾秒不等,稱爲冷啓動。

優化函數的性能,也就須要從函數生命週期的各個階段去優化。

  • 一、函數實例複用,這是最直接有效的手段。可是保留多長時間合適?3分鐘,能解決95%的問題3小時,能解決99%的問題3天,能解決99.9%的問題。這個是一個成本和效果衡量的問題。(保留時間也不必定是固定不變的值,須要分析函數特色和時間段。 )
  • 二、預建立一批不一樣規格的容器(不含代碼)來減小建立容器的耗時。
  • 三、函數平臺有一個代碼倉庫來保存管理函數代碼的,在使用的時候纔會在下載到容器中。能夠對熱點代碼進行緩存:一級:Node計算節點緩存,二級:機房緩存
  • 四、經過機器學習預測流量,預先啓動一些函數實例,這樣就能夠儘可能消除冷啓動,保證明例都是熱啓動的。

這些都是平臺作的優化,那麼開發者能夠作什麼呢?

  • 代碼精簡:縮短代碼下載時間
  • 公共剝離:增長緩存效果,將一些公共的,常調用的服務拆分紅一個獨立的雲函數,能夠增長緩存的效果。
  • 資源複用:縮短執行時間,這裏指的是,函數使用的公共資源能夠放到函數外面來定義執行,好比數據庫的鏈接。
  • 保持活躍:避免資源回收,這就保證了請求都是熱啓動的。

最後

一、雲函數目前還在起步階段,應用的過程當中還會遇到這樣那樣的問題,好在騰訊雲的同事們(@masonlu等)積極響應,主動和咱們一塊兒尋找問題解決問題,最終一塊兒共同成長。

二、雲函數目前的特色就是不適合對時延要求比較高的應用,不適合有狀態的應用,可是這個不是必然的,這兩個問題有來合適的方案以後,就不會再是問題。

相關文章
相關標籤/搜索