SpringBoot has its own monitoring function Actuator, which can help monitor the internal operation of the program, such as monitoring status, Bean loading status, environment variables, log information, thread information, etc.
Configure Actuators
pom.xml
<!-- web start-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- web end-->
<!-- actuator start-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- actuator end-->
browser opens the linkhttp://localhost:8080/actuator/
You can see all supported connections, the default is only
/actuator
/actuator/health
/actuator/health/{component}
/actuator/health/{component}/{instance}
/actuator/info
bean loadinghttp://localhost:8080/actuator/beans
Specific usage method:
-
Introduce the above dependent jar
Enable all monitoring endpoints with the following configuration, which are disabled by default;
management:
endpoints:
web:
exposure:
include: "*"
"*" stands for enabling all monitoring endpoints, which can be enabled individually, for example, health
, info
, metrics
etc.
Actuator's REST interface
Actuator monitoring is divided into two categories: native endpoints and user-defined endpoints; custom endpoints mainly refer to scalability. Users can define some indicators of concern according to their actual applications and monitor them during runtime.
The native endpoint is to provide many web interfaces in the application, and through them to understand the internal conditions of the application when it is running. Native endpoints can be further divided into three categories:
-
Application configuration class : You can view the static information of the application during runtime: such as automatic configuration information, loaded springbean information, yml file configuration information, environment information, and request mapping information;
-
Metric category : mainly dynamic information during runtime, such as stack, request connection, some health indicators, metrics information, etc.;
-
Operation control class : mainly refers to shutdown, the user can send a request to close the monitoring function of the application.
Actuator provides 13 interfaces, as shown in the following table.
Detailed command
For security reasons in Spring Boot 2.x, Actuator only opened two endpoints /actuator/health
and /actuator/info
. Can be set to open in the configuration file.
All monitoring points can be opened
management:
endpoints:
web:
exposure:
include: "*"
You can also choose to open the section
management:
endpoints:
web:
exposure:
exclude: beans,trace
Actuator has all monitoring point paths by default /actuator/*
, and of course, this path also supports customization if necessary.
management:
endpoints:
web:
base-path: /manage #记得要加上/
After setting and restarting, the access address will become/manage/*
Actuator monitors almost all aspects of the application, and we focus on some commands that are often used in projects.
-
health
health is mainly used to check the running status of the application, which is the most frequently used monitoring point. This interface is usually used to remind us of the running status of the application instance and the reason why the application is not "healthy", such as database connection, insufficient disk space, etc.
By default, the state of health is open. After adding dependencies, start the project and visit: http://localhost:8080/actuator/health
to see the state of the application.
{
"status" : "UP"
}
If you want to view detailed application health information, you need to configure management.endpoint.health.show-details
the value of always. After the configuration, we visit again http://localhost:8080/actuator/health
, and the obtained information is as follows:
{
"status": "UP",
"components": {
"diskSpace": {
"status": "UP",
"details": {
"total": 236510507008,
"free": 223361744896,
"threshold": 10485760
}
},
"ping": {
"status": "UP"
}
}
}
The health information of Spring boot ApplicationContext
is HealthIndicator Beans
collected from various sources. The Spring boot framework contains a large number of HealthIndicators
implementation classes. Of course, you can also achieve the health status you think.
By default, the state of the final Spring Boot application is HealthAggregator
summarized, and the summary algorithm is:
-
Set status code sequence:
setStatusOrder(Status.DOWN, Status.OUT_OF_SERVICE, Status.UP, Status.UNKNOWN);
. -
Filter out unrecognized status codes.
-
If there is no status code, the status of the entire Spring Boot application is
UNKNOWN
. -
Sort all collected status codes in the order of 1.
-
Returns the first status code in an ordered sequence of status codes as the status of the entire Spring Boot application.
health Checks the health of the application by combining several health indices. The ones that come with the Spring boot framework HealthIndicators
currently include:
For example, if your application uses Redis, RedisHealthindicator
it will be considered as part of the check; if it uses MongoDB, MongoHealthIndicator
it will be considered as part of the check.
You can turn off specific health check indicators in the configuration file, such as turning off redis health check:
management:
health:
redise:
enabled: false
By default, all of these health indicators are considered part of the health check.
-
Custom HealthIndicator health check
Sometimes you need to provide custom health status check information, you can HealthIndicator
implement it through the implemented interface, and register the implementation class as a spring bean. You need to implement one of the health()
methods and return a custom health status response message, which should include a status code and detailed information to display. For example, the following is an HealthIndicator
implementation class of an interface:
@Component
public class MyHealthIndicator implements HealthIndicator {
@Override
public Health health() {
int errorCode = check(); // perform some specific health check
if (errorCode != 0) {
return Health.down().withDetail("Error Code", errorCode).build();
}
return Health.up().build();
}
}
In addition, in addition to several state types defined by Spring boot, we can also customize state types to represent a new system state. In this case, you also need to implement the interface HealthAggregator
, or configure the default implementation management.health.status.order
to continue using .HealthAggregator
For example, in your custom health check HealthIndicator
implementation class, a custom status type is used FATAL
. In order to configure the severity of the status type, you need to add the following configuration to the application configuration file:
management:
health:
status:
order: FATAL, DOWN, OUT_OF_SERVICE, UNKNOWN, UP
When doing a health check, the HTTP status code in the response reflects the overall health status, (for example, UP corresponds to 200, and UP OUT_OF_SERVICE
corresponds DOWN
to 503). Similarly, you also need to set the corresponding HTTP status code for the custom status type. For example, the following configuration can be FATAL
mapped to 503 (service unavailable):
management:
health:
status:
http-mapping:
FATAL: 503
The following is a list of HTTP status codes corresponding to the built-in health status types:
info
info is the configuration information that we configure ourselves starting with info in the configuration file. For example, our configuration in the sample project is:
info:
app:
name:
spring-boot-actuator
version: 1.0.0
test: test
Start the sample project, visit: http://localhost:8080/actuator/info
Return part of the information is as follows:
{
"app": {
"name": "spring-boot-actuator",
"version": "1.0.0",
"test":"test"
}
}
beans
According to the example, it can be seen that the bean's alias, type, whether it is a singleton, class address, dependency and other information are displayed.
Start the sample project, visit: http://localhost:8080/actuator/beans
Return part of the information is as follows:
[
{
"context": "application:8080:management",
"parent": "application:8080",
"beans": [
{
"bean": "embeddedServletContainerFactory",
"aliases": [
],
"scope": "singleton",
"type": "org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory",
"resource": "null",
"dependencies": [
]
},
{
"bean": "endpointWebMvcChildContextConfiguration",
"aliases": [
],
"scope": "singleton",
"type": "org.springframework.boot.actuate.autoconfigure.EndpointWebMvcChildContextConfiguration$$EnhancerBySpringCGLIB$$a4a10f9d",
"resource": "null",
"dependencies": [
]
}
}
]
conditions
The automatic configuration function of Spring Boot is very convenient, but sometimes it means that it is difficult to find out the specific cause of the problem. Using conditions, you can view the code under what conditions a certain configuration takes effect when the application is running, or why a certain automatic configuration does not take effect.
Start the sample project, visit: http://localhost:8080/actuator/conditions
Return part of the information is as follows:
{
"positiveMatches": {
"DevToolsDataSourceAutoConfiguration": {
"notMatched": [
{
"condition": "DevToolsDataSourceAutoConfiguration.DevToolsDataSourceCondition",
"message": "DevTools DataSource Condition did not find a single DataSource bean"
}
],
"matched": [ ]
},
"RemoteDevToolsAutoConfiguration": {
"notMatched": [
{
"condition": "OnPropertyCondition",
"message": "@ConditionalOnProperty (spring.devtools.remote.secret) did not find property 'secret'"
}
],
"matched": [
{
"condition": "OnClassCondition",
"message": "@ConditionalOnClass found required classes 'javax.servlet.Filter', 'org.springframework.http.server.ServerHttpRequest'; @ConditionalOnMissingClass did not find unwanted class"
}
]
}
}
}
heapdump
Returns a GZip compressed JVM heap dump
Start the sample project and visit: http://localhost:8080/actuator/heapdump
A Jvm heap file heapdump will be automatically generated. We can use the Jvm monitoring tool VisualVM that comes with the JDK to open this file to view memory snapshots. Similar to the following picture:
shutdown
Open the interface to gracefully close the Spring Boot application. To use this function, you first need to open it in the configuration file:
management:
endpoint:
shutdown:
enabled: true
After the configuration is complete, start the sample project and use curl to simulate a post request to access the shutdown interface.
The shutdown interface only supports post requests by default.
curl -X POST "http://localhost:8080/actuator/shutdown"
{
"message": "Shutting down, bye..."
}
At this point you will find that the application has been closed.
mappings
Describe all URI paths and their mapping to controllers
Start the sample project, visit: http://localhost:8080/actuator/mappings
Return part of the information is as follows:
{
"/**/favicon.ico": {
"bean": "faviconHandlerMapping"
},
"{[/hello]}": {
"bean": "requestMappingHandlerMapping",
"method": "public java.lang.String com.neo.controller.HelloController.index()"
},
"{[/error]}": {
"bean": "requestMappingHandlerMapping",
"method": "public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)"
}
}
threaddump
/threaddump
The interface generates a snapshot of current thread activity. This function is very good, and it is convenient for us to check the thread status when we locate the problem every day. It mainly displays information such as thread name, thread ID, thread status, whether to wait for lock resources, etc.
Start the sample project, visit: http://localhost:8080/actuator/threaddump
Return part of the information is as follows:
[
{
"threadName": "http-nio-8088-exec-6",
"threadId": 49,
"blockedTime": -1,
"blockedCount": 0,
"waitedTime": -1,
"waitedCount": 2,
"lockName": "java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@1630a501",
"lockOwnerId": -1,
"lockOwnerName": null,
"inNative": false,
"suspended": false,
"threadState": "WAITING",
"stackTrace": [
{
"methodName": "park",
"fileName": "Unsafe.java",
"lineNumber": -2,
"className": "sun.misc.Unsafe",
"nativeMethod": true
},
...
{
"methodName": "run",
"fileName": "TaskThread.java",
"lineNumber": 61,
"className": "org.apache.tomcat.util.threads.TaskThread$WrappingRunnable",
"nativeMethod": false
}
...
],
"lockInfo": {
"className": "java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject",
"identityHashCode": 372286721
}
}
...
]
When there is a problem in production, you can use the thread snapshot of the application to detect the tasks being executed by the application.
loggers endpoint
Access http://localhost:8080/actuator/loggers
to view information such as the log level of the current application:
This is not special in itself, but there is a very useful function. For example, the log level of our production environment is generally info, but now there is a bug that cannot be checked through the info level, so we can temporarily modify the log level.
For example, the ROOT node in the above figure is at the info level, then we can use tools such as postman to send a post request to modify the log level.
After the modification, you will find that the log changes from the original info to debug:
metrics endpoint
Metrics is a very important monitoring endpoint. Its monitoring content covers some important indicators such as JVM memory, heap, class loading, processor and tomcat container:
You can see that there are a lot of indicators, and you can view the corresponding indicator information by visiting any indicator:
Custom Endpoints
Custom configuration to control whether to enable filtering
actuator:
filter:
switch: false
Common annotations for custom monitoring endpoints
Customizing a monitoring endpoint mainly has the following common annotations:
-
@Endpoint : Define a monitoring endpoint, both HTTP and JMX are supported.
-
@WebEndpoint : Define a monitoring endpoint, which only supports HTTP.
-
@JmxEndpoint : Define a monitoring endpoint, only supports JMX mode.
The above three annotations act on the class, indicating that the current class is a monitoring endpoint. In addition, some annotations will be used on methods and parameters:
-
@ReadOperation : acts on the method and can be used to return the information displayed by the endpoint (requested through the Get method).
-
@WriteOperation : acts on the method and can be used to modify the information displayed by the endpoint (requested through the Post method).
-
@DeleteOperation : acts on the method and can be used to delete the corresponding endpoint information (requested through the Delete method).
-
@Selector : Acts on the parameter and is used to locate the specific indicator route of an endpoint.
Under normal circumstances, it is not necessary to customize the Endpoint, but it does not rule out special circumstances. I customize an Endpoint here to put a user object in the request. This user is used for testing and is used to break through the filter below. (to be discussed later), let’s first talk about how to add this user.
The process is as follows:
-
Annotate
@Endpoint
the corresponding class as an endpoint of Actuator. The annotation needs to specify the id, which is used as the access path, such as here/actuator/super
; -
@ReadOperation
To annotate the query interface, if you want to query according to the path, you need to use@Selector
the annotation method parameters; note that this place is that@Selector String arg0
this arg0 cannot be changed, it can be changed to other, the open interface is still there/{arg0}
, which makes your method unable to obtain the parameter value normally . -
@WriteOperation
To annotate the modification interface, note that the request data must be json, and the parameters are not as flexible as in the controller. Entities cannot be used as parameters, and the corresponding attributes in the entities must be used as parameters. -
When adding a user here, put a user object in the request.
SuperEndPoint :
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;
}
}
}
Also register the Endpoint as a bean
MvcEndPointConfig:
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();
}
}
Use Filter to restrict access to actuator
As mentioned above, the interface of the actuator needs to be protected. I will use the filter to protect the interface in the simplest way.
-
Filter
/actuator/*下
all paths, and useactuator.filter.switch
attributes to switch filters; -
If it is
/actuator/super
the post operation of the path, let it go, it will put an object in the request; -
For other
/actuator/*下
paths, it is necessary to judge whether there is a user object in the request, and if there is no user object, an error message will be returned.
ActuatorPermissionFilter :
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 as a monitoring page
Additional dependencies
<dependency>
<groupId>cn.pomit</groupId>
<artifactId>spring-boot-monitor</artifactId>
<version>0.0.1</version>
</dependency>
Spring Boot Monitor is a monitoring tool that modifies the Spring boot admin monitoring tool and adapts to a single machine. It perfectly inherits the style of Spring boot admin and directly uses the indicators of the actuator to display.
Spring Boot Monitor official website: https://www.pomit.cn/SpringBootMonitor
In the previous maven dependency, it has been stated that it depends on spring-boot-monitor. At this time, no other configuration is required.
Access http://127.0.0.1:8080/monitor
, automatically jump to the monitoring page of Spring Boot Monitor.
The monitoring page of Spring Boot Monitor is exactly the same as that of Spring boot admin, and the front-end functions are also exactly the same.
You can see all the indicators of Spring boot at a glance, and you can also perform simple operations.
Of course, if the indicators of the Spring boot actuator are restricted, it will not be able to get the corresponding indicators, because it directly requests the actuator interface.
Source: blog.csdn.net/yunfeather/
article/details/122581536