前人栽树 下面基本都是这篇博客的东西,搭建过程中也遇到一些问题,算是做个备份吧

需要有docker环境,大家可以看其他博客搞一下

部署Prometheus

docker部署

$ docker run --name prometheus -d -p 9090:9090 prom/prometheus

-p后不要定义127.0.0.1,不然通过浏览器无法访问,还需要改ports映射关系

Prometheus获取springboot项目监控指标

  1. 拷贝配置文件
#查看配置文件内容
$ docker exec -it [容器ID] cat /etc/prometheus/prometheus.yml
#拷贝到当前目录
$ docker cp [容器ID]:/etc/prometheus/prometheus.yml .
  1. 配置文件末尾添加节点
- job_name: 'springboot_app'
    scrape_interval: 5s
    metrics_path: '/actuator/prometheus'
    static_configs:
      - targets: ['192.168.31.6:8080']
        "labels": {
            "instance": "springboot2-A",
            "service": "springboot2-A-service"
        }

metrics_path :指定监控端点的路径。

targets :指定应用的IP端口,这里使用了IP(如果监控项目和Prometheus在一台服务器上,不要用127.0.0.1,尽量使用公网ip或局域网ip),没有使用localhost,因为 Prometheus 是容器运行的,如果使用 localhost 就会访问容器内部。

  1. 停掉之前的容器,重新启动新容器
$ docker run --name prometheusnew -d \
    -p 9090:9090 \
    -v [PATH]/prometheus.yml:/etc/prometheus/prometheus.yml \
    prom/prometheus

注意这里[PATH]替换为拷贝的配置文件绝对路径
prometheus需要换一个名字,我这里换成了prometheusnew,不然启动不了,其实就是新启动了一个docker,之前的可以停掉或者移除

grafan添加官方demo_spring boot

部署 Grafana

$ docker run -d \
    -p 3000:3000 \
    --name=grafana \
    grafana/grafana

默认用户名密码 admin/admin

添加 Prometheus 数据源

grafan添加官方demo_配置文件_02

选择Prometheus

grafan添加官方demo_docker_03


grafan添加官方demo_spring boot_04

展示应用的 JVM 信息

Grafana 中已经有现成的 JVM 仪表盘,我们直接导入使用即可。

这个仪表盘的编号为 4701。

grafan添加官方demo_spring boot_05

grafan添加官方demo_spring_06


效果图

grafan添加官方demo_spring_07


至此,Prometheus + Grafana + Springboot 的整体流程已经跑通了

自定义监控指标

pom文件

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--<dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-starter-client</artifactId>
            <version>2.2.3</version>
        </dependency>-->
        <dependency>
            <groupId>io.micrometer</groupId>
            <artifactId>micrometer-registry-prometheus</artifactId>
        </dependency>

aop计算请求量

package com.rookie.csdntestdemo.aop;

import com.rookie.csdntestdemo.utils.JacksonUtil;
import com.rookie.csdntestdemo.utils.RequestParseUtil;
import com.rookie.csdntestdemo.utils.ThreadLocalContext;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Objects;

@Aspect
@Component
public class WebLogAspect {
    private static final Logger LOGGER = LoggerFactory.getLogger(WebLogAspect.class);


    @Resource
    private MeterRegistry registry;
    // 统计请求次数
    private Counter counter;

    @PostConstruct
    private void init() {
        counter = registry.counter("info_requests_total", "count", "qps");
    }

    public WebLogAspect() {
    }

    @Pointcut("execution(public * com..*.controller..*.*(..))")
    public void webLog() {
    }

    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) throws IOException {
        counter.increment();
    }


    @AfterReturning(
            returning = "ret",
            pointcut = "webLog()"
    )
    public void doAfter(JoinPoint joinPoint, Object ret) {
        LOGGER.info("RESPONSE : [{}], COST : {}ms", JacksonUtil.toJson(ret), (System.currentTimeMillis() - ThreadLocalContext.getStartTime()));
        ThreadLocalContext.clear();
    }
}

配置文件

#开启全部端点
management.endpoints.web.exposure.include=*
management.metrics.tags.application=${spring.application.name}

重启应用,多访问几次测试接口,然后查看 Prometheus 中的应用监控端点页面(http://localhost:9000/actuator/prometheus,ip、端口换成自己的服务),就可以看到监控结果:

grafan添加官方demo_spring boot_08


这就是之后在grafna配置的监控字段

grafan添加官方demo_spring_09


这使用了rate函数,貌似是qps…,很神奇,函数待之后探索

动态变更监控目标

上面 Prometheus 配置文件中定义的监控目标使用的是静态方式,改配置文件后需要重启。

如果服务变更了,或者增加服务了,经常重启 Prometheus 肯定不合适。

Prometheus 提供了动态加载的方式,把服务信息放到一个单独的文件中,Prometheus 配置中指定这个外部文件,内容变化后,Prometheus 就会自动重新加载。

服务信息配置文件例如:

[
    {
        "targets": [
            "192.168.31.6:8080"
        ],
        "labels": {
            "instance": "springboot2-A",
            "service": "springboot2-A-service"
        }
    }
]

Prometheus 配置文件中的写法:

- job_name: 'springboot_app'
    scrape_interval: 5s
    metrics_path: '/actuator/prometheus'
    file_sd_configs:
    - files:
      - /home/*.json
      refresh_interval: 1m

启动 Prometheus 容器时要挂载这个服务信息配置文件的目录:

$ docker run --name prometheus -d -p 9090:9090 \
    -v [PATH]/prometheus.yml:/etc/prometheus/prometheus.yml \
    -v [PATH]:/home \
    prom/prometheus