介绍
- Spring Boot 可帮助创建可以运行的独立的、生产级的基于 Spring 的应用程序。
- 可以使用 Spring Boot 创建可以使用java -jar或更传统的 war 部署启动的 Java应用程序。我们还提供了一个运行“spring 脚本”的命令行工具。
springboot的主要目标是:
- 为所有 Spring 开发提供更快且可广泛访问的入门体验。
- 开箱即用,但随着需求开始偏离默认设置,请迅速让开。
- 提供一系列大型项目通用的非功能特性(例如嵌入式服务器、安全性、指标、健康检查和外部化配置)。
- 绝对不需要代码生成,也不需要 XML 配置。
Spring指标监控
1.x版本与2.x版本对比
Springboot Actuator官网教程
Actuator如何使用
- 导入spring-boot-starter-actuator场景依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
- 导入场景后访问http://localhost:8080/actuator/*
{"_links":{"self":{"href":"http://localhost:8080/actuator","templated":false},"health":{"href":"http://localhost:8080/actuator/health","templated":false},"health-path":{"href":"http://localhost:8080/actuator/health/{*path}","templated":true}}}
- 通过访问上述地址,就可以得到相关指标的信息
端点
- Actuator 端点可让监控应用程序并与之交互。Spring Boot 包含许多内置端点,并允许添加自己的端点。例如,health端点提供基本的应用程序健康信息。
- 每个单独的端点都可以通过 HTTP 或JMX启用或禁用和公开(远程访问)。当端点被启用和公开时,它被认为是可用的。内置端点只有在可用时才会自动配置。大多数应用程序选择通过 HTTP 公开,其中端点的 ID 和前缀/actuator被映射到URL。例如,默认情况下,health端点映射到/actuator/health.
在官网中描述了不同端点的意义,同时也提供了JMX与WEB两种访问权限。在springboot中端点是默认开启的,但是可以通过web访问的端点较少。可以手动添加web权限访问的端点。
management:
endpoints:
enabled-by-default: true #开启默认端点,默认值就是true
web:
exposure:
include: '*' #设置web下暴露所有端点
端点启用
默认情况下,shutdown启用除 之外的所有端点。要配置端点的启用,请使用其management.endpoint..enabled属性。以下示例启用shutdown端点:
management.endpoint.shutdown.enabled=true
在springboot中很多端点都是默认开启的,想要关闭可以使用
management.endpoints.enabled-by-default=false
端点暴露
该include属性列出了公开的端点的 ID。该exclude属性列出了不应公开的端点的 ID。该exclude属性优先的include属性。无论include和exclude属性可与端点ID列表进行配置。
常用端点信息
- health 显示应用程序运行状况信息。
health是对整个系统的健康状况的检测,记录了每个组件的健康状况。
在springboot中我们可以对每个端点通过配置文件的方式进行详细配置,例如:
endpoint:
health:
enabled: true
show-details: always #展示健康或者不健康详情
- metrics 显示当前应用程序的“指标”信息。
- loggers 显示和修改应用程序中记录器的配置。
在springboot端点是默认开启的,这样可能会存在安全因素,所以我们希望关闭所有的端点,单独开启必须的端点。
management:
endpoints:
enabled-by-default: false #关闭默认端点,默认值就是true
web:
exposure:
include: '*' #设置web下暴露所有端点
endpoint:
health:
enabled: true # 开启health端点
show-details: always #展示健康或者不健康详情
metrics:
enabled: true # 开启metrics端点
定制化endPoint(端点)
health健康端点定制化
通过配置文件来定义
- 使用健康信息来检查正在运行的应用程序的状态。当生产系统出现故障时,监控软件通常使用它来提醒。health端点公开的信息取决于可以使用以下值之一配置的management.endpoint.health.show-details和management.endpoint.health.show-components属性:
通过配置类——注册实现HealthIndicator接口
要提供自定义健康信息,可以注册实现该HealthIndicator接口的Spring bean 。需要提供该health()方法的实现并返回Health响应。Health响应应该包括一个状态,并且可以任选地包括另外的细节被显示。以下代码显示了一个示例HealthIndicator实现:
package cn.supperbro.actuator.user.actuator;
import cn.supperbro.actuator.user.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@Component
public class MyHealthIndicator implements HealthIndicator { //需要HealthIndicator结尾
@Autowired
private UserService userServiceImpl;
@Override
public Health health() {
Map<String,Object> map = new HashMap<>();
//此处书写判断程序是否健康的逻辑
if (userServiceImpl.list()!=null){
map.put("数据查询","正常");
return Health.up().withDetails(map).build();
}else {
map.put("数据查询","异常");
return Health.down().withDetails(map).build();
}
}
}
info定制化
自动配置
InfoContributor在适当的时候,Spring Boot 会自动配置以下bean:
通过配置文件自定义
可以info通过设置info.* 属性来自定义端点公开的数据。Environment下的所有属性都会info自动公开。
info:
appName: supperbroApp
appVersion: 1.1.1
mavenPorjectName: @project.name@ # @ maven文件内容 @
通过配置类
要提供自定义应用程序信息,可以注册实现该InfoContributor接口的Spring bean 。
package cn.supperbro.actuator.user.actuator;
import org.springframework.boot.actuate.info.Info;
import org.springframework.boot.actuate.info.InfoContributor;
import org.springframework.stereotype.Component;
import java.util.Collections;
@Component
public class ExampleInfoContributor implements InfoContributor {
@Override
public void contribute(Info.Builder builder) {
builder.withDetail("消息", Collections.singletonMap("app版本","1.1.1"));
}
}
定制metrics
metrics是指标检测,包括了很多的默认配置,如果需要自定义配置的话。
要注册自定义指标,请注入MeterRegistry的组件,如以下示例所示:
class Dictionary {
private final List<String> words = new CopyOnWriteArrayList<>();
Dictionary(MeterRegistry registry) {
registry.gaugeCollectionSize("dictionary.size", Tags.empty(), this.words);
}
// …
}
如果指标依赖于其他 bean,建议您使用 aMeterBinder来注册它们,如以下示例所示:
@Bean
MeterBinder queueSize(Queue queue) {
return (registry) -> Gauge.builder("queueSize", queue::size).register(registry);
}
使用 MeterBinder可确保设置正确的依赖关系,并且在检索度量值时该 bean 可用。MeterBinder,如果发现实现也可能是有用的,可重复的仪器一套跨组件或应用指标。
案例:
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Autowired
private UserMapper userMapper;
private Counter counter;
public UserServiceImpl(MeterRegistry registry){
counter = registry.counter("findAllStudents.List");
}
@Override
public List<User> list() {
counter.increment();
return userMapper.selectList(null);
}
}
定制端点
package cn.supperbro.actuator.user.actuator;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.annotation.WriteOperation;
import org.springframework.stereotype.Component;
import java.util.Collections;
import java.util.Map;
@Endpoint(id = "example")
@Component
public class ExampleEndPoint {
@ReadOperation
public Map getReader(){
return Collections.singletonMap("value","自定义的endPoint");
}
@WriteOperation
public void getWriter(){
System.out.println("endpoint");
}
}
spring-admin-boot
是一个开源项目,可以用来显示端点数据,在github上,官方文档。官方地址详细说明了。
实例:
1.创建一个服务器用于获取检测端数据,导入相关依赖
<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>
<version>2.3.1</version>
</dependency>
2.在服务器端启动类标注注解@@EnableAdminServer
3.客户端导入依赖,此处没有导入安全检测,(注意安全检测)
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>2.3.1</version>
</dependency>
4 配置客户端发送信息至服务器地址
spring.boot.admin.client.url=http://localhost:8080
management.endpoints.web.exposure.include=*
Profile功能
profile环境切换功能
-
使用步骤:
首先可以创建不同的配置环境:
application.properties/yaml------>默认配置文件
application-prod.properties/yaml------->生产配置文件
application-test.properties/yaml--------->测试生产环境
需要某套配置环境时,可以在默认配置直接指定其生产环境版本
spring: profiles: active: test #指定test生产环境
指定以后,application.properties/yaml+application-prod.properties/yaml都会生效,同名的配置项会以指定版本有效
但我们的项目已经打包以后,同样可以通过命令行指定配置文件
java -jar xxx.jar --spring.profiles.active = prod --spring.xxx.xxx=xxx(也可以去设置配置文件的配置参数)
-
通过@Profile(“xxxx”)指定xxxx的配置文件生效时,该注解作用的类或者是该注解作用的方法生效。
外部化配置
自定义start
虽然springboot已经内置了很多的场景启动器,但是也会有不满足我们需求的,那么自定义start显得很重要。
分析:
-
通过查看spring的内置启动器,我们发现start中并没有具体的实际业务逻辑代码,一个场景启动器往往是说明该场景引入了那些依赖,例如web场景启动器中
-
然而关于一个场景启动器的自动配置功能,往往存在一个xx-xx-xx-autoconfigure的配置类当中
自定义场景启动器
supperbro-hello-spring-boot-starter———启动类
supperbro-hello-spring-boot-starter-configure————自动配置包
1 首先通过maven新建了一个启动器的模块
<groupId>cn.supperbro</groupId>
<artifactId>supperbro-hello-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
2 通过spring向导新建了一个自动配置包
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.supperbro</groupId>
<artifactId>supperbro-hello-spring-boot-starter-configure</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>supperbro-hello-spring-boot-starter-configure</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
3 通过我们的启动器导入配置包的依赖
<dependency>
<groupId>cn.supperbro</groupId>
<artifactId>supperbro-hello-spring-boot-starter-configure</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
4 通过我们的配置包定义自动配置规则或者是业务逻辑
测试demo
首先定义一个配置文件(通过引入场景后在application配置文件中配置)
package cn.supperbro.hello.bean;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("supperbro.hello")
public class HelloInfo {
private String prefix;
private String suffix;
public String getPrefix() {
return prefix;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public String getSuffix() {
return suffix;
}
public void setSuffix(String suffix) {
this.suffix = suffix;
}
}
定义一个业务逻辑类,用于测试
package cn.supperbro.hello.service;
import cn.supperbro.hello.bean.HelloInfo;
import org.springframework.beans.factory.annotation.Autowired;
public class HelloService {
@Autowired
HelloInfo helloInfo;
public String getHello(String name){
return helloInfo.getPrefix()+":"+name+"-"+helloInfo.getSuffix();
}
}
定义自动配置,合适的时候让我们的业务逻辑生效
package cn.supperbro.hello.autofigure;
import cn.supperbro.hello.bean.HelloInfo;
import cn.supperbro.hello.service.HelloService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableConfigurationProperties(HelloInfo.class)
@ConditionalOnMissingBean(HelloService.class)//不存在该bean时配置
public class HelloAutoConfiguration {
@Bean
public HelloService getHelloService(){
return new HelloService();
}
}
通过上述配置后,想要让我们springboot首先加载我们的自动配置类,就要通过配置spring.factories来启动我们的配置类,可以参照springboot的其他场景
完成目录文件的新建后,就可以开始添加我们的自动配置类
Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.supperbro.hello.autofigure.HelloAutoConfiguration
这样就简单的自定义了一个starter