## Actuator 监控
Spring Boot 使用“习惯优于配置的理念”,采用包扫描和自动化配置的机制来加载依赖 Jar 中的 Spring bean,不需要任何 Xml 配置,就可以实现 Spring 的所有配置。虽然这样做能让我们的代码变得非常简洁,但是整个应用的实例创建和依赖关系等信息都被离散到了各个配置类的注解上,这使得我们分析整个应用中资源和实例的各种关系变得非常的困难。
Actuator 是 Spring Boot 提供的对应用系统的自省和监控的集成功能,可以查看应用配置的详细信息,例如自动化配置信息、创建的 Spring beans 以及一些环境属性等。
为了保证 actuator 暴露的监控接口的安全性,需要添加安全控制的依赖spring-boot-start-security依赖,访问应用监控端点时,都需要输入验证信息。Security 依赖,可以选择不加,不进行安全管理,但不建议这么做。
# Actuator 的 REST 接口
Actuator 监控分成两类:原生端点和用户自定义端点;自定义端点主要是指扩展性,用户可以根据自己的实际应用,定义一些比较关心的指标,在运行期进行监控。
原生端点是在应用程序里提供众多 Web 接口,通过它们了解应用程序运行时的内部状况。原生端点又可以分成三类:
应用配置类:可以查看应用在运行期的静态信息:例如自动配置信息、加载的 springbean 信息、yml 文件配置信息、环境信息、请求映射信息;
度量指标类:主要是运行期的动态信息,例如堆栈、请求连、一些健康指标、metrics 信息等;
操作控制类:主要是指 shutdown,用户可以发送一个请求将应用的监控功能关闭。
Actuator 提供了 13 个接口,具体如下表所示。

## 上手
加入jar
```
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
```
配置文件
```
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always
#management.endpoints.web.base-path=/monitor
management.endpoint.shutdown.enabled=true
```
配置文件解释:
* management.endpoints.web.exposure.include=* 打开全部
* management.endpoint.shutdown.enabled=true 启用接口关闭 Spring Boot
* management.endpoint.health.show-details 的值为always 可以查看详细的应用健康信息,配置之后我们再次访http://127.0.0.1:8080/actuator/health 获得信息
* management.endpoints.web.base-path=/monitor 代表启用单独的url地址来监控 Spring Boot 应用,为了安全一般都启用独立的端口来访问后端的监控信息
## 什么是 Spring Boot Admin?
Spring Boot Admin 是一个管理和监控 Spring Boot 应用程序的开源软件。每个应用都认为是一个客户端,通过 HTTP 或者使用 Eureka 注册到 admin server 中进行展示,Spring Boot Admin UI 部分使用 VueJs 将数据展示在前端。
#### bug提醒:spring-boot-admin 2.1.6与springboot目前最新版2.2.6整合有一些不兼容 如图:

