服務端性能監控—— Spring Boot Actuator介紹
監控後臺服務是否正常運行,有很多指標需要我們關注,一是機器本身的狀態,比如CPU利用率、磁盤使用率、內存、網絡等,通過這些來判斷機器是否運行正常。這些是屬於機器指標,一般雲服務商會提供。今天我們要分析的是程序的性能指標,因爲即使機器正常,但程序可能已經掛了。
對java程序來說,我們主要關注JVM的狀態是否正常,希望能把一般通過jconsole
得到的數據能通過監控自動獲取出趨勢圖。此時我們就需要一個非常強大的模塊:Spring Boot Actuator
來幫助獲取到應用的統計信息。Spring Boot Actuator
不止能提供jvm相關信息,也能對應用相關依賴做健康檢查,功能十分強大,接入非常簡單。
給一個Maven項目增加Actuator
使用如下依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
介紹Endpoints
Endpoints是Actuator中的端點,每個端點都提供了不同的功能,Actuator內置了很多Endpoints,配置就可以使用。
如/health
提供了應用健康信息。
/info
提供了應用基本信息。
/logfile
可以直接查看日誌文件等等。
同時我們也可以定義自己的Endpoints,以此來自定義想要的監控項。
查看所有endpoints
啓動項目,訪問http://localhost:8080/actuator查看,你應該能看到如下列表
{
"_links":{
"self":{
"href":"http://localhost:7777/actuator",
"templated":false
},
"auditevents":{
"href":"http://localhost:7777/actuator/auditevents",
"templated":false
},
"health":{
"href":"http://localhost:7777/actuator/health",
"templated":false
},
"env":{
"href":"http://localhost:7777/actuator/env",
"templated":false
}
}
}
訪問/actuator獲取到的是當前已開啓的endpoints列表,有一些文檔說很多endpoints是默認開啓的,但從Spring Boot2.0之後,因爲安全原因,大部分的endpoints都是默認關閉的了,需要在配置文件中手動開啓。
配置endpoints的開關
在配置文件中,可以通過include
和exclude
配置endpoint在http或jmx中是否開啓或關閉,如下。
management:
endpoints:
web:
exposure:
exclude: shutdown
include: ["auditevents", "info", "health", "metrics", "loggers", "logfile", "httptrace", "env", "flyway", "mappings",
"scheduledtasks", "prometheus"]
jmx:
exposure:
include: * #所有
這樣就能在/actuator
頁面看到大多數的endpoints了。
重要的endpoint
id | desc |
---|---|
auditevents |
顯示當前應用程序的審計事件信息 |
beans |
顯示應用Spring Beans的完整列表 |
caches |
顯示可用緩存信息 |
conditions |
顯示自動裝配類的狀態及及應用信息 |
configprops |
顯示所有 @ConfigurationProperties 列表 |
env |
顯示 ConfigurableEnvironment 中的屬性 |
flyway |
顯示 Flyway 數據庫遷移信息 |
health |
顯示應用的健康信息(未認證只顯示status ,認證顯示全部信息詳情) |
info |
顯示任意的應用信息(在資源文件寫info.xxx即可) |
liquibase |
展示Liquibase 數據庫遷移 |
metrics |
展示當前應用的 metrics 信息 |
mappings |
顯示所有 @RequestMapping 路徑集列表 |
scheduledtasks |
顯示應用程序中的計劃任務 |
sessions |
允許從Spring會話支持的會話存儲中檢索和刪除用戶會話。 |
shutdown |
允許應用以優雅的方式關閉(默認情況下不啓用) |
threaddump |
執行一個線程dump |
httptrace |
顯示HTTP跟蹤信息(默認顯示最後100個HTTP請求 - 響應交換) |
/actuator/httptrace
可以查看近期的請求詳細數據,比如參數、cookie等
####/actuator/scheduledtasks
顯示定時任務列表
{
"cron": [
{
"runnable": {
"target": "com.test.test.test.test.test.refresh"
},
"expression": " 0 0 0 1 1/1 ? "
}
],
"fixedDelay": [],
"fixedRate": [],
"custom": []
}
/actuator/mappings
顯示所有的@RequestMapping 路徑
/actuator/metrics
顯示metrics數據。
/actuator/health
health是比較重要的一個endpoint,因爲它本身自帶了許多健康檢查,可以對我們的線上監控起到非常重要的作用。
/health默認只返回一個簡單的UP
或DOWN
的status信息,想要看到全部數據,需要修改xml配置。
management:
endpoint:
health:
show-details: always #展示所有細節內容
這樣我們訪問就可以看到如下信息
// 省略了一些detail信息
{
"status":"UP",
"details":{
"db":{
"status":"UP",
"details":{
"dataSource":{
"status":"UP"
}
}
},
"refreshScope":{
"status":"UP"
},
"discoveryComposite":{
"status":"UP",
"details":{
"discoveryClient":{
"status":"UP",
"details":{
}
},
"eureka":{
"description":"Remote status from Eureka server",
"status":"UNKNOWN",
"details":{
}
}
}
},
"redis":{
"status":"UP",
"details":{
"version":"2.8.13"
}
}
}
}
可以看到db 、redis、eureka等許多重要依賴的健康信息。如果其中有一個爲DOWN,那麼應用的整體狀態就是DOWN。
我們之所以能看到這些信息的原理是它們都實現了HealthIndicator
接口,會返回自身的健康狀態,如果我們需要定義自定義的健康指標的話,也是需要實現這個接口或繼承AbstractHealthIndicator
,重寫其中的doHealthCheck
方法,後面會會講解這種方式。
已經實現這個接口的有
名稱 | 描述 |
---|---|
CassandraHealthIndicator |
檢查 Cassandra 數據庫是否啓動。 |
DiskSpaceHealthIndicator |
檢查磁盤空間不足。 |
DataSourceHealthIndicator |
檢查是否可以獲得連接 DataSource 。 |
ElasticsearchHealthIndicator |
檢查 Elasticsearch 集羣是否啓動。 |
InfluxDbHealthIndicator |
檢查 InfluxDB 服務器是否啓動。 |
JmsHealthIndicator |
檢查 JMS 代理是否啓動。 |
MailHealthIndicator |
檢查郵件服務器是否啓動。 |
MongoHealthIndicator |
檢查 Mongo 數據庫是否啓動。 |
Neo4jHealthIndicator |
檢查 Neo4j 服務器是否啓動。 |
RabbitHealthIndicator |
檢查 Rabbit 服務器是否啓動。 |
RedisHealthIndicator |
檢查 Redis 服務器是否啓動。 |
SolrHealthIndicator |
檢查 Solr 服務器是否已啓動。 |
自定義健康指標
比如我的項目中,並沒有用es默認的client,而是自己去創建一個es的RestLowLevelClientt
,以此來跳過https證書檢查。這樣我就沒有辦法使用ElasticsearchHealthIndicator
,因爲它肯定會一直返回down,只能自己實現一個HealthIndicator接口或繼承AbstractHealthIndicator
類。如下代碼(檢查邏輯是參照的ElasticsearchHealthIndicator
)
public class EsRestLowLevelClientHealthIndicator extends AbstractHealthIndicator {
private static final String RED_STATUS = "red";
private final JsonParser jsonParser;
private RestLowLevelClient restLowLevelClient;
@Autowired
public EsRestLowLevelClientHealthIndicator(RestLowLevelClient restLowLevelClient) {
this.restLowLevelClient = restLowLevelClient;
this.jsonParser = JsonParserFactory.getJsonParser();;
}
@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {
Response response = this.restLowLevelClient.performRequest(new Request("GET", "/_cluster/health/"));
StatusLine statusLine = response.getStatusLine();
if (statusLine.getStatusCode() != 200) {
builder.down();
builder.withDetail("statusCode", statusLine.getStatusCode());
builder.withDetail("reasonPhrase", statusLine.getReasonPhrase());
} else {
InputStream inputStream = response.getEntity().getContent();
Throwable var5 = null;
try {
this.doHealthCheck(builder, StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8));
} catch (Throwable var14) {
var5 = var14;
throw var14;
} finally {
if (inputStream != null) {
if (var5 != null) {
try {
inputStream.close();
} catch (Throwable var13) {
var5.addSuppressed(var13);
}
} else {
inputStream.close();
}
}
}
}
}
private void doHealthCheck(Health.Builder builder, String json) {
Map<String, Object> response = this.jsonParser.parseMap(json);
String status = (String)response.get("status");
if (RED_STATUS.equals(status)) {
builder.outOfService();
} else {
builder.up();
}
builder.withDetails(response);
}
}
這個類加載到Spring中,在訪問/actuator/health
時就會得到如下信息。
{
"status":"UP",
"details":{
"esRestLowLevelClient":{
"status":"UP",
"details":{
"cluster_name":"shark",
"status":"yellow",
"timed_out":false,
"number_of_nodes":26,
"number_of_data_nodes":26,
"active_primary_shards":10009,
"active_shards":20105,
"relocating_shards":0,
"initializing_shards":0,
"unassigned_shards":14,
"delayed_unassigned_shards":0,
"number_of_pending_tasks":0,
"number_of_in_flight_fetch":0,
"task_max_waiting_in_queue_millis":0,
"active_shards_percent_as_number":99.93041403648293
}
}
}
}
可以看到我們自定義的esRestLowLevelClient
指標爲UP狀態。
通過/actuator/health
,我們可以寫一個定時器對應用做黑盒監控,判斷返回值是否爲UP,否則報警,就可以很容易地對應用和依賴做出監控了。
結語
上面主要介紹了Spring Boot Actuator
的作用和用法,可以看出它是一個開箱即用、功能強大的組件,除了上面介紹了的還有修改日誌等級、管理session等功能,大家可以嘗試加入到自己項目中,能大大地提高監控效率。下一篇我們會分享如何把jvm監控數據展示到Grafana中,得到詳細的性能監控圖表。如下圖