Spring Boot Actuator
是spring boot
项目一个监控模块,提供了不少原生的端点,包含了对应用系统的自省和监控的集成功能,好比应用程序上下文里所有的Bean、运行情况检查、健康指标、环境变量及各种重要度量指标等等,以图形化界面的方式展现这些信息,经过这些监控信息,咱们就能随时了解应用的运行状况了。java
做用:能够经过监控运行状态检查获取应用的运行状态,潜在问题等。能够更具这些且在风险对项目进行优化,排除问题保证项目的运行。能够经过监控度量指标获取应用内存占用,线程数量,垃圾回收过程对项目进行深刻分析。git
在项目中引入Actuator依赖,该以来由SprngBoot官方提供。github
1 <dependency> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-actuator</artifactId> 4 </dependency>
当项目中引入了Actuator依赖后,那么当前的项目就表示拥有了度量指标监控能力了,启动SpringBoot项目,控制台以下:web
框起来的那段内容表示:SpringBoot监控已经默认暴露了两个基础端点,可供咱们访问获取应用监控数据,基础访问路径是"/actuator"spring
输入访问路径:localhost:8080/actuator 结果以下:(为便于查看,我已将JSON结果格式化)编程
1 { 2 "_links": { 3 "self": { 4 "href": "http://localhost:8080/actuator", // 基础访问地址 5 "templated": false 6 }, 7 "health-path": { 8 "href": "http://localhost:8080/actuator/health/{*path}", 9 "templated": true 10 }, 11 "health": { 12 "href": "http://localhost:8080/actuator/health", // 暴露的端点一 (访问URL) 13 "templated": false 14 }, 15 "info": { 16 "href": "http://localhost:8080/actuator/info", // 暴露的端点二 (访问URL) 17 "templated": false 18 } 19 } 20 }
那么这些暴露的URL访问后分别表明什么呢?Actuator提供了13个接口,能够分为三大类:配置接口、度量接口和其它接口,具体以下表:json
HTTP 方法 | 路径 | 描述 |
---|---|---|
GET | /autoconfig | 提供了一份自动配置报告,记录哪些自动配置条件经过了,哪些没经过 |
GET | /configprops | 描述配置属性(包含默认值)如何注入Bean缓存 ●prefix属性表明 了属性的配置前缀 |
GET | /beans | 描述应用程序上下文里所有的Bean,以及它们的关系多线程 ●bean:Bean的名称 |
GET | /dump | 获取线程活动的快照 |
GET | /env | 获取所有环境属性。包括:环境变量、JVM属性.应用的配置配置。命令行中的参数等 |
GET | /env/{name} | 根据名称获取特定的环境属性值。/env接口还能用来获取单个属性的值。只须要在请求时在/env/+属性名便可。 |
GET | /health | 报告应用程序的健康指标(运行状态),这些值由HealthIndicator的实现类提供.(默认暴露的接口) |
GET | /info | 获取应用程序的自定义的定制信息,这些信息由info打头的属性提供。默认状况下.该端点只会返回一个空的json内容,咱们能够在application.properties配置文件中经过info前骚来设置一些属性(默认暴露的接口) |
GET | /mappings | 描述所有的URI路径,以及它们和控制器(包含Actuator端点)的映射关系,罗列出应用程序发布的所有接口。 ●bean属性标识了 该映射关系的请求处理器 |
GET | /metrics | 报告各类应用程序度量信息,好比内存用量,线程信息,垃圾回收信息,HTTP请求计数等 |
GET | /metrics/{name} | 报告指定名称的应用程序度量值 |
POST | /shutdown | 关闭应用程序,要求endpoints.shutdown.enabled设置为true |
GET | /trace | 提供基本的HTTP请求跟踪信息(时间戳、HTTP头等) |
访问一个试试?localhost:8080/actuator/health 访问后结果:运行状态为正常运行(说明:Actuator监控获取的全部数据都是JSON格式的。)
1 {"status":"UP"}
那么若是但愿访问其余接口怎么办?,默认只开启了info、health
两个端点,须要额外开启端点,须要额外去配置的!!!
1 #配置访问端点的根路径 2 management: 3 endpoints: 4 web: 5 # 配置访问端点的根路径,默认是/actuator 6 #base-path: /actuator 7 exposure: 8 #配置开启其余端点的URI,开启全部的端点访问: *,也能够指定开启端点访问:如: /beans, /env 9 include: "*" 10 # - /beans 11 # - /env 12 #配置排除其余端点的URI(排除即不开启) 13 #exclude: 14 # - /beans 15 # - /env
重启SpringBoot服务,以下:
具体访问测试就不演示了,Actuator监控获取的全部数据都是JSON格式的,能够本身访问测试后经过网络工具格式化JSON。
Actuator来监控Spring Boot应用,其提供了许多REST接口来查看应用的信息。但其返回的是大量的JSON格式数据,信息看上去不直观也不易于理解。Spring Boot Admin(SBA)是一款基于Actuator开发的开源软件(是一个针对spring-boot
的actuator
接口进行UI美化封装的监控工具),能够实现图形化界面的方式展现Spring Boot应用的配置信息、Beans信息、环境属性、线程信息、JVM情况等。官方说明文档点这里。选择版本文档说明,内有详情使用说明。
SpringBootAdmin的使用是须要创建服务端与客户端的。Spring Boot Admin
包含admin-server
与admin-client
两个组件,admin-server
经过采集actuator
端点数据,显示在spring-boot-admin-ui
上。
服务端:独立的项目,会将搜集到的数据在本身的图形界面中展现。依赖admin-server
客户端:须要监控的项目。依赖Actuator,admin-client
对应关系:一个服务端能够监控多个客户端。
舒适提示:服务端属于一个独立SpringBoot的项目(新建项目)。
1 <!-- spring-boot-admin-服务端依赖 --> 2 <dependency> 3 <groupId>de.codecentric</groupId> 4 <artifactId>spring-boot-admin-starter-server</artifactId> 5 <version>2.3.1</version> 6 </dependency>
1 server: 2 #servlet: 3 # 配置访问路径(可选) 4 #context-path: /admin-server 5 # 配置端口 6 port: 9090
1 @SpringBootApplication 2 @EnableAdminServer 3 public class SpringbootAdminServerApplication {
由于还没添加客户端,因此监控列表里是空的,接下来建立一个Spring Boot应用做为客户端。
admin-server
经过采集actuator
端点数据,将信息解析展现在UI界面的。那么客户端就须要依赖Actuator和admin-clietn。
1 <!-- spring-boot-admin-starter-client客户端依赖:注意要与服务端版本一致 --> 2 <dependency> 3 <groupId>de.codecentric</groupId> 4 <artifactId>spring-boot-admin-starter-client</artifactId> 5 <version>${spring-boot-admin.version}</version> 6 </dependency>
注意:1.版本要与服务端一致。2.客户端项目依赖不能少了Actuator。
1 #配置访问端点的根路径 2 management: 3 endpoints: 4 web: 5 # 配置访问端点的根路径,默认是/actuator 6 #base-path: /actuator 7 exposure: 8 #配置开启其余端点的URI,开启全部的端点访问: *,也能够指定开启端点访问:如: /beans, /env 9 include: "*" 10 # - /beans 11 # - /env 12 #配置排除其余端点的URI(排除即不开启) 13 #exclude: 14 # - /beans 15 # - /env 16 17 spring: 18 boot: 19 admin: 20 client: 21 # 配置客户端,被监控的服务端地址(官方说明也很详细的,这个是必须配置的) 22 url: 23 - http://localhost:9090
点击左上“应用墙”进入SpringBootAdmin主页,显示运行时间,项目个数。点击进入详情页,便可已图形报表UI界面方式显示全部监控信息: 如上的操做更多的多是涉及到了测试/运维的问题,因此这里就不深究了,但某些时候须要咱们开发人员配和实现更多操做,例如邮件方式发送检测日志,信息等。详情参考SpringBootAdmin
实际开发中,有一些业务可能和实际业务无关,但又不能没有,例如:注册新用户,当即送积分(没有点击领取但积分已到帐),或下单成功,发送push消息等等。
一般咱们开发的程序都是同步调用的,即程序按照代码的顺序一行一行的逐步往下执行,每一行代码都必须等待上一行代码执行完毕才能开始执行。而异步编程则没有这个限制,代码的调用再也不是阻塞的。因此在一些情景下,经过异步编程能够提升效率,提高接口的吞吐量。
使用异步的好处?就拿注册用户送积分来讲:
不使用异步调用,即同步调用测试。
1 @Service 2 public class AsynService { 3 4 /** 5 * 注册方法 6 */ 7 public void register() { 8 System.out.println("注册成功......."); 9 } 10 /** 11 * 异步方法送积分 12 */ 13 public void asynIntegral() { 14 try { 15 Thread.sleep(3000);// 休息三秒 16 } catch (InterruptedException e) { 17 // TODO Auto-generated catch block 18 e.printStackTrace(); 19 } 20 System.out.println("送积分100分....执行者线程名为:"+Thread.currentThread().getName()); 21 } 22 23 }
1 @RestController 2 @Slf4j // 获取log对象,Lombok插件中的注解 3 public class AsynController { 4 5 @Autowired 6 private AsynService asynService; 7 8 @RequestMapping("/register") 9 public String asynTest() { 10 long startTmie = System.currentTimeMillis(); 11 // 注册逻辑:调用注册方法 12 asynService.register(); 13 // 调用送积分方法 14 asynService.asynIntegral(); 15 long endtTmie = System.currentTimeMillis(); 16 log.info("消耗时间:"+(endTime-starttTmie)); 17 return "ok"; 18 } 19 20 }
注册成功.......
送积分100分....执行者线程名称为:http-nio-8080-exec-1
2020-12-02 20:00:15.112 INFO 4604 --- [nio-8080-exec-1] c.xsge123.app.controller.AsynController : 消耗时间:3002
结束语:在同步调用时,页面不会马上刷新注册结果,只有注册和送积分的功能所有执行完成后,页面才会显示注册通知。客户需等待较长的时间。程序总耗时较长。
在同步代码基础上,新增配置类AsyncConfig,配置开启异步调用,同时在须要使用异步调用的方法上使用注解@Async便可。
1 @Configuration // 将类注入到Spring容器中 2 @EnableAsync //开启SpringBoot异步调用(针对异步调用的方法,开启新线程),在启动类上使用也能够 3 public class AsyncConfig { 4 5 }
1 /** 2 * 异步方法送积分 3 */ 4 @Async // 标注当前方法为异步方法 5 public void asynIntegral() { 6 try { 7 Thread.sleep(3000);// 休息3秒 8 } catch (InterruptedException e) { 9 // TODO Auto-generated catch block 10 e.printStackTrace(); 11 } 12 System.out.println("送积分100分...."+Thread.currentThread().getName()); 13 }
注册成功....... 2020-12-02 20:18:11.764 INFO 4604 --- [nio-8080-exec-2] c.xsge123.app.controller.AsynController : 消耗时间:6 送积分100分....task-1
送积分100分....score-2
送积分100分....score-3
结束语:在异步调用的状况下,页面即刻响应注册结果,无需等待,后台等待3秒后,送积分程序显示执行结果。
@Async注解,在默认状况下,用的是SimpleAsyncTaskExecutor线程池,该线程池不是真正意义上的线程池,由于线程不可重用,每次调用都会新建一条线程。能够经过控制台日志输出查看,每次打印的线程名都是[task -1]、[task -2]、[task-3]、[task-4].....递增的。
@Async注解异步框架提供有多种线程池支持:
SimpLeAsyncTaskExecutor:不是真的线程池,这个类不可重用线程,每次调用都会建立一个新的线程 。
SyncTaskExecutor:这个类没有实现异步调用,只是一个同步操做。只适用于不须要多线程的地方
ConcurrentTaskExecutor:Executor的适配类,不推荐使用。若是ThreadPoolTaskExecutor不知足要求时,才用考虑使用这个类
ThreadPoolTaskScheduler:可使用cron表达式。
ThreadPoolTaskExecutor :最常使用,推荐。 其实质是对java.util.concurrent .ThreadPoolExecutor的包装类。
1 @Configuration // 将类注入到Spring容器中 2 @EnableAsync //开启SpringBoot异步调用(针对异步调用的方法,开启新线程) 3 public class AsyncConfig { 4 5 @Bean(name = "scorePoolTaskExecutor") 6 public ThreadPoolTaskExecutor getScorePoolTaskExecutor() { 7 // 建立线程池对象 8 ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); 9 //核心线程数 10 taskExecutor.setCorePoolSize(10); 11 //线程池维护线程的最大数量,只有在缓冲队列满了以后才会申请超过核心线程数的线程 12 taskExecutor.setMaxPoolSize(100); 13 //缓存队列 14 taskExecutor.setQueueCapacity(50) ; 15 //许的空闲时间,当超过了核心线程出以外的线程在空闲时间到达以后会被销毁 16 taskExecutor.setKeepAliveSeconds (200) ; 17 //.异步方法内部线程名称 18 taskExecutor.setThreadNamePrefix("score-"); 19 /** 20 * 当线程池的任务缓存队列已满,而且线程池中的线程数目达到maximumPoolSize,若是还有任务到来就会采起任务拒绝策略 21 * 一般有如下四种策略: 22 * ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecuti onException异常。 23 * ThreadPoolExecutor.DiscardPolicy: 也是丢弃任务,可是不抛出异常。 24 * ThreadPoolExecutor. DiscardOldestPolicy: 丢弃队列最前面的任务,而后从新尝试执行任务(重复此过程) 25 * ThreadPoolExecutor . CallerRunsPolicy:重试添加当前的任务,自动重复调用execute()方法,直到成功 26 */ 27 taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); 28 taskExecutor.initialize() ; 29 return taskExecutor; 30 } 31 32 }
1 /** 2 * 异步方法送积分 3 */ 4 @Async("scorePoolTaskExecutor") // 标注当前方法为异步方法 5 public void asynIntegral() { 6 try { 7 Thread.sleep(3000); 8 } catch (InterruptedException e) { 9 // TODO Auto-generated catch block 10 e.printStackTrace(); 11 } 12 System.out.println("送积分100分...."+Thread.currentThread().getName()); 13 }
注册成功....... 2020-12-02 20:45:57.898 INFO 4604 --- [nio-8080-exec-3] c.xsge123.app.controller.AsynController : 消耗时间:2 送积分100分....score-1 送积分100分....score-2 送积分100分....score-3
结束语:线程实现自定义