关于springbootadmin2.1.6出现的adminHandlerMapping问题:[官方讨论地址](https://github.com/codecentric/spring-boot-admin/issues?q=adminHandlerMapping)
# 上手
### 依赖版本:
```
spring-boot 2.1.0
eureka-server 2.1.0
spring-boot-admin 2.1.6
```
### 项目结构

### 建立父工程springbootadmin
主要依赖
```
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
```
### 建立eureka-server(端口:8080) eureka-servertow端口:8081)实现高可用
主要依赖
```
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
```
启动类中添加注释 `@EnableEurekaServer`
```
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
```
配置Security
```
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
//spring security csrf (跨域保护)关闭
http.csrf().disable();
super.configure(http);
}
}
```
配置application.yml
```
server:
port: 8081
spring:
application:
name: eureka-server
security:
user:
name: "admin"
password: "admin"
eureka:
instance:
hostname: localhost
health-check-url-path: /actuator/health
prefer-ip-address: true #如果设置了eureka.instance.ip-address 属性,则使用该属性配置的IP
metadata-map:
startup: ${random.int} #需要在重启后触发信息和端点更新
#如果springbootadmin配置了security需要在这里添加用户名和密码
user.name: ${spring.security.user.name}
user.password: ${spring.security.user.password}
client:
service-url:
startup: ${random.int} #需要在重启后触发信息和端点更新
#因为eureka配置了security需要在url上面带上用户名和密码
defaultZone: http://admin:admin@${eureka.instance.hostname}:8080/eureka/,http://admin:admin@${eureka.instance.hostname}:8081/eureka/
register-with-eureka: true # 是否拉取其它服务的信息,默认是true,如果是单个EurekaServer为false
fetch-registry: true # 是否注册自己的信息到EurekaServer,默认是true,如果是单个EurekaServer为false
server:
enable-self-preservation: false # 关闭自我保护模式(缺省为打开)
eviction-interval-timer-in-ms: 1000 # 扫描失效服务的间隔时间(缺省为60*1000ms)
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: ALWAYS
```
eureka-servertow的application.yml唯一区别在于一个端口
关于eureka以后会出相关文章
### 创建admin-server
主要依赖
```
<!-- spring-boot-admin服务端 -->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>2.1.6</version>
</dependency>
<!-- spring-boot-adminUI -->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-server-ui</artifactId>
<version>2.1.6</version>
</dependency>
```
启动类中添加注释 `@EnableAdminServer` ` @EnableEurekaClient`
```
@SpringBootApplication
@EnableAdminServer
@EnableEurekaClient
public class AdminServerApplication{
public static void main(String[] args) {
SpringApplication.run(AdminServerApplication.class, args);
}
}
```
配置Security
```
public class SecuritySecureConfig extends WebSecurityConfigurerAdapter {
private final String adminContextPath;
public SecuritySecureConfig(AdminServerProperties adminServerProperties) {
this.adminContextPath = adminServerProperties.getContextPath();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
successHandler.setTargetUrlParameter("redirectTo");
successHandler.setDefaultTargetUrl(adminContextPath + "/");
http.authorizeRequests()
.antMatchers(adminContextPath + "/assets/**").permitAll()
.antMatchers(adminContextPath + "/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and()
.logout().logoutUrl(adminContextPath + "/logout").and()
.httpBasic().and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringAntMatchers(
adminContextPath + "/instances",
adminContextPath + "/actuator/**"
);
// @formatter:on
}
}
```
配置application.yml
```
server:
port: 9091
#设置security
spring:
application:
name: admin-server
security:
user:
name: "admin"
password: "admin"
#配置eureka
eureka:
instance:
leaseRenewalIntervalInSeconds: 10 #eurek心跳
health-check-url-path: /actuator/health #健康检查页面的URL,相对路径,默认使用 HTTP 访问,如果需要使用 HTTPS则需要使用绝对路径配置
prefer-ip-address: true #如果设置了eureka.instance.ip-address 属性,则使用该属性配置的IP
metadata-map:
startup: ${random.int} #需要在重启后触发信息和端点更新
user.name: ${spring.security.user.name}
user.password: ${spring.security.user.password}
hostname: localhost
client:
registryFetchIntervalSeconds: 5 # 从eureka服务器注册表中获取注册信息的时间间隔(s),默认为30秒
serviceUrl:
defaultZone: http://admin:admin@${eureka.instance.hostname}:8080/eureka/,http://admin:admin@${eureka.instance.hostname}:8081/eureka/
# 开放所有endpoint,实际生产根据自身需要开放,出于安全考虑不建议全部开放。
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: ALWAYS
```
### 创建admin-client
主要依赖
```
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>2.1.6</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
```
启动类中添加注释 `@EnableEurekaClient` ` `
```
@SpringBootApplication
@EnableEurekaClient
public class AdminClientApplication{
public static void main(String[] args) {
SpringApplication.run(AdminClientApplication.class, args);
}
}
```
配置Security
```
@Configuration
public static class SecurityPermitAllConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().permitAll()
.and().csrf().disable();
}
}
```
配置application.yml
```
server:
port: 9002
#配置security
spring:
application:
name: admin-client
security:
user:
name: "admin"
password: "admin"
#配置eureka
eureka:
instance:
leaseRenewalIntervalInSeconds: 10 #eurek心跳
health-check-url-path: /actuator/health #健康检查页面的URL,相对路径,默认使用 HTTP 访问,如果需要使用 HTTPS则需要使用绝对路径配置
prefer-ip-address: true #如果设置了eureka.instance.ip-address 属性,则使用该属性配置的IP
metadata-map:
startup: ${random.int} #需要在重启后触发信息和端点更新
#如果eureka配置了security需要在这里添加用户名和密码
user.name: ${spring.security.user.name}
user.password: ${spring.security.user.password}
hostname: localhost
client:
registryFetchIntervalSeconds: 5 # 从eureka服务器注册表中获取注册信息的时间间隔(s),默认为30秒
serviceUrl:
defaultZone: http://admin:admin@${eureka.instance.hostname}:8080/eureka/,http://admin:admin@${eureka.instance.hostname}:8081/eureka/
# 开放所有endpoint,实际生产根据自身需要开放,出于安全考虑不建议全部开放。
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: ALWAYS
```
#### 浏览器输入: localhost:9091

输入用户名/密码
```
admin/admin
```


## 获取源码公众号回复: SpringBootAdmin


Springboot2.0学习之Actuator与SpringBoot-Admin