首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

AOP@Work: AspectJ 企業級效能監控實戰 (一) — 核心架構與 JDBC/Servlet 監控基石

     編輯:Java 相關知識

前言:為何傳統監控失效於生產環境

現代 Java 應用是複雜、多執行緒、分散式系統。Profiler 開銷過大,不適合生產/負測環境。手工插桩代碼分散、糾纏、難維護、難擴展。**系統監控是經典橫切關注點** — AspectJ 天生適合:定義切點匹配數百連接點,Advice 自動織入統計邏輯,模組化、可擴展、開銷可控。

本系列使用開源 **Glassbox Inspector** 框架核心代碼示範:以中等代碼量實現請求計數/耗時/最差案例、JDBC 連線/Statement 深度監控、JMX 即時公開、巢狀統計關聯 — **生產環境可用開銷**。

核心架構總覽

Glassbox Inspector + JConsole 架構

圖 1:多應用監控、合併統計、JMX Remote 公開、JConsole 視覺化

Glassbox Inspector 架構圖

圖 2:切面與容器內應用交互 → 捕獲效能數據 → JMX Remote 標準暴露

**JMX 優勢**:標準 API、成熟工具 (JConsole、VisualVM)、Java 5 內建、企業容器標配。

第一步:Servlet 請求基礎監控

public aspect HttpServletMonitor {
    public pointcut monitoredOperation(Object operation) :
        execution(void HttpServlet.do*(..)) && this(operation); // 匹配 doGet/doPost/doPut...
    void around(Object operation) : monitoredOperation(operation) {
        long start = System.currentTimeMillis();
        proceed(operation);
        PerfStats stats = lookupStats(operation);
        stats.recordExecution(start, System.currentTimeMillis());
    }
    // lookupStats 以 Servlet Class 為鍵,WeakIdentityHashMap 儲存
}
  • 切點精準匹配所有 `HttpServlet.do*` 方法。
  • `around` Advice:計時 → `proceed()` → 記錄統計。
  • `PerfStats` 介面:`accumulatedTime`、`maxTime`、`count`、`reset()`。
  • `PerfStatsFactory` 抽象統計物件建立,利於擴展。

第二步:JMX 公開 — 讓統計可視、可管

**可重用 `JmxManagement` 切面**:

  • 標記介面 `ManagedBean` 定義 `getOperationName()`、`getMBean()`。
  • `after() returning` 攔截 `ManagedBean` 建構子 → 自動向 `MBeanServer` 註冊。
  • IOC 模式注入 `MBeanServer`,適合 Spring 容器管理。

**`StatsJmxManagement` 專用於統計**:

  • `declare parents: PerfStats implements PerfStatsMBean` — **動態實作介面**,避免標準 MBean 需為每個實作類建立對應介面的僵化。
  • 使用 Spring `InterfaceBasedMBeanInfoAssembler` 建立 `DynamicMBean`,以 `PerfStatsMBean` 為管理介面。
  • JMX ObjectName 格式:`glassbox.inspector:operation="fully.qualified.ServletClassName"`。

JConsole 顯示 Servlet 統計

圖 3:JConsole 即時顯示各 Servlet 執行次數、總耗時、最大耗時

第三步:資料庫深度監控 — JDBC 連線與 Statement

**設計模式:Worker Object (RequestContext)** — 匿名內部類封裝請求上下文,支援巢狀關聯、生命週期管理、統計快取。比 `ThreadLocal` 更模組化、型別安全。

抽象基礎 `AbstractRequestMonitor`

  • `requestExecution(RequestContext)` / `inRequest(RequestContext)` 切點定義監控範圍。
  • `after() returning` 攔截 `RequestContext` 建構子 → 建立父子關聯 (`setParent`),**實現巢狀統計樹** (Servlet → JDBC Connection → Statement)。
  • `RequestContext.execute()` 模板方法:計時 → `doExecute()` (子類實作) → 記錄統計。
  • `lookupStats()` 抽象方法:子類依上下文決定統計物件 (Servlet 看類別、JDBC 看 DataSource/URL/SQL)。

JdbcConnectionMonitor:連線效能與資料庫識別

  • 切點:`DataSource.getConnection()`、`Driver.connect()`、`DriverManager.getConnection()`。
  • 排除巢狀連線調用 (`cflowbelow`),避免重複計數。
  • 關鍵挑戰:**DataSource 無標準取名方法** → 反射嘗試 `getDatabaseName`、`getUrl`、`getDescription` 等常見方法。
  • `WeakIdentityHashMap` 關聯連線實例與資料庫名稱,**不依賴 `hashCode/equals`**,支援動態 Proxy/Wrapper 連線。
  • 父請求 (Servlet) 統計物件持有各資料庫 `DatabaseStats` 容器。

JdbcStatementMonitor:SQL 執行效能與參數關聯

  • 切點:`java.sql..*.execute*()` — 捕獲所有 Statement/PreparedStatement/CallableStatement 執行。
  • 兩張弱身份映射表:
    • `statementCreators: Statement -> Connection`:`after() returning` 攔截 `Connection.createStatement()` 等 12 種建立方法,**繞過 Wrapper 連線的 `getConnection()`**。
    • `statementSql: Statement -> String`:`before` 切點捕獲動態 SQL 參數 (`args(sql)`);`after` 切點捕獲 `PreparedStatement` 建立時的 SQL。
  • `stripAfterWhere(sql)` 移除 WHERE 子句後內容:**避免敏感數據洩漏、將同類查詢歸類統計**。
  • `lookupStats()` 串聯查詢:Statement → Connection → 資料庫名稱 → 父 Servlet 統計 → `DatabaseStats` → `RequestStats(SQL)`。
  • 防禦性編程:各層檢查 `null`,應用違背預期時不拋出異常。

一般化監控設計類別圖

圖 4:監控物件層次 — OperationStats (Servlet) → DatabaseStats (DataSource) → RequestStats (SQL)

JConsole 顯示資料庫統計

圖 5:JConsole 深入檢視特定資料庫、特定 SQL 執行統計

巢狀 Servlet 監控升級

更新 `HttpServletMonitor` 繼承 `AbstractRequestMonitor`,使用 `RequestContext` Worker Object。`lookupStats()` 邏輯:

if (getParent() != null) {
    // 巢狀操作:如 BannerServlet 被其他 Servlet include
    return parentStats.getOperationStats(operation.getClass());
}
return lookupStats(operation.getClass()); // 頂層操作

實現 **同一請求內多 Servlet 調用的獨立統計** (如 Duke 書店所有頁面包含 BannerServlet)。

第一部分總結

  • 建立核心監控基礎設施:Servlet、JDBC 連線/Statement、巢狀統計、JMX 公開。
  • AspectJ 模組化優勢:精準切點、可擴展 Advice、關注點分離、零業務代碼侵入。
  • Worker Object 模式優雅解決上下文傳遞與巢狀關聯。
  • WeakIdentityHashMap 解決第三方 Proxy/Wrapper 物件身份追蹤難題。
  • 代碼簡潔、開銷可控、生產環境可用。

第二部分將擴展:多應用隔離、Struts/Spring MVC/WebService 監控、錯誤追蹤、執行時動態開關、錯誤隔離層、LTW 部署、效能基準測試。敬請期待!

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved