執行在 SSR 模式下的 Angular 應用,為了避免伺服器端和客戶端兩次呼叫同樣的 API 引起螢幕的 Flickering 問題,通過都會使用 Angular TransferState
服務將資訊從伺服器傳送到客戶端,其工作原理如下圖所示:
首先在應用程式 app.module.ts
中匯入 BrowserTransferStateModule
:
import { BrowserModule, BrowserTransferStateModule } from '@angular/platform-browser';
imports: [
BrowserModule.withServerTransition({appId: 'my-app'}),
BrowserTransferStateModule,
...
]
然後在伺服器端模組 app.server.module.ts
中匯入 ServerTransferStateModule
:
import { ServerModule, ServerTransferStateModule } from '@angular/platform-server';
imports: [
AppModule,
ServerModule,
ServerTransferStateModule,
...
]
我們可以使用 makeStateKey
函式來建立一個鍵,以儲存狀態中的資料(將傳遞給瀏覽器)。 使用 this.state.get
從狀態中獲取資料,並使用 this.state.set
設定狀態中的資料。 進行 API 呼叫時,使用之前呼叫 makeStateKey 建立的金鑰將返回的資料儲存在Angular state 中。
採用了 TransferState 服務的 Spartacus SSR 應用,在出現記憶體洩漏時通常有下列表現:
- 使用者請求響應時間增加
- jsapps pods 頻繁重啟
- 執行時出現如下日誌:
(1) SSR rendering exceeded timeout 3000, fallbacking to CSR for /xyz
(2) PM2 Process 0 restarted because it exceeds --max-memory-restart value (current_memory=4009730048 max_memory_limit=3865051136 [octets])
(3) Rendering of /xyz was not able to complete. This might cause memory leaks!
如果出現了以上之一的症狀,我們可以使用 Dynatrace 進行記憶體洩漏原因分析。
在 Dynatrace 中,可以從左側導航選單中的技術和程式選項和 Node.js 技術中找到每個 SSR pod。 程式組將具有包含您的應用程式 SSR 的主檔案的名稱,通常是 main.js 或 server.js。 單擊後者將列出在指定時間範圍內處於活動狀態的 pod,允許我們訪問任何單個 pod 的程式詳細資訊頁面。
在 high level 層面,僅通過檢視 Dynatrace 中的 V8 堆記憶體圖表就可以對記憶體洩漏的可能性做出明智的判斷。 Node.js 中潛在記憶體洩漏的最明顯跡象是:
- V8 堆記憶體出現峰值(sharp spike)
- 每次 pod 重新啟動後,記憶體佔用圖都會
再次
出現峰值
通常情況下,如下圖所示的鋸齒模式(saw tooth
)似乎表明應用程式健康,因為假設記憶體中的每個釋放都是由於垃圾收集而發生的。 但是,如果您發現記憶體中的每個峰值之後都會有一個記憶體釋放的行為,而該記憶體釋放僅僅是因為 pod 的重啟造成的,那麼該應用很可能存在記憶體洩漏的問題。
如果我們增加系統的可用記憶體,但是 Dynatrace 裡觀測到的鋸齒模式仍然存在,這種效能更能成為該應用存在記憶體洩漏的有力證據之一。