??<前文回顧>
<今日更新>
一、引子:監控這事兒,不能光靠“瞅”
咱們搞開發的,最怕的就是系統出問題,結果自己還蒙在鼓里。你說你寫的代碼,跑得好好的,突然就“拉胯”了,用戶那邊嗷嗷叫,你這邊還一臉懵。這不就跟“瞎子摸象”似的,摸到哪兒算哪兒,最后還得靠運氣。所以啊,監控這事兒,不能光靠“瞅”,得有點真家伙。
Spring Boot 里頭有個叫 Actuator 的玩意兒,專門用來監控應用的健康狀態。這玩意兒就跟“千里眼”似的,能讓你一眼瞅見系統里頭哪兒不對勁。今兒個咱就嘮嘮,咋用 Actuator 實現健康檢查。
二、Actuator 是啥?能吃嗎?
Actuator 是 Spring Boot 提供的一個模塊,專門用來監控和管理應用。它提供了一堆端點(Endpoint),通過這些端點,你可以查看應用的運行狀態、健康情況、內存使用情況等等。說白了,就是給你開了個“后門”,讓你能隨時“偷窺”系統的內部情況。
Actuator 的核心功能包括:
- 健康檢查(Health Check)
- 指標收集(Metrics)
- 環境信息(Environment)
- 線程信息(Thread Dump)
- 日志管理(Loggers)
這些功能就跟“工具箱”似的,里頭啥都有,隨用隨取。今兒個咱主要嘮嘮健康檢查這塊兒。
三、健康檢查:別等“病入膏肓”才想起來治
健康檢查是 Actuator 里頭最常用的功能之一。它能告訴你應用現在是“生龍活虎”還是“病入膏肓”。你可能會說,這不就跟“體檢”似的嗎?沒錯,就是體檢。不過這個體檢是實時的,隨時都能做。
1. 咋啟用 Actuator?
首先,你得在?pom.xml?里頭加上 Actuator 的依賴:
XML Code |
<dependency> ????<groupId>org.springframework.boot</groupId> ????<artifactId>spring-boot-starter-actuator</artifactId> </dependency> |
加完依賴,啟動應用,Actuator 就自動啟用了。默認情況下,Actuator 的端點是通過 HTTP 暴露的,你可以通過?/actuator?路徑訪問這些端點。
2. 健康檢查端點
健康檢查的端點是?/actuator/health。你可以在瀏覽器里訪問這個端點,或者用?curl?命令:
bash Code |
curl http://localhost:8080/actuator/health |
返回的結果大概是這樣的:
JSON Code |
{ ????"status": "UP" } |
這個?status?字段告訴你應用的健康狀態。UP?表示應用正常,DOWN?表示應用掛了。
3. 自定義健康檢查
默認的健康檢查只能告訴你應用是不是還活著,但有時候你需要的不僅僅是“活著”。比如,你可能想知道數據庫連接是不是正常,磁盤空間是不是夠用,外部服務是不是能訪問。這時候,你就得自定義健康檢查了。
Spring Boot 提供了一個?HealthIndicator?接口,你可以實現這個接口,自定義健康檢查的邏輯。比如,你想檢查數據庫連接是不是正常,可以這么寫:
Java Code |
import org.springframework.boot.actuate.health.Health; import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.stereotype.Component; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; @Component public class DatabaseHealthIndicator implements HealthIndicator { ????@Override ????public Health health() { ????????try (Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password")) { ????????????if (connection.isValid(1)) { ????????????????return Health.up().build(); ????????????} else { ????????????????return Health.down().withDetail("Error", "Database connection is invalid").build(); ????????????} ????????} catch (SQLException e) { ????????????return Health.down(e).build(); ????????} ????} } |
這個?DatabaseHealthIndicator?類實現了?HealthIndicator?接口,檢查數據庫連接是不是正常。如果連接正常,返回?UP,否則返回?DOWN。
4. 健康檢查的坑
自定義健康檢查雖然好用,但也有坑。最大的坑就是健康檢查的邏輯不能太復雜,否則會影響應用的性能。比如,你要是每次健康檢查都去連接數據庫,那數據庫的壓力可就大了。所以,健康檢查的邏輯要盡量簡單,別整得太復雜。
另外,健康檢查的結果是緩存的,默認情況下,緩存時間是 10 秒。也就是說,你改了健康檢查的邏輯,得等 10 秒才能看到效果。你要是覺得 10 秒太長,可以通過配置改:
Yml Code |
management: ??endpoint: ????health: ??????cache: ????????time-to-live: 1s |
這個配置把緩存時間改成了 1 秒。
四、其他端點:別光盯著健康檢查
Actuator 里頭不光有健康檢查,還有其他一堆端點。這些端點就跟“工具箱”里的其他工具似的,各有各的用處。
1. 指標收集(Metrics)
指標收集的端點是?/actuator/metrics。這個端點能告訴你應用的各項指標,比如內存使用情況、CPU 使用情況、請求次數等等。你可以通過這個端點,實時監控應用的性能。
bash Code |
curl http://localhost:8080/actuator/metrics |
返回的結果大概是這樣的:
JSON Code |
{ ????"names": [ ????????"jvm.memory.max", ????????"jvm.memory.used", ????????"jvm.threads.live", ????????"http.server.requests" ????] } |
你可以通過?/actuator/metrics/{metricName}?查看具體的指標。比如,查看內存使用情況:
bash Code |
curl http://localhost:8080/actuator/metrics/jvm.memory.used |
2. 環境信息(Environment)
環境信息的端點是?/actuator/env。這個端點能告訴你應用的環境變量、配置文件里的配置項等等。你可以通過這個端點,查看應用的配置是不是正確。
bash Code |
curl http://localhost:8080/actuator/env |
返回的結果大概是這樣的:
JSON Code |
{ ????"activeProfiles": [], ????"propertySources": [ ????????{ ????????????"name": "server.ports", ????????????"properties": { ????????????????"local.server.port": { ????????????????????"value": 8080 ????????????????} ????????????} ????????}, ????????{ ????????????"name": "applicationConfig: [classpath:/application.yml]", ????????????"properties": { ????????????????"management.endpoint.health.cache.time-to-live": { ????????????????????"value": "1s" ????????????????} ????????????} ????????} ????] } |
3. 線程信息(Thread Dump)
線程信息的端點是?/actuator/threaddump。這個端點能告訴你應用的所有線程的狀態。你可以通過這個端點,查看應用是不是有線程死鎖、線程阻塞等問題。
bash Code |
curl http://localhost:8080/actuator/threaddump |
返回的結果大概是這樣的:
JSON Code |
{ ????"threads": [ ????????{ ????????????"threadName": "main", ????????????"threadId": 1, ????????????"blockedCount": 0, ????????????"blockedTime": -1, ????????????"waitedCount": 0, ????????????"waitedTime": -1, ????????????"lockName": null, ????????????"lockOwnerId": -1, ????????????"lockOwnerName": null, ????????????"inNative": false, ????????????"suspended": false, ????????????"threadState": "RUNNABLE", ????????????"stackTrace": [ ????????????????{ ????????????????????"className": "java.lang.Thread", ????????????????????"methodName": "sleep", ????????????????????"fileName": "Thread.java", ????????????????????"lineNumber": -2, ????????????????????"nativeMethod": true ????????????????} ????????????], ????????????"lockedMonitors": [], ????????????"lockedSynchronizers": [], ????????????"lockInfo": null ????????} ????] } |
4. 日志管理(Loggers)
日志管理的端點是?/actuator/loggers。這個端點能告訴你應用的日志配置。你可以通過這個端點,動態修改日志級別。
bash Code |
curl http://localhost:8080/actuator/loggers |
返回的結果大概是這樣的:
JSON Code |
{ ????"levels": [ ????????"OFF", ????????"ERROR", ????????"WARN", ????????"INFO", ????????"DEBUG", ????????"TRACE" ????], ????"loggers": { ????????"ROOT": { ????????????"configuredLevel": "INFO", ????????????"effectiveLevel": "INFO" ????????}, ????????"com.example": { ????????????"configuredLevel": null, ????????????"effectiveLevel": "INFO" ????????} ????} } |
你可以通過?/actuator/loggers/{loggerName}?修改某個 Logger 的日志級別。比如,把?com.example?的日志級別改成?DEBUG:
bash Code |
curl -X POST http://localhost:8080/actuator/loggers/com.example -H "Content-Type: application/json" -d '{"configuredLevel": "DEBUG"}' |
五、安全性:別讓人“偷家”
Actuator 的端點雖然好用,但也有安全隱患。你要是把這些端點暴露在外網,那可就相當于“開門揖盜”了。所以,你得做好安全措施。
1. 只暴露必要的端點
默認情況下,Actuator 只暴露了?/actuator/health?和?/actuator/info?兩個端點。你可以通過配置,暴露其他端點:
Yml Code |
management: ??endpoints: ????web: ??????exposure: ????????include: "*" |
這個配置暴露了所有端點。你要是覺得不安全,可以只暴露必要的端點:
Yml Code |
management: ??endpoints: ????web: ??????exposure: ????????include: "health,info,metrics" |
2. 啟用安全認證
你可以通過 Spring Security 啟用安全認證,保護 Actuator 的端點。比如,你可以配置一個簡單的 HTTP Basic 認證:
Java Code |
import org.springframework.context.annotation.Bean; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.provisioning.InMemoryUserDetailsManager; @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { ????@Override ????protected void configure(HttpSecurity http) throws Exception { ????????http ????????????.authorizeRequests() ????????????????.antMatchers("/actuator/**").authenticated() ????????????????.and() ????????????.httpBasic(); ????} ????@Bean ????@Override ????public UserDetailsService userDetailsService() { ????????UserDetails user = User.withDefaultPasswordEncoder() ????????????.username("admin") ????????????.password("password") ????????????.roles("USER") ????????????.build(); ????????return new InMemoryUserDetailsManager(user); ????} } |
這個配置啟用了 HTTP Basic 認證,只有用戶名是?admin,密碼是?password?的用戶才能訪問 Actuator 的端點。
專有名詞解釋
- Actuator:Spring Boot 提供的一個模塊,用于監控和管理應用。
- HealthIndicator:Spring Boot 提供的一個接口,用于自定義健康檢查的邏輯。
- Metrics:Spring Boot 提供的指標收集功能,用于監控應用的性能。
- Environment:Spring Boot 提供的環境信息功能,用于查看應用的環境變量和配置項。
- Thread Dump:Spring Boot 提供的線程信息功能,用于查看應用的所有線程的狀態。
- Loggers:Spring Boot 提供的日志管理功能,用于查看和修改應用的日志配置。
寫在最后
身為一個中古程序猿,我有很多自己想做的事情,比如埋頭苦干手搓一個低代碼數據庫設計平臺(目前只針對寫java的朋友),已經在找朋友內測了,比如很喜歡幫身邊的朋友看看簡歷,講講面試技巧,畢竟工作這么多年,也做到過高管,有很多面人經歷,意見還算有用,大家基本都能拿到想要的offer...
我深刻意識到,能自由做自己喜歡的事情是有多么不容易,又是多么有成就感。所以我拉了兩三個志同道合的好友,開了一間公司,繼續朝著“自由”的目標前進。
當下呢,我們希望有更多的朋友能夠參與到產品的測試中來,體驗并且給出更好的建議。未來可能會在博客po更多關于我們產品的內容,包括使用場景、說明、課程等,希望能對大家有所幫助。
另外,想整個花活兒,每天花個1-2小時,來幫助我素未謀面的老朋友們看看簡歷,提提意見啥的,純屬為愛發電。我在線時間不固定,但是不要米,咱就別要自行車兒了唄~如果您有興趣,可以點擊文章底部卡片一起交流(人工回復,比較慢,請擔待)。
最后,請大家持續關注我們的博客,未來還有很多欄目,一起發掘~!
(來呀~↓↓↓~老鐵)