背景
项目中部署prometheus的时候,最开始如果需要额外添加一台机器,需要手动更新prometheus的配置文件,再重新启动,如果是正式生产环境存在大量的机器的情况,这种方式有很大的运维成本。于是想如果能让prometheus自动发现要添加的应用实例,则可以免去手动添加的繁琐操作。组内项目有使用eureka做服务发现,它也有对应的API开放,就想如果能够集成eureka会方便很多。开始想的是自己写个脚本(如python)从eureka获取注册的实例,然后写到配置里,使用prometheus的文件服务发现,然后做reload实现。
好在后续调研发现,在新版本的prometheus已经支持了集成eureka,只需要添加配置就可以实现想要的功能。
说明
使用的prometheus版本是2.22.0
。项目中使用prometheus + micrometer进行基础的JVM、http、数据库、线程池以及业务的可用度、耗时监控,这块后面单独再写文章详细介绍,下面会简单介绍。只要知道在完成后,会通过在actuator/prometheus
暴露各项指标,然后由prometheus拉取,实现数据的采集。
springboot actuator集成prometheus
- 依赖
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient_common</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
<version>1.5.1</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<version>1.5.1</version>
</dependency>
- 配置
添加application.yml
management:
endpoints:
enabled-by-default: true
web:
exposure:
include: ['pause','prometheus']
endpoint:
pause:
enabled: true
prometheus:
enabled: true
server:
port: 8293
servlet:
context-path: /api # 给actuator也设置context-path 这个配置在springboot 2.4 0 之后,改为base-path, 相应eureka配置也要修改
这里基于安全考虑对actuator添加了额外的端口,和服务端口不一样。因此,在本地eureka的配置中添加一个metadataMap.prometheus.port
项。这个会保存到eureka的metadata,然后被prometheus eureka sd解析到。如下:
eureka:
instance:
prefer-ip-address: true
lease-renewal-interval-in-seconds: 10
metadataMap.prometheus.port: 8293
加几个自定义标签,比如这里设置application为业务名,以及添加一个idc表示业务部署机房。
@Slf4j
@Configuration
public class PrometheusConfiguration {
private final Tags commonTags = Tags.of("application", "myapp", "idc", System.getProperty("idc"));
@Autowired
private MeterRegistry meterRegistry;
@Bean
public MeterRegistryCustomizer<MeterRegistry> configurer() {
//key value
//log4j 的用不到,排除掉
return (registry) -> registry.config().commonTags(commonTags).meterFilter(MeterFilter.denyNameStartsWith("log4j")).pauseDetector();
}
}
- 结果示例
项目集成完成后启动,访问yourapp:port/actuator/prometheus
得到prometheus的待采集数据
# HELP jvm_memory_used_bytes The amount of used memory
# TYPE jvm_memory_used_bytes gauge
jvm_memory_used_bytes{application="myapp",area="nonheap",id="Code Cache",idc="staging",} 1.20810432E8
jvm_memory_used_bytes{application="myapp",area="nonheap",id="Metaspace",idc="staging",} 1.5934492E8
jvm_memory_used_bytes{application="myapp",area="heap",id="G1 Old Gen",idc="staging",} 2.54245616E8
jvm_memory_used_bytes{application="myapp",area="heap",id="G1 Eden Space",idc="staging",} 2.0447232E8
jvm_memory_used_bytes{application="myapp",area="nonheap",id="Compressed Class Space",idc="staging",} 1.8597632E7
jvm_memory_used_bytes{application="myapp",area="heap",id="G1 Survivor Space",idc="staging",} 8388608.0
配置
然后我们添加prometheus的配置,让其自动发现我们注册到eureka的服务实例。
scrape_configs:
# The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
- job_name: 'prometheus'
# metrics_path defaults to '/metrics'
# scheme defaults to 'http'.
static_configs:
- targets: ['localhost:9090']
#原先静态配置的targets,需要重启和改配置文件
# - job_name: 'myapp'
# metrics_path: '/actuator/prometheus'
# scrape_interval: 5s
# static_configs:
# - targets: ['myapp1:8157', 'myapp2:8157']
- job_name: 'eureka_sd'
eureka_sd_configs:
- server: 'http://my_eureka.server:port/eureka' #注意这里地址后面是eureka
basic_auth:
username: 'myuser'
password: 'mypass' # 应用对/actuator添加了spring security http basic验证
relabel_configs:
- source_labels: [__address__, __meta_eureka_app_instance_metadata_prometheus_port]
action: replace
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
target_label: __address__
metrics_path: '/actuator/prometheus' #采集地址
之后重启prometheus服务或者reload配置,然后在prometheus的管理界面访问/service-discovery
,就可以看到通过eureka服务发现添加的实例。配置中relablel_configs
的部分,可以通过对原始标签对应内容的匹配过滤,生成新的标签内容。比如根据eureka注册的实例名称和端口,生成新的目标标签。
总结
以上就是本期的所有内容。目前对于prometheus的应用比较初级,其实还有许多要解决的问题,首先是数据的持久化,本来考虑支持openTSDB,公司也有内部资源支持,但是openTSDB查询对于模糊查询支持不太好,且公司的资源维护也在起步阶段,试用后发现有些问题,再者没有很好的兼容grafana
。因此,还是使用在单机的prometheus本地tsdb存储;其次,对于报警方面目前还没有深入调研,我们知道监控和报警一般是相辅相成的;最后就是prometheus服务本身的HA这块,也需要再做了解。