目錄
-
-
- 概述
- 監控普通的springboot應用
-
- admin server
- admin client
- 監控微服務
-
- eureka server
- 說明
-
大型分布式系統都應該提供監控功能,監控系統各部分的運作狀态。
監控的好處
- 便于檢視分布式系統各個節點的運作狀态,及時發現可能存在的隐患
- 系統故障時便于排查
- 可根據監控提供的qps、硬體使用情況等針對性地對系統進行優化
監控次元
- cpu、記憶體、硬碟、帶寬等硬體的使用情況
- db、redis、tomcat、kafka等元件的狀态、相關名額
- 接口qps、響應時間的95線|99線等應用本身的名額
springboot提供的actuator可以監控應用,但需要通路actuator相關接口檢視監控資訊,直接使用很麻煩。springboot admin內建了actuator,可以将actuator擷取到的監控資訊可視化地展示出來,直覺、友善。
springboot admin是codecentric公司的開源項目,并非springboot官方元件,分為server、client兩部分,被監控的springboot應用作為admin client,admin server提供web界面,可檢視監控資訊。
大公司往往都有自己的監控元件,對于小公司而言,springboot admin可以作為應用監控的一個不錯選擇。
依賴
建立項目時勾選
- Web -> Spring Web
- Security -> Spring Security
- I/O -> Java Mail Sender
- Ops -> Codecentric’s Spring Boot Admin(Server)
也可以手動添加依賴
<!-- 因為包含web界面,需要web的依賴-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 已經包含了spring-boot-starter-actuator -->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
</dependency>
<!-- 登入密碼 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- 非必需 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 郵件通知 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
引導類
加@EnableAdminServer
yml
server:
port: 7501
spring:
application:
name: springboot-admin-server
#指定admin server的使用者名、密碼
security:
user:
name: chy
password: abcd
#郵件伺服器配置
mail:
#郵件伺服器位址。qq是smtp.qq.com,163是smtp.163.com,阿裡雲是smtp.aliyun.com
host: smtp.qq.com
#賬号
username: [email protected]
#密碼(授權碼)
password: xxxxxxxx
#郵件通知配置
boot:
admin:
notify:
mail:
#發件郵箱,與上面配置的郵箱伺服器賬号保持一緻
from: [email protected]
#收件郵箱,有多個時逗号分隔
to: [email protected]
#抄送
cc: [email protected]
#指定郵件模闆,預設為 classpath:/META-INF/spring-boot-admin-server/mail/status-changed.html 可輕按兩下shift搜尋此檔案,copy到resources下修改
# template:
節點上線、下線都會自動發郵件通知收件人,開發環境下屏蔽收件人設定
配置類
config.SecuritySecureConfig
/**
* 配置security的登入驗證
*/
@Configuration
public class SecuritySecureConfig extends WebSecurityConfigurerAdapter {
private final String contextPath;
public SecuritySecureConfig(AdminServerProperties adminServerProperties) {
this.contextPath = adminServerProperties.getContextPath();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// 配置跨域,admin client注冊到admin server的/instances下
http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringAntMatchers(contextPath + "/instances");
// 配置靜态資源
http.authorizeRequests().antMatchers(contextPath + "/assets/**").permitAll();
// 所有請求都必須通過認證
http.authorizeRequests().anyRequest().authenticated();
// 登入登出的頁面配置
http.formLogin().loginPage("/login").permitAll();
http.logout().logoutUrl("/logout").logoutSuccessUrl("/login");
// 啟用basic認證
http.httpBasic();
}
}
- Ops -> Codecentric’s Spring Boot Admin(Client)
<!-- 已經包含了spring-boot-starter-actuator -->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
</dependency>
<!-- web項目,以維持運作狀态 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<property name="LOG_HOME" value="C:/Users/chy/Desktop/日志"/>
<!-- 指定彩色日志的渲染規則 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="wex"
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="wEx"
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
<!-- 指定彩色日志的格式,LN後面是行數 -->
<property name="CONSOLE_LOG_PATTERN"
value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:-}){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(LN:%L ){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<!-- 控制台輸出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!-- 引用日志格式 -->
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>utf8</charset>
</encoder>
</appender>
<!-- 每日檔案輸出 -->
<appender name="DAY_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志檔案名 -->
<FileNamePattern>${LOG_HOME}/user-server-%d{yyyy-MM-dd}.log</FileNamePattern>
<!-- 日志檔案保留天數 -->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!-- 指定格式:%d表示日期,%thread表示線程名,%-5level:級别從左顯示5個字元寬度%msg:日志消息,%n是換行符 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<!-- 日志檔案最大體積 -->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>500MB</MaxFileSize>
</triggeringPolicy>
</appender>
<!-- 輸出到指定檔案中 -->
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${LOG_HOME}/user-server-all.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!-- 指定格式:%d表示日期,%thread表示線程名,%-5level:級别從左顯示5個字元寬度%msg:日志消息,%n是換行符 -->
<!--<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>-->
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<!-- 預設輸出級别 -->
<root level="INFO">
<appender-ref ref="STDOUT"/>
<appender-ref ref="DAY_FILE"/>
<appender-ref ref="FILE"/>
</root>
<!-- 給特殊的包指定輸出級别 -->
<logger name="com.apache.ibatis" level="WARN" />
<logger name="java.sql.Connection" level="WARN" />
<logger name="java.sql.Statement" level="WARN" />
<logger name="java.sql.PreparedStatement" level="WARN" />
<logger name="java.sql.ResultSet" level="DEBUG" />
<logger name="com.alibaba.druid.pool.DruidPooledResultSet" level="ERROR" />
<logger name="org.apache.shiro" level="WARN" />
<logger name="springfox.documentation" level="WARN" />
</configuration>
注意:admin server、tail -f都可以顯示彩色日志,但使用記事本之類的普通文本閱讀器打開看到的是亂碼。
server:
port: 7502
spring:
application:
name: user-server
boot:
admin:
client:
#指定admin server的位址
url: http://localhost:7501
#如果admin server設定了密碼,admin client也要密碼才能注冊到admin server上
username: chy
password: abcd
#以ip注冊到admin server上,預設false使用hostname注冊
instance:
prefer-ip: true
management:
#暴露actuator的全部endpoint(即/actuator系列路徑),預設隻暴露少數endpoint
endpoints:
web:
exposure:
include: "*"
#顯示節點健康的具體資訊,/actuator/health預設隻傳回節點狀态(up|down),不傳回節點的具體資訊
endpoint:
health:
show-details: always
#指定日志檔案位置,要與logback中配置的日志檔案位置一緻,此處的檔案名不能使用%d{yyyy-MM-dd}之類的格式,識别不了
#會把此檔案中的日志傳輸到admin server,在admin server中也可以實時看到此應用的日志
logging:
file:
name: C:/Users/chy/Desktop/日志/user-server-all.log
admin server實時顯示日志需要滿足的條件
- 如果沒有logback的配置檔案,直接在yml中logging.file.name指定日志輸出位置即可
- 如果有logback的配置檔案,則yml中的logging.file.name必須和logback配置檔案中指定的日志檔案位置保持一緻
大體流程:所有服務(包括admin server)都作為eureka client注冊到eureka server上,并将狀态資訊傳給eureka server,admin server從eureka server拿各服務的狀态資訊。
就是一個普通的eureka server,不需要加額外的配置。
建立子產品時勾選 Spring Cloud Discovery -> Eureka Server ,也可以手動添加依賴
<!-- 已經包含了spring-boot-starter-actuator -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
加 @EnableEurekaServer
server:
port: 7500
spring:
application:
name: eureka-server
eureka:
instance:
#所在機器的hostname或者ip
hostname: 127.0.0.1
client:
#不注冊到其它eureka server上
registerWithEureka: false
#不從其它eureka server上拉取、同步注冊資訊
fetchRegistry: false
#此eureka server綁定的注冊中心位址
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
#日志檔案位置
logging:
file:
name: C:/Users/chy/Desktop/日志/eureka-server-all.log
建立子產品時勾選
- Spring Cloud Discovery -> Eureka Discovery Client
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- 非必需 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
加 @EnableAdminServer、@EnableEurekaClient
server:
port: 7501
spring:
application:
name: springboot-admin-server
#指定admin server的使用者名、密碼
security:
user:
name: chy
password: abcd
#郵件伺服器配置
mail:
#郵件伺服器位址。qq是smtp.qq.com,163是smtp.163.com,阿裡雲是smtp.aliyun.com
host: smtp.qq.com
#賬号
username: [email protected]
#密碼(授權碼)
password: xxxxxxxxx
boot:
admin:
#配置web路徑字首,值為網關路由中配置的admin-server子產品的路徑,預設路由為服務名。如果不通過網關通路,可不用配置
ui:
public-url: /admin-server
#郵件通知配置
notify:
mail:
#發件郵箱,與上面配置的郵箱伺服器賬号保持一緻
from: [email protected]
#收件郵箱,有多個時逗号分隔
to: [email protected]
# #抄送
cc: [email protected]
#郵件模闆
# template:
management:
#暴露actuator的全部endpoint
endpoints:
web:
exposure:
include: "*"
#顯示節點健康的具體資訊
endpoint:
health:
show-details: always
#日志檔案位置
logging:
file:
name: C:/Users/chy/Desktop/日志/springboot-admin-server-all.log
eureka:
instance:
#預設就是/actuator/health,可預設
#health-check-url-path: /actuator/health
#發送心跳包的時間間隔,預設30,開發、測試環境可設定小些
lease-renewal-interval-in-seconds: 10
#中繼資料
metadata-map:
user.name: ${spring.security.user.name}
user.password: ${spring.security.user.password}
client:
#ribbon更新節點清單的時間間隔,預設30,開發、測試環境可設定小些
registry-fetch-interval-seconds: 10
#注冊中心位址
service-url:
defaultZone: http://localhost:7500/eureka/
- admin server是從注冊中心拿各服務節點的狀态資訊,可以監測各個eureka client(包括 admin server本身)的狀态。
- 單機版eureka server是監測不到eureka server自身狀态的,eureka server叢集後,eureka server也會作為eureka client注冊到其它eureka server上,這時可以監測到eureka server的狀态。上面eureka server的yml中我沒有暴露eureka server自身的全部端點,需要的可以自己加上。
- 關于日志,通常不太關心eureka server、admin server自身的日志,是以我隻輸出到一個日志檔案中,沒有逐天輸出,需要的可以自行加上logback-spring.xml。
/**
* 配置security的登入驗證
*/
@Configuration
public class SecuritySecureConfig extends WebSecurityConfigurerAdapter {
private final String contextPath;
public SecuritySecureConfig(AdminServerProperties adminServerProperties) {
this.contextPath = adminServerProperties.getContextPath();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// 配置跨域,admin client注冊到admin server的/instances下
http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringAntMatchers(contextPath + "/instances");
// 配置靜态資源
http.authorizeRequests().antMatchers(contextPath + "/assets/**").permitAll();
// 所有請求都必須通過認證
http.authorizeRequests().anyRequest().authenticated();
// 登入登出的頁面配置
http.formLogin().loginPage("/login").permitAll();
http.logout().logoutUrl("/logout").logoutSuccessUrl("/login");
// 啟用basic認證
http.httpBasic();
}
}
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- 已經包含了spring-boot-starter-actuator -->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>2.3.1</version>
</dependency>
admin client的依賴都是公共依賴,很多服務中已經包含了這些公共依賴,基本不用添加admin client的依賴。
加不加 @EnableEurekaClient 均可
server:
port: 7502
spring:
application:
name: user-server
management:
#暴露actuator的全部endpoint
endpoints:
web:
exposure:
include: "*"
#顯示節點健康的具體資訊
endpoint:
health:
show-details: always
#指定日志檔案位置,要與logback中配置的日志檔案位置一緻
logging:
file:
name: C:/Users/chy/Desktop/日志/user-server-all.log
eureka:
instance:
#預設就是/actuator/health,可以預設
health-check-url-path: /actuator/health
#發送心跳包的時間間隔,預設30,開發、測試可設定小些
lease-renewal-interval-in-seconds: 10
client:
#ribbon更新節點清單的時間間隔,預設30,開發、測試環境可設定小些
registry-fetch-interval-seconds: 10
service-url:
defaultZone: http://localhost:7500/eureka/
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<property name="LOG_HOME" value="C:/Users/chy/Desktop/日志"/>
<!-- 指定彩色日志的渲染規則 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="wex"
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="wEx"
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
<!-- 指定彩色日志的格式,LN後面是行數 -->
<property name="CONSOLE_LOG_PATTERN"
value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:-}){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(LN:%L ){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<!-- 控制台輸出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!-- 引用日志格式 -->
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>utf8</charset>
</encoder>
</appender>
<!-- 每日檔案輸出 -->
<appender name="DAY_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志檔案名 -->
<FileNamePattern>${LOG_HOME}/user-server-%d{yyyy-MM-dd}.log</FileNamePattern>
<!-- 日志檔案保留天數 -->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!-- 指定格式:%d表示日期,%thread表示線程名,%-5level:級别從左顯示5個字元寬度%msg:日志消息,%n是換行符 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<!-- 日志檔案最大體積 -->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>500MB</MaxFileSize>
</triggeringPolicy>
</appender>
<!-- 輸出到指定檔案中 -->
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${LOG_HOME}/user-server-all.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!-- 指定格式:%d表示日期,%thread表示線程名,%-5level:級别從左顯示5個字元寬度%msg:日志消息,%n是換行符 -->
<!--<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>-->
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<!-- 預設輸出級别 -->
<root level="INFO">
<appender-ref ref="STDOUT"/>
<appender-ref ref="DAY_FILE"/>
<appender-ref ref="FILE"/>
</root>
<!-- 給特殊的包指定輸出級别 -->
<logger name="com.apache.ibatis" level="WARN" />
<logger name="java.sql.Connection" level="WARN" />
<logger name="java.sql.Statement" level="WARN" />
<logger name="java.sql.PreparedStatement" level="WARN" />
<logger name="java.sql.ResultSet" level="DEBUG" />
<logger name="com.alibaba.druid.pool.DruidPooledResultSet" level="ERROR" />
<logger name="org.apache.shiro" level="WARN" />
<logger name="springfox.documentation" level="WARN" />
</configuration>
1、像springboot admin這種第三方元件,等springboot新版本推出一段時候後才會慢慢适配,盡量不要使用很新的springboot版本。
2、@EnableAdminServer、@EnableHystrixDashboard 這2個注解有沖突,如果同時标在同一個引導類上,hystrix dashboard的靜态資源會404,盡量不要在同一個子產品中同時使用springboot admin、hystrix dashboard 2個監控。
3、內建spring security監控微服務這一塊,應用到生産中有很多坑,不一定非要內建內建spring security,可以走内網通路。