记录开发微服务监控的坑spring actuator、spring boot admin、prometheus、grafana

常规前置操作:看文档写demo

开整,首先引入依赖,将actuator的数据转换成Prometheus需要的格式

        <!--    actuator begin    -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--集成prometheus客户端,将actuator监控的指标转为prometheus格式-->
        <dependency>
            <groupId>io.micrometer</groupId>
            <artifactId>micrometer-registry-prometheus</artifactId>
        </dependency>
        <!--    actuator end   -->

docker拉取prometheus镜像并安装参考

https://blog.csdn.net/qq_26462567/article/details/108501175

我的配置

#普罗米修斯docker配置
sudo docker run -d -p 9090:9090 --name prom -v /data/prometheus/data/prometheus.yml:/etc/prometheus/prometheus.yml  bitnami/prometheus
#这里注意普罗米修斯配置文件在容器的/etc/prometheus/prometheus.yml下,做数据卷映射的时候要匹配,或者可以用--config指定配置文件

prometheus的配置文件如下prometheus.yml,采集路径配置的是actuator暴露的prometheus端点地址。

scrape_configs:
  # 任意写,建议英文,不要包含特殊字符
  - job_name: 'test'
    # 采集的间隔时间
    scrape_interval: 15s
    # 采集时的超时时间
    scrape_timeout: 10s
    # 采集路径
    metrics_path: '/actuator/prometheus'
    # 采集服务的地址,也就是我们应用的地址
    static_configs:
      - targets: [192.168.206.1:9011']

整完以上内容先访问要监控的应用的端点信息http://ip:port/actuator/prometheus
在这里插入图片描述
看似没有问题!!!!!!

第一坑 spring actuator 整合Prometheus报错: “INVALID” “”" is not a valid start token

然后打开http://192.168.206.129:9090/targets普罗米修斯监控页面报错"INVALID" “”" is not a valid start token
在这里插入图片描述
这是神马情况?查看报错信息 :" 不是有效的开头,查找了半天发现是消息格式不对。为什么不对呢。再找了半天,发现项目配置了json序列化

@Configuration
public class HttpConverterConfig {

    @Bean
    public HttpMessageConverters fastJsonHttpMessageConverters() {
        FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat,
                SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.WriteMapNullValue,
                SerializerFeature.WriteNullStringAsEmpty, SerializerFeature.WriteNullListAsEmpty);

        //解决中文乱码问题:在方法内部添加这段代码
        List<MediaType> fastMediaTypes = new ArrayList<>();
        fastMediaTypes.add(MediaType.APPLICATION_JSON);
        fastMediaTypes.add(MediaType.ALL);
        fastConverter.setSupportedMediaTypes(fastMediaTypes);

        fastConverter.setFastJsonConfig(fastJsonConfig);
        return new HttpMessageConverters(fastConverter);
    }

}

