

【中间件】Prometheus基于AOP实现埋点采集上报
source link: https://spring.hhui.top/spring-blog/2021/12/22/211222-SpringBoot%E7%B3%BB%E5%88%97%E4%B9%8BPrometheus%E5%9F%BA%E4%BA%8EAOP%E5%AE%9E%E7%8E%B0%E5%9F%8B%E7%82%B9%E9%87%87%E9%9B%86%E4%B8%8A%E6%8A%A5/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

【中间件】Prometheus基于AOP实现埋点采集上报
前面几篇文章介绍了SpringBoot继承Prometheus实现埋点上报,基本上可以非常简单的实现采样收集,对于由SpringBoot搭建的web应用,甚至是可以说是引入依赖,简单的配置下,剩下的啥也不用管,就可以配置一个REST应用的监控大盘
接下来我们通过AOP的方式,来定义一个自定义数据采集的功能,用于实现一些上面覆盖不到的场景(如应用内的定时任务执行情况,三方接口请求监控等)
I. 方案确定与环境搭建
1.metric选择
通过前面的几篇文章,至少我们会了解到Prometheus的四种Metric,对于自定义的数据采集,根据最终希望监控的指标(每秒请求数 qps, 响应耗时 rt, 可用率 sla, 请求分布),我们这里选择Histogram
- 通过histogram指标中的 count 值来计算qps
- 通过 sum / count 来计算rt
- 通过
成功数 / 总请求数
计算可用率sla - 通过histogram的bucket分布来查看请求分布
2.项目依赖
本项目借助SpringBoot 2.2.1.RELEASE
+ maven 3.5.3
+ IDEA
进行开发
其核心pom依赖,主要是下面几个包
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.2.1.RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
3. 配置信息
其次是配置文件,注册下Prometheus的相关信息
spring:
application:
name: spring-prometheus-metric
management:
endpoints:
web:
exposure:
include: "*"
metrics:
tags:
application: ${spring.application.name}
上面配置中,有两个关键信息,前面博文也有介绍,这里简单说明
management.endpoints.web.exposure.include
这里指定所有的web接口都会上报metrics.tags.application
这个应用所有上报的metrics 都会带上application这个标签
配置完毕之后,会提供一个 /actuator/prometheus
的端点,供prometheus来拉取Metrics信息
II. AOP切面实现埋点上报
1. 切面实现类
通过切面来拦截目标类的执行,选择三个关键指标
- service: 表示具体执行的类
- method:执行的方法
- err: true 表示执行异常/else 表示执行正常
直接使用Histogram来实现数据采集上报,直接使用前面博文* 【中间件】Prometheus自定义埋点姿势二 | 一灰灰Blog 使用姿势即可
@Aspect
@Component
public class MetricAop {
@Autowired
private MeterRegistry meterRegistry;
@Pointcut("execution(public * com.git.hui.demo.prometheus.service.*.*(..))")
public void point() {
}
/**
* 拦截Service共有方法,上报接口执行情况到Prometheus
*
* @param joinPoint
* @return
* @throws Throwable
*/
@Around("point()")
public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
String service = joinPoint.getTarget().getClass().getSimpleName();
String method = joinPoint.getSignature().getName();
Timer.Sample sample = Timer.start();
boolean hasError = false;
try {
return joinPoint.proceed();
} catch (Throwable e) {
hasError = true;
throw e;
} finally {
Timer timer = Timer.builder("micro_service_histogram")
.minimumExpectedValue(Duration.ofMillis(1))
.maximumExpectedValue(Duration.ofMinutes(3))
.sla(Duration.ofMillis(10), Duration.ofMillis(50), Duration.ofMillis(100), Duration.ofMillis(300), Duration.ofMillis(1000))
.tags(Tags.of("service", service, "method", method, "err", String.valueOf(hasError)))
.register(meterRegistry);
sample.stop(timer);
}
}
}
2. 测试方法
这里写两个简单的Service类,作为收集采样的目标
@Service
public class DemoService {
private Random random = new Random();
// 用于控制方法的执行耗时
private void trySleep() {
try {
Thread.sleep(random.nextInt(50));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public int add(int a, int b) {
trySleep();
return a + b;
}
public int sub(int a, int b) {
trySleep();
return a - b;
}
public int divide(int a, int b) {
trySleep();
return a / b;
}
}
@Service
public class HelloService {
private Random random = new Random();
private void trySleep() {
try {
Thread.sleep(random.nextInt(100) + 100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public String hello(String name) {
trySleep();
return "hello: " + name;
}
public String welcome(String name) {
trySleep();
return "welcome: " + name;
}
}
然后我们通过定时任务来不断的访问上面的服务方法,用来模拟请求场景
@Autowired
private DemoService demoService;
@Autowired
private HelloService helloService;
private Random random = new Random();
private void call(Runnable runnable, CountDownLatch latch) {
new Thread(() -> {
try {
runnable.run();
} finally {
latch.countDown();
}
}).start();
}
// 100ms请求一次,基本上接口的qps在10左右
@Async("main")
@Scheduled(fixedDelay = 100)
public void doDemoCall() {
CountDownLatch latch = new CountDownLatch(3);
call(() -> demoService.add(random.nextInt(10), random.nextInt(30)), latch);
call(() -> demoService.sub(random.nextInt(10), random.nextInt(30)), latch);
// 注意这个divide,分母是可能存在为0的哦
call(() -> demoService.divide(random.nextInt(10), random.nextInt(30)), latch);
latch.countDown();
}
@Async
@Scheduled(fixedDelay = 100)
public void doHelloCall() {
CountDownLatch latch = new CountDownLatch(2);
call(() -> helloService.hello("YiHui " + random.nextInt(30)), latch);
call(() -> helloService.welcome("YiHui " + random.nextInt(30)), latch);
latch.countDown();
}
3. 启动类
最后就是在启动类中注册一下MeterRegistryCustomizer,为所有的metric携带上application
标签
@EnableScheduling
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
@Bean
MeterRegistryCustomizer<MeterRegistry> configurer(@Value("${spring.application.name}") String applicationName) {
return (registry) -> {
registry.config().commonTags("application", applicationName);
MetricWrapper.setMeterRegistry(registry);
};
}
}
应用启动之后,就可以通过http://m-162d9nnes031u:8080/actuator/prometheus
来查看收集的采样信息了,如
4. 业务大盘配置
上面基本即实现了一个基于aop的采样收集,接下来重点就是如何将这些收集上来的数据,可视化配置起来
借助Grafana无疑是个比较推荐的case,下一篇博文将详细介绍如何针对上面收集的信息进行友好的配置,欢迎有兴趣的小伙伴关注吐槽
III. 不能错过的源码和相关知识点
0. 项目源码
系列博文:
1. 微信公众号: 一灰灰Blog
尽信书则不如,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激
下面一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛
一灰灰blog
Recommend
-
34
数据采集是数据分析的基础,而埋点是最主要的采集方式。那么数据埋点采集到底都包括哪些问题?本文作者从什么是埋点、埋点怎么设计、埋点的应用三个方面对这个问题进行了梳理,与大家分享。
-
6
【中间件】Prometheus实现应用监控 | 一灰灰Blog 1. prometheus 安装
-
5
之前介绍了一篇SpringBoot集成Prometheus实现数据上报的博文,在前面一篇博...
-
3
关于Prometheus的自定义埋点,前一篇博文已经介绍了,为啥这里又来一次?
-
12
相关知识点 什么是AST抽象语法树 程序的编译过程 AST的用途 Babel的原理 个人实现的基于babel的埋点实例及思考
-
8
Prometheus监控Kubernetes系列3——业务指标采集 · Service Mesh|服务网格中文社区 由于容器化和微服务的大力发展,Kubernetes基本已经统一了容器管理方案,当我们使用Kubernetes来进行容器化管理的时候,全面监控Ku...
-
13
使用 Vmagent 代替 Prometheus 采集监控指标-51CTO.COM 使用 Vmagent 代替 Prometheus 采集监控指标 作者:阳明 2022-05-12 08:01:26 我们以抓取 Kubernetes 集群指标为例说明如何使用...
-
6
前端埋点对于那些营销活动的项目是必须的,它可以反应出用户的喜好与习惯,从而让项目的运营者们能够调整策略优化流程提高用户体验从而获取更多的$。这篇文章将实现一个Vue3版本的埋点上报插件,主要功能有 通过Vue自定义指令形式实现点击事件上报
-
8
恩不想搭建太多prometheus了,想用一个prometheus,当然了 前提是我A集群可以连通B集群网络,实现 Prometheus跨集群采集采集 关于A集群 A集群 以及prometheus搭建 参照:
-
11
基于matomo实现业务数据埋点采集上报
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK