前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringBoot入门建站全系列(二十九)Actuator服务监控及SpringBootMonitor单机监控页面

SpringBoot入门建站全系列(二十九)Actuator服务监控及SpringBootMonitor单机监控页面

作者头像
品茗IT
发布2020-05-28 16:11:25
1.8K0
发布2020-05-28 16:11:25
举报
文章被收录于专栏:品茗IT品茗IT

SpringBoot入门建站全系列(二十九)Actuator服务监控及SpringBootMonitor单机监控页面

一、概述

Actuaotr是spring boot项目中非常强大的一个功能,有助于对应用程序进行监控和管理,通过restful api请求来监管、审计、收集应用的运行情况,针对微服务而言它是必不可少的一个环节。

spring-boot-actuator中已经内置了非常多的Endpoints(health、info、beans、httptrace、shutdown)等等,同时也允许我们自己扩展自己的端点.

本篇简单介绍Spring Boot Actuaotr的使用方法,及自定义使用方法、安全控制方法,并介绍单机监控页面SpringBootMonitor的使用。

代码可以在SpringBoot组件化构建https://www.pomit.cn/java/spring/springboot.html中的Actuator组件中查看,并下载。

**如果大家正在寻找一个java的学习环境,或者在开发中遇到困难,可以<a

href="https://jq.qq.com/?_wv=1027&k=52sgH1J"

target="_blank">

加入我们的java学习圈,点击即可加入

</a>

,共同学习,节约学习时间,减少很多在学习中遇到的难题。**

二、配置

本文假设你已经引入spring-boot-starter-web。已经是个SpringBoot项目了,如果不会搭建,可以打开这篇文章看一看《SpringBoot入门建站全系列(一)项目建立》

2.1 Maven依赖

使用actuator可以使用spring-boot-starter-actuator,方便快捷,一般springboot对大多数开源项目都做了整合,提供了专用的stater。

同时,本篇使用了spring-boot-monitor做Spring boot actuator的监控页面,spring-boot-monitor是一个对Spring boot Admin监控工具做简化的单机版监控工具,单机版使用spring-boot-monitor足够了,方便快捷。

代码语言:javascript
复制
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

<dependency>
	<groupId>cn.pomit</groupId>
	<artifactId>spring-boot-monitor</artifactId>
	<version>0.0.1</version>
</dependency>
2.2 配置文件

在application.properties 中需要配置actuator的信息,如:

代码语言:javascript
复制
management.endpoints.web.exposure.include=*

actuator.filter.switch=false

