Undertow 介紹
Undertow 是 Red Hat 開發的一款高性能、靈活的 Java Web 服務器,也是 WildFly 應用服務器的嵌入式組件。它支持非阻塞 I/O,基於 NIO 構建,並提供了 HTTP/2、WebSockets 和 Servlet 4.0 等現代 Web 技術支持。Undertow 以其輕量級、嵌入式友好 的特性而聞名,開發者可以輕鬆將其集成到自己的應用程序中,也可以作為獨立服務器運行。它的模塊化設計允許用户按需選擇所需功能,從而實現低資源佔用和高吞吐量。
Undertow 可觀測性在現代應用中至關重要。APM 雖能展示 HTTP 請求的端到端耗時,但它們無法直接揭示 Undertow 內部處理請求的細節。
Undertow 線程池配置不當可能導致:
- 請求排隊:線程不足時,新請求等待處理,APM 中表現為 HTTP 請求耗時增加。
- 資源浪費或瓶頸轉移:線程過多會增加上下文切換開銷,甚至將壓力轉嫁給下游服務。
因此,監控 Undertow 的 XNIO Worker 線程數、活躍線程數、任務隊列大小等指標,能有效識別請求處理瓶頸,確保系統高效穩定運行。
觀測雲
觀測雲是一款專為 IT 工程師打造的全鏈路可觀測產品,它集成了基礎設施監控、應用程序性能監控和日誌管理,為整個技術棧提供實時可觀察性。這款產品能夠幫助工程師全面瞭解端到端的用户體驗追蹤,瞭解應用內函數的每一次調用,以及全面監控雲時代的基礎設施。此外,觀測雲還具備快速發現系統安全風險的能力,為數字化時代提供安全保障。
部署 DataKit
DataKit 是一個開源的、跨平台的數據收集和監控工具,由觀測雲開發並維護。它旨在幫助用户收集、處理和分析各種數據源,如日誌、指標和事件,以便進行有效的監控和故障排查。DataKit 支持多種數據輸入和輸出格式,可以輕鬆集成到現有的監控系統中。
登錄觀測雲控制枱,在「集成」 - 「DataKit」選擇對應安裝方式,當前採用 Linux 主機部署 DataKit。
採集器配置
DataKit 配置
DataKit 安裝完成後,可以自定義開啓採集器,本集成需要開啓如下兩個採集器。
開啓 StatsD 採集器
# 開啓採集器
cp /usr/local/datakit/conf.d/statsd/statsd.conf.sample /usr/local/datakit/conf.d/statsd/statsd.conf
# 重啓 Datakit
datakit service -R
開啓鏈路採集
# 開啓採集器
cp /usr/local/datakit/conf.d/ddtrace/ddtrace.conf.sample /usr/local/datakit/conf.d/ddtrace/ddtrace.conf
# 重啓 Datakit
datakit service -R
客户端配置
場景環境:
jdk: 1.8.0_361
spring-boot: 2.7.12-SNAPSHOT
undertow:2.2.24.Final
備註: 不同版本指標可能會有差異。
以 Java Demo 應用為例,使用 undertow 作為 web 容器配置。
##啓用 Undertow pom 配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
Demo 項目中 undertow 運行配置如下:
server.port=8080
server.undertow.threads.worker=10
server.undertow.threads.io=2
接入 APM ,配置採集 jmx ,應用啓動增加如下參數,啓動命令如下:
java \
-javaagent:/xxx/dd-java-agent.jar \
-Ddd.agent.port=9529 \
-Ddd.service=demo \
-Ddd.jmxfetch.check-period=1000 \
-Ddd.jmxfetch.enabled=true \
-Ddd.jmxfetch.config.dir=/xxx/ \
-Ddd.jmxfetch.config=undertow.yaml \
-jar xxxx.jar
dd-java-agent.jar Guance 版下載地址:
wget -O dd-java-agent.jar 'https://static.guance.com/dd-image/dd-java-agent.jar'
其中 -Ddd.jmxfetch.config.dir 和 -Ddd.jmxfetch.config=undertow.yaml 需要把 undertow.yaml 放到 Java 啓動可以讀取到的地址。
undertow.yaml 內容如下,無需修改。
init_config:
instances:
- jvm_direct: true
name: undertow-monitoring
collect_default_jvm_metrics: false
collect_default_metrics: false
refresh_beans: 60
conf:
- include:
bean_regex: "org.xnio:type=Xnio,provider=\"nio\",worker=\"XNIO-.*\""
attribute:
IoThreadCount:
metric_type: gauge
alias: undertow.io.thread.count
- include:
bean_regex: "jboss.threads:name=\"XNIO-.*\",type=thread-pool"
attribute:
CorePoolSize:
metric_type: gauge
alias: undertow.core.pool.size
MaximumPoolSize:
metric_type: gauge
alias: undertow.max.pool.size
ActiveCount:
metric_type: gauge
alias: undertow.active.count
LargestPoolSize:
metric_type: gauge
alias: undertow.largest.pool.size
CompletedTaskCount:
metric_type: gauge
alias: undertow.completed.task.count
PoolSize:
metric_type: gauge
alias: undertow.pool.size
GrowthResistance:
metric_type: gauge
alias: undertow.growth.resistance
MaximumQueueSize:
metric_type: gauge
alias: undertow.max.queue.size
LargestQueueSize:
metric_type: gauge
alias: undertow.largest.queue.size
SubmittedTaskCount:
metric_type: gauge
alias: undertow.submitted.task.count
RejectedTaskCount:
metric_type: gauge
alias: undertow.rejected.task.count
SpinMissCount:
metric_type: gauge
alias: undertow.spin.miss.count
QueueSize:
metric_type: gauge
alias: undertow.queue.size
KeepAliveTimeSeconds:
metric_type: gauge
alias: undertow.keep.alive.time.seconds
關鍵指標
指標集:undertow
| 指標 | 描述 | 用途 |
|---|---|---|
| active_count | 活躍線程數 | 當前線程池中正在執行任務的線程數量。 |
| completed_task_count | 已完成任務數 | 線程池自啓動以來已完成的任務總數。 |
| core_pool_size | 核心線程池大小 | 線程池中始終保持活動的線程數,即使它們處於空閒狀態。 |
| io_thread_count | I/O 線程數 | Undertow 底層 XNIO 框架用於處理網絡 I/O 事件(如接受連接、讀寫數據)的線程數量。 |
| keep_alive_time_seconds | 線程保持活躍時間 | 當線程數超過核心線程數時,多餘的空閒線程在被終止前可以等待的時間。 |
| largest_pool_size | 歷史最大線程池大小 | 線程池自啓動以來達到的最大線程數量。 |
| largest_queue_size | 歷史最大隊列大小 | 任務隊列自啓動以來達到的最大任務數量。 |
| max_pool_size | 最大線程池大小 | 線程池允許創建的最大線程數量。這是一個關鍵的配置參數,限制了併發處理能力。 |
| max_queue_size | 最大隊列大小 | 任務隊列可以容納的最大任務數量。 |
| pool_size | 當前線程池大小 | 當前線程池中的總線程數量(包括活躍和空閒線程)。 |
| queue_size | 當前隊列大小 | 當前在任務隊列中等待被執行的任務數量。持續增長通常表示處理能力不足。 |
| rejected_task_count | 被拒絕任務數 | 由於線程池已滿(線程數達到最大且隊列已滿)或拒絕策略觸發,而被拒絕執行的任務數量。這是一個重要的過載指標。 |
場景視圖
登錄觀測雲控制枱,點擊「場景」 -「新建儀表板」,輸入 “Undertow”, 選擇 “Undertow監控視圖”,點擊 “確定” 即可添加視圖。
監控器(告警)
Undertow 排隊請求數監控
簡要描述:檢測指標 queue_size , 5分鐘內超過100觸發告警,如下圖:
Undertow 線程池使用率監控
簡要描述:檢測指標 pool_size/max_pool_size , 5分鐘內超過90% 觸發告警,如下圖:
總結
這些指標提供了 Undertow 線程池運行狀態的全面視圖,幫助開發者和運維人員監控和優化線程池的性能。通過合理配置和監控這些指標,可以確保線程池在高併發場景下高效運行,同時避免資源浪費和性能瓶頸。