Spring Boot+Docker环境下Actuator/Prometheus请求超时问题排查
执行docker-compose up -d后所有服务启动正常,本地访问localhost:1221/actuator/prometheus可正常获取如下指标数据:
# HELP jvm_buffer_count_buffers An estimate of the number of buffers in the pool # TYPE jvm_buffer_count_buffers gauge jvm_buffer_count_buffers{id="mapped - 'non-volatile memory'",} 0.0 jvm_buffer_count_buffers{id="mapped",} 0.0 jvm_buffer_count_buffers{id="direct",} 9.0 # HELP spring_security_filterchains_requestcache_before_total # TYPE spring_security_filterchains_requestcache_before_total counter spring_security_filterchains_requestcache_before_total{security_security_reached_filter_section="before",spring_security_filterchain_position="0",spring_security_filterchain_size="0",spring_security_reached_filter_name="none",} 7.0 ....
但访问http://localhost:9090/targets时,Prometheus提示如下错误:
Get "http://book-delivery-app-1:1221/actuator/prometheus": context deadline exceeded
相关配置文件
docker-compose.yml
version: "3.9" services: database: container_name: database image: mysql:8.0.33 restart: always env_file: - .env # 使用.env文件存储环境变量 environment: MYSQL_DATABASE: bookdelivery MYSQL_PASSWORD: ${DATABASE_PASSWORD} MYSQL_ROOT_PASSWORD: ${DATABASE_PASSWORD} MYSQL_ROOT_HOST: '%' MYSQL_PORT: 3307 volumes: - ./db:/var/lib/mysql ports: - "3307:3306" networks: - bookDeliveryNetwork bookdelivery: image: 'bookdelivery:latest' build: context: . dockerfile: Dockerfile container_name: bookdelivery restart: on-failure env_file: - .env # 使用.env文件存储环境变量 ports: - "1221:1221" environment: - server.port=1221 - spring.datasource.username=${DATABASE_USERNAME} - spring.datasource.password=${DATABASE_PASSWORD} - BOOK_DELIVERY_DB_IP=database - BOOK_DELIVERY_DB_PORT=3307 - spring.datasource.url=jdbc:mysql://host.docker.internal:3307/bookdelivery depends_on: - database networks: - bookDeliveryNetwork prometheus: image: prom/prometheus:v2.35.0 container_name: prometheus restart: unless-stopped ports: - "9090:9090" volumes: - ./data/prometheus/config:/etc/prometheus/ command: - '--config.file=/etc/prometheus/prometheus.yml' networks: - bookDeliveryNetwork grafana: image: grafana/grafana-oss:8.5.2 pull_policy: always container_name: grafana restart: unless-stopped ports: - "3000:3000" volumes: - ./data/grafana:/var/lib/grafana environment: - GF_SECURITY_ADMIN_PASSWORD=admin - GF_SERVER_DOMAIN=localhost networks: - bookDeliveryNetwork networks: bookDeliveryNetwork:
prometheus.yml
global: scrape_interval: 120s # 默认每15秒抓取一次目标,此处修改为120秒 evaluation_interval: 120s # 默认每15秒评估一次规则,此处修改为120秒 # 抓取配置,包含一个要抓取的端点: # 这里是Prometheus自身 scrape_configs: # 作业名称会作为标签`job=<job_name>`添加到从此配置抓取的所有时间序列中 - job_name: 'prometheus' # 覆盖全局默认,每5秒抓取一次此作业的目标 scrape_interval: 5s # metrics_path默认为'/metrics' # scheme默认为'http' static_configs: - targets: ['localhost:9090'] - job_name: 'Spring Boot Application input' metrics_path: '/actuator/prometheus' scrape_interval: 2s static_configs: - targets: [ 'book-delivery-app-1:1221' ] labels: application: 'Book Delivery API'
问题根源与修复方案
1. 核心问题:Prometheus目标地址错误
在Docker自定义网络bookDeliveryNetwork中,服务间通信必须使用服务名称或容器名称作为访问地址,而非Docker自动生成的容器前缀名book-delivery-app-1。你的Spring Boot服务在docker-compose中定义的container_name是bookdelivery,服务名也是bookdelivery,Prometheus无法解析不存在的book-delivery-app-1地址,导致请求超时。
2. 修复步骤
步骤1:修正Prometheus配置
修改prometheus.yml中的Spring Boot抓取目标,将:
targets: [ 'book-delivery-app-1:1221' ]
改为:
targets: [ 'bookdelivery:1221' ]
步骤2:优化Spring Boot数据库连接配置(可选但推荐)
当前bookdelivery服务的spring.datasource.url使用了host.docker.internal:3307,在自定义Docker网络中,服务间应直接通过服务名访问容器内部端口,而非主机映射端口。将其改为:
spring.datasource.url=jdbc:mysql://database:3306/bookdelivery
此修改可避免依赖主机端口映射,让服务间通信更稳定。
步骤3:重启服务
执行以下命令重启Prometheus(或整个docker-compose服务栈):
# 仅重启Prometheus docker-compose restart prometheus # 或重启所有服务 docker-compose down && docker-compose up -d
内容的提问来源于stack exchange,提问作者Sercan Noyan Germiyanoğlu