这里将actuator的所有endpoints都开放出来了,这是一种很危险的配置,但是,开放出来的理由有

  • 如果是内网环境,可以开放出来,但不要开放到外网环境;
  • 如果使用了Spring Security,可以根据用户权限配置,需要将所有endpoints开放出来;
  • 如果想简单使用filter对endpoints做控制,可以全部开放出来,本篇就是使用filter对actuator/*做简单的控制,actuator.filter.switch的配置就是为了对filter做开关。

三、Actuator的使用

3.1 Actuator开放的端点

Actuator只需要加载依赖和配置即可使用,启动时候会提示你Actuator暴漏了哪些接口,如:

代码语言:javascript
复制
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/super],methods=[POST],consumes=[application/vnd.spring-boot.actuator.v2+json || application/json],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" 
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/super],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" 
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/super/{arg0}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/auditevents],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/beans],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" 
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/health],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" 
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/conditions],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" 
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/configprops],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" 
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/env],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" 
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/env/{toMatch}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" 
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/info],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" 
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/logfile],methods=[GET],produces=[application/octet-stream]}" 
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/loggers],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/loggers/{name}],methods=[POST],consumes=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/loggers/{name}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" 
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/heapdump],methods=[GET],produces=[application/octet-stream]}" 
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/threaddump],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" 
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/metrics],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" 
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/metrics/{requiredMetricName}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" 
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/scheduledtasks],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" 
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/httptrace],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" 
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/mappings],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" 
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" 

这里面的/actuator/super是我自定义的,下面会说明,其他的都是actuator自己的endpoint。

大致有这些:

在这里插入图片描述

3.2 Actuator路径

Actuator开放的端口都可以直接访问的,根据提示的get/post请求即可:

  • get请求返回的都是json,有的可以带路径筛选;
  • post请求是json数据。返回也是json。

下面请求下127.0.0.1:8080/actuator:

代码语言:javascript
复制
{
    "_links": {
        "self": {
            "href": "http://127.0.0.1:8080/actuator",
            "templated": false
        },
        "super": {
            "href": "http://127.0.0.1:8080/actuator/super",
            "templated": false
        },
        "super-arg0": {
            "href": "http://127.0.0.1:8080/actuator/super/{arg0}",
            "templated": true
        },
        "auditevents": {
            "href": "http://127.0.0.1:8080/actuator/auditevents",
            "templated": false
        },
        "beans": {
            "href": "http://127.0.0.1:8080/actuator/beans",
            "templated": false
        },
        "health": {
            "href": "http://127.0.0.1:8080/actuator/health",
            "templated": false
        },
        "conditions": {
            "href": "http://127.0.0.1:8080/actuator/conditions",
            "templated": false
        },
        "configprops": {
            "href": "http://127.0.0.1:8080/actuator/configprops",
            "templated": false
        },
        "env": {
            "href": "http://127.0.0.1:8080/actuator/env",
            "templated": false
        },
        "env-toMatch": {
            "href": "http://127.0.0.1:8080/actuator/env/{toMatch}",
            "templated": true
        },
        "info": {
            "href": "http://127.0.0.1:8080/actuator/info",
            "templated": false
        },
        "logfile": {
            "href": "http://127.0.0.1:8080/actuator/logfile",
            "templated": false
        },
        "loggers": {
            "href": "http://127.0.0.1:8080/actuator/loggers",
            "templated": false
        },
        "loggers-name": {
            "href": "http://127.0.0.1:8080/actuator/loggers/{name}",
            "templated": true
        },
        "heapdump": {
            "href": "http://127.0.0.1:8080/actuator/heapdump",
            "templated": false
        },
        "threaddump": {
            "href": "http://127.0.0.1:8080/actuator/threaddump",
            "templated": false
        },
        "metrics": {
            "href": "http://127.0.0.1:8080/actuator/metrics",
            "templated": false
        },
        "metrics-requiredMetricName": {
            "href": "http://127.0.0.1:8080/actuator/metrics/{requiredMetricName}",
            "templated": true
        },
        "scheduledtasks": {
            "href": "http://127.0.0.1:8080/actuator/scheduledtasks",
            "templated": false
        },
        "httptrace": {
            "href": "http://127.0.0.1:8080/actuator/httptrace",
            "templated": false
        },
        "mappings": {
            "href": "http://127.0.0.1:8080/actuator/mappings",
            "templated": false
        }
    }
}
3.3 自定义Endpoint

一般情况下,是没必要自定义Endpoint的,但是也不排除特殊情况,我这里自定义一个Endpoint,用来往request里放一个user对象,这个user是用来做测试的,用于下面突破filter用的(下面再说),这里先说怎么增查这个user。

过程如下:

  • 使用@Endpoint注解相应的类,作为Actuator的一个endpoint。注解要指定id,这个id作为访问路径,比如这里是/actuator/super;
  • @ReadOperation来注解查询接口,如果要根据路径做查询,要用@Selector注解方法参数;注意这地方是**@Selector String arg0**,这个arg0不能改变,改成其他的,开放出去的接口还是/{arg0},这就导致你的方法无法正常获取参数值。
  • @WriteOperation 来注解修改接口,注意请求数据必须是json,而且参数不像controller中那么灵活,不能将实体作为参数,要把实体中相应的属性拿出来做参数。
  • 这里在增加用户时,往request里放一个user对象。

SuperEndPoint :

代码语言:javascript
复制
package com.cff.springbootwork.actuator.endpoint;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.http.HttpServletRequest;

import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.annotation.Selector;
import org.springframework.boot.actuate.endpoint.annotation.WriteOperation;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Endpoint(id = "super")
public class SuperEndPoint {
	private Map<String, SuperUser> users = new ConcurrentHashMap<>();

	@ReadOperation
	public Set<String> users() {
		return users.keySet();
	}

	@ReadOperation
	public SuperUser usersIdentify(@Selector String arg0) {
		return users.get(arg0);
	}

	@WriteOperation
	public Set<String> set(String userName, String passwd) {
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();
		if (request != null) {
			SuperUser superUser = new SuperUser();
			superUser.setUserName(userName);
			superUser.setPasswd(passwd);
			request.getSession().setAttribute("superUser", superUser);

			users.put(superUser.getUserName(), superUser);
		}

		return users.keySet();
	}

	public static class SuperUser {
		private String userName;
		private String passwd;

		public String getUserName() {
			return userName;
		}

		public void setUserName(String userName) {
			this.userName = userName;
		}

		public String getPasswd() {
			return passwd;
		}

		public void setPasswd(String passwd) {
			this.passwd = passwd;
		}
	}
}

还要将Endpoint注册为bean

MvcEndPointConfig:

代码语言:javascript
复制
package com.cff.springbootwork.actuator;

import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.cff.springbootwork.actuator.endpoint.SuperEndPoint;

@Configuration
@ServletComponentScan 
public class MvcEndPointConfig {

	@Bean
	@ConditionalOnEnabledEndpoint
	public SuperEndPoint superEndPoint() {
		return new SuperEndPoint();
	}
}

四、使用Filter对访问actuator做限制

上面已经说了,actuator的接口要做保护,我这里就用filter对接口做最简单的保护。

  • 对/actuator/*下所有路径做过滤,并用actuator.filter.switch属性对filter做开关;
  • 如果时/actuator/super路径的post操作,放行它,它将会往request中放一个对象;
  • 其他/actuator/*下路径要判断request中有没有user对象,没有就返回错误提示。

ActuatorPermissionFilter :

代码语言:javascript
复制
package com.cff.springbootwork.actuator.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;

import com.fasterxml.jackson.databind.ObjectMapper;

@WebFilter(urlPatterns = "/actuator/*", filterName = "actuatorPermissionFilter")
@Order(1) // 指定过滤器的执行顺序,值越大越靠后执行
public class ActuatorPermissionFilter implements Filter {
	private String excludePath = "actuator/super";
	@Value("${actuator.filter.switch}")
	Boolean actuatorSwitch;

	@Override
	public void init(FilterConfig filterConfig) {

	}

	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
			throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) servletRequest;
		HttpServletResponse response = (HttpServletResponse) servletResponse;
		if (actuatorSwitch && !(request.getRequestURI().endsWith(excludePath)
				&& request.getMethod().equals(HttpMethod.POST.toString()))) {
			Object user = request.getSession().getAttribute("superUser");
			if (user == null) {
				// 未登录,返回数据
				ObjectMapper mapper = new ObjectMapper();
				response.setStatus(HttpStatus.OK.value());
				response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
				mapper.writeValue(response.getWriter(), "您没有权限访问该接口,请使用自定义的登录接口设置superUser后使用!");
				return;
			}
		}
		filterChain.doFilter(servletRequest, servletResponse);

	}

	@Override
	public void destroy() {
	}

}

五、Spring Boot Monitor做监控页面

Spring Boot Monitor是一个对Spring boot admin监控工具做修改并适配单机的监控工具,完美继承了Spring boot admin的风格,直接使用actuator的指标进行显示。

Spring Boot Monitor官网:https://www.pomit.cn/SpringBootMonitor

前面maven依赖中,已经说明依赖spring-boot-monitor,这时,无需其他配置.

访问http://127.0.0.1:8080/monitor , 自动跳转到Spring Boot Monitor的监控页面。

在这里插入图片描述

Spring Boot Monitor的监控页面和Spring boot admin的一模一样,前端的功能也一模一样。

在这里插入图片描述

可以对Spring boot的各项指标一目了然,还可以进行简单的操作。

当然,如果Spring boot actuator的指标被限制了,它也拿不到相应的指标了,因为它是直接请求actuator接口的。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-09-30 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • SpringBoot入门建站全系列(二十九)Actuator服务监控及SpringBootMonitor单机监控页面
  • 一、概述
  • 二、配置
    • 2.1 Maven依赖
      • 2.2 配置文件
      • 三、Actuator的使用
        • 3.1 Actuator开放的端点
          • 3.2 Actuator路径
            • 3.3 自定义Endpoint
            • 四、使用Filter对访问actuator做限制
            • 五、Spring Boot Monitor做监控页面
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档