导致返回的json被再一次编码,所以报错。把序列化去掉后正确的消息格式`
在这里插入图片描述

第二坑 关于micrometer的方法监控切面TimedAspect和@Time注解了方法,访问http://ip:port/actuator/metrics 却找不到相应的metrics问题

actuator集成了micrometer,micrometer提供了方法级的监控,只需要在方法上注解@Timed(“sample.controller”),sample.controller就是metrics的标签,

@RestController
@RequestMapping(path = "/sample")
public class SampleController {

	private final SampleService sampleService;

	public SampleController(SampleService sampleService) {
		this.sampleService = sampleService;
	}

	@Timed("sample.controller")
	@GetMapping("/call-rest-template")
	public Map<String, Object> callRestTemplate() {
		return this.sampleService.callRestTemplate();
	}

}

然后将TimedAspect 切面注入容器

@Configuration
@EnableAspectJAutoProxy
public class MetricsConfig {
	@Bean
	public TimedAspect timedAspect(MeterRegistry registry) {
		return new TimedAspect(registry);
	}
}

接着访问http://ip:port/actuator/metrics,????找不到相应的metrics

{
    "names": [
        "jvm.buffer.count",
        "jvm.buffer.memory.used",
        "jvm.buffer.total.capacity",
        "jvm.classes.loaded",
        "jvm.classes.unloaded",
        "jvm.gc.live.data.size",
        "jvm.gc.max.data.size",
        "jvm.gc.memory.allocated",
        "jvm.gc.memory.promoted",
        "jvm.gc.pause",
        "jvm.memory.committed",
        "jvm.memory.max",
        "jvm.memory.used",
        "jvm.threads.daemon",
        "jvm.threads.live",
        "jvm.threads.peak",
        "jvm.threads.states",
        "logback.events",
        "process.cpu.usage",
        "process.start.time",
        "process.uptime",
        "system.cpu.count",
        "system.cpu.usage",
        "tomcat.sessions.active.current",
        "tomcat.sessions.active.max",
        "tomcat.sessions.alive.max",
        "tomcat.sessions.created",
        "tomcat.sessions.expired",
        "tomcat.sessions.rejected"
    ]
}

分析TimedAspect源码发现,在进入切面后调用processWithTimer,processWithTimer调用record,此时才进行metrics的注册。得出原因,需要访问一次@Time注解了的方法才能将这个指标注册。

    @Around("execution (@io.micrometer.core.annotation.Timed * *.*(..))")
    public Object timedMethod(ProceedingJoinPoint pjp) throws Throwable {
		//............省略一万行
        if (!timed.longTask()) {
            return processWithTimer(pjp, timed, metricName, stopWhenCompleted);
        } 
        //............省略一万行
    }
    private Object processWithTimer(ProceedingJoinPoint pjp, Timed timed, String metricName, boolean stopWhenCompleted) throws Throwable {

       //............省略一万行

        if (stopWhenCompleted) {
            try {
                return ((CompletionStage<?>) pjp.proceed()).whenComplete((result, throwable) ->
                        record(pjp, timed, metricName, sample, getExceptionTag(throwable)));
            } 
            //............省略一万行
    }
    private void record(ProceedingJoinPoint pjp, Timed timed, String metricName, Timer.Sample sample, String exceptionClass) {
        try {
            sample.stop(Timer.builder(metricName)
                    .description(timed.description().isEmpty() ? null : timed.description())
                    .tags(timed.extraTags())
                    .tags(EXCEPTION_TAG, exceptionClass)
                    .tags(tagsBasedOnJoinPoint.apply(pjp))
                    .publishPercentileHistogram(timed.histogram())
                    .publishPercentiles(timed.percentiles().length == 0 ? null : timed.percentiles())
                    .register(registry));
        } catch (Exception e) {
            // ignoring on purpose
        }
    }

访问测试接口http://localhost:8080/sample/call-rest-template后再次调用http://localhost:8080/actuator/metrics

{
    "names": [
        "http.client.requests",
        "http.server.requests",
        "jvm.buffer.count",
        "jvm.buffer.memory.used",
        "jvm.buffer.total.capacity",
        "jvm.classes.loaded",
        "jvm.classes.unloaded",
        "jvm.gc.live.data.size",
        "jvm.gc.max.data.size",
        "jvm.gc.memory.allocated",
        "jvm.gc.memory.promoted",
        "jvm.gc.pause",
        "jvm.memory.committed",
        "jvm.memory.max",
        "jvm.memory.used",
        "jvm.threads.daemon",
        "jvm.threads.live",
        "jvm.threads.peak",
        "jvm.threads.states",
        "logback.events",
        "process.cpu.usage",
        "process.start.time",
        "process.uptime",
        "sample.controller",	<-------------找到sample.controller
        "system.cpu.count",
        "system.cpu.usage",
        "tomcat.sessions.active.current",
        "tomcat.sessions.active.max",
        "tomcat.sessions.alive.max",
        "tomcat.sessions.created",
        "tomcat.sessions.expired",
        "tomcat.sessions.rejected"
    ]
}

访问http://localhost:8080/actuator/metrics/sample.controller

{
  "name" : "sample.controller",
  "description" : null,
  "baseUnit" : "seconds",
  "measurements" : [ {
    "statistic" : "COUNT",
    "value" : 2.0
  }, {
    "statistic" : "TOTAL_TIME",
    "value" : 2.4237243
  }, {
    "statistic" : "MAX",
    "value" : 0.0
  } ],
  "availableTags" : [ {
    "tag" : "exception",
    "values" : [ "None", "none" ]
  }, {
    "tag" : "method",
    "values" : [ "callRestTemplate", "GET" ]
  }, {
    "tag" : "uri",
    "values" : [ "/sample/call-rest-template" ]
  }, {
    "tag" : "class",
    "values" : [ "com.izeye.sample.web.SampleController" ]
  }, {
    "tag" : "outcome",
    "values" : [ "SUCCESS" ]
  }, {
    "tag" : "status",
    "values" : [ "200" ]
  } ]
}

后续改造自动注册metrics

未完待续

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值