Appearance
Spring Boot Actuator Info 端点详解 📊
什么是 Info 端点?
Spring Boot Actuator 的 info
端点就像是你应用程序的"身份证",它提供了关于应用程序的基本信息。想象一下,当你需要快速了解一个正在运行的应用程序时,你会想知道什么?版本号、构建信息、运行环境等等,这些都是 info
端点能够告诉你的。
NOTE
Info 端点是 Spring Boot Actuator 提供的监控端点之一,主要用于暴露应用程序的元数据信息,帮助运维人员和开发者快速了解应用程序的基本情况。
为什么需要 Info 端点? 🤔
在微服务架构中,我们经常面临这样的问题:
- 版本混乱:生产环境运行的到底是哪个版本?
- 环境不明:这个服务运行在什么操作系统上?使用的是哪个 Java 版本?
- 构建信息缺失:这个版本是什么时候构建的?基于哪个 Git 分支?
- 资源使用情况:当前进程使用了多少内存?有多少 CPU 核心可用?
Info 端点就是为了解决这些问题而生的!
快速开始 🚀
1. 添加依赖
首先,确保你的项目中包含了 Actuator 依赖:
kotlin
dependencies {
implementation("org.springframework.boot:spring-boot-starter-actuator")
implementation("org.springframework.boot:spring-boot-starter-web")
}
xml
<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>
</dependencies>
2. 配置端点暴露
在 application.yml
中配置:
yaml
management:
endpoints:
web:
exposure:
include: info
endpoint:
info:
enabled: true
3. 访问 Info 端点
启动应用后,访问:http://localhost:8080/actuator/info
Info 端点的工作原理 ⚙️
Info 端点通过 InfoContributor
接口收集各种信息。Spring Boot 内置了多个贡献者:
响应结构详解 📋
完整响应示例
当你访问 /actuator/info
时,会得到类似这样的响应:
json
{
"git": {
"branch": "main",
"commit": {
"id": "df027cf",
"time": "2025-05-22T20:03:14Z"
}
},
"build": {
"artifact": "application",
"version": "1.0.3",
"group": "com.example"
},
"os": {
"name": "Linux",
"version": "6.11.0-1014-azure",
"arch": "amd64"
},
"process": {
"pid": 90556,
"parentPid": 89245,
"owner": "runner",
"memory": {
"heap": {
"max": 1610612736,
"committed": 173015040,
"used": 80645120,
"init": 262144000
},
"nonHeap": {
"max": -1,
"committed": 95682560,
"used": 93349504,
"init": 7667712
},
"garbageCollectors": [{
"name": "G1 Young Generation",
"collectionCount": 15
}]
},
"cpus": 4
},
"java": {
"version": "17.0.15",
"vendor": {
"name": "BellSoft"
},
"runtime": {
"name": "OpenJDK Runtime Environment",
"version": "17.0.15+10-LTS"
},
"jvm": {
"name": "OpenJDK 64-Bit Server VM",
"vendor": "BellSoft",
"version": "17.0.15+10-LTS"
}
}
}
各部分信息解析
🏗️ Build 信息
包含应用程序的构建相关信息:
字段 | 类型 | 描述 |
---|---|---|
artifact | String | 项目的 artifact ID |
group | String | 项目的 group ID |
name | String | 应用程序名称 |
version | String | 应用程序版本 |
time | Varies | 构建时间戳 |
🌿 Git 信息
包含版本控制相关信息:
字段 | 类型 | 描述 |
---|---|---|
branch | String | Git 分支名称 |
commit.id | String | 提交 ID |
commit.time | Varies | 提交时间戳 |
💻 操作系统信息
包含运行环境的系统信息:
字段 | 类型 | 描述 |
---|---|---|
name | String | 操作系统名称 |
version | String | 操作系统版本 |
arch | String | 系统架构 |
🔄 进程信息
包含当前 Java 进程的详细信息:
字段 | 类型 | 描述 |
---|---|---|
pid | Number | 进程 ID |
parentPid | Number | 父进程 ID |
owner | String | 进程所有者 |
cpus | Number | 可用 CPU 核心数 |
memory.heap.* | Object | 堆内存信息 |
memory.nonHeap.* | Object | 非堆内存信息 |
☕ Java 信息
包含 Java 运行时环境信息:
字段 | 类型 | 描述 |
---|---|---|
version | String | Java 版本 |
vendor.name | String | JVM 厂商名称 |
runtime.name | String | 运行时名称 |
jvm.name | String | JVM 名称 |
实际应用场景 🎯
场景1:版本确认
在生产环境部署后,运维人员可以快速确认部署的版本:
bash
# 快速检查生产环境版本
curl -s http://prod-server:8080/actuator/info | jq '.build.version'
# 输出: "1.0.3"
场景2:问题排查
当应用出现内存问题时,可以查看内存使用情况:
bash
# 检查内存使用情况
curl -s http://localhost:8080/actuator/info | jq '.process.memory.heap'
场景3:环境验证
确认应用运行在正确的环境中:
bash
# 检查运行环境
curl -s http://localhost:8080/actuator/info | jq '{os: .os, java: .java.version}'
自定义 Info 信息 🛠️
方式1:配置文件添加
在 application.yml
中添加自定义信息:
yaml
info:
app:
name: "我的应用程序"
description: "这是一个示例应用"
contact:
email: "[email protected]"
phone: "123-456-7890"
team:
name: "开发团队A"
lead: "张三"
方式2:自定义 InfoContributor
创建自定义的信息贡献者:
kotlin
@Component
class CustomInfoContributor : InfoContributor {
override fun contribute(builder: Info.Builder) {
// 添加数据库连接信息
val dbInfo = mapOf(
"url" to getDataSourceUrl(),
"driver" to "MySQL",
"poolSize" to getCurrentPoolSize()
)
// 添加缓存信息
val cacheInfo = mapOf(
"type" to "Redis",
"nodes" to getRedisNodes(),
"hitRate" to getCacheHitRate()
)
builder.withDetail("database", dbInfo)
.withDetail("cache", cacheInfo)
}
private fun getDataSourceUrl(): String {
// 获取数据源URL的逻辑
return "jdbc:mysql://localhost:3306/mydb"
}
private fun getCurrentPoolSize(): Int {
// 获取连接池大小的逻辑
return 10
}
private fun getRedisNodes(): List<String> {
// 获取Redis节点信息的逻辑
return listOf("redis-1:6379", "redis-2:6379")
}
private fun getCacheHitRate(): Double {
// 获取缓存命中率的逻辑
return 0.85
}
}
方式3:环境相关的信息贡献者
根据不同环境提供不同信息:
kotlin
@Component
class EnvironmentInfoContributor(
private val environment: Environment
) : InfoContributor {
override fun contribute(builder: Info.Builder) {
val activeProfiles = environment.activeProfiles
val environmentInfo = mapOf(
"profiles" to activeProfiles.toList(),
"environment" to determineEnvironment(activeProfiles),
"config" to getEnvironmentConfig()
)
builder.withDetail("environment", environmentInfo)
}
private fun determineEnvironment(profiles: Array<String>): String {
return when {
profiles.contains("prod") -> "生产环境"
profiles.contains("staging") -> "预发布环境"
profiles.contains("test") -> "测试环境"
else -> "开发环境"
}
}
private fun getEnvironmentConfig(): Map<String, Any> {
return mapOf(
"serverPort" to environment.getProperty("server.port", "8080"),
"logLevel" to environment.getProperty("logging.level.root", "INFO"),
"enableDebug" to environment.getProperty("debug", Boolean::class.java, false)
)
}
}
安全考虑 🔒
WARNING
Info 端点可能暴露敏感信息,在生产环境中需要特别注意安全配置。
1. 限制访问
yaml
management:
endpoints:
web:
exposure:
include: info
base-path: "/management"
endpoint:
info:
enabled: true
security:
enabled: true
2. 配置安全认证
kotlin
@Configuration
@EnableWebSecurity
class ActuatorSecurityConfig {
@Bean
fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
return http
.requestMatchers("/actuator/**")
.hasRole("ADMIN")
.and()
.httpBasic()
.and()
.build()
}
}
3. 过滤敏感信息
kotlin
@Component
class SecureInfoContributor : InfoContributor {
override fun contribute(builder: Info.Builder) {
// 只暴露必要的信息,避免敏感数据
val safeInfo = mapOf(
"version" to getApplicationVersion(),
"status" to "running",
"uptime" to getUptime()
// 不包含数据库密码、API密钥等敏感信息
)
builder.withDetail("application", safeInfo)
}
private fun getApplicationVersion(): String = "1.0.0"
private fun getUptime(): String = "2 days, 3 hours"
}
最佳实践 ✅
1. 合理的信息粒度
TIP
不要暴露过多详细信息,保持信息的简洁性和相关性。
kotlin
// ✅ 好的做法
val buildInfo = mapOf(
"version" to "1.0.3",
"timestamp" to "2024-01-15T10:30:00Z"
)
// ❌ 避免的做法
val buildInfo = mapOf(
"version" to "1.0.3",
"timestamp" to "2024-01-15T10:30:00Z",
"buildMachine" to "jenkins-slave-01.internal.company.com",
"buildUser" to "jenkins",
"internalBuildId" to "BUILD-12345-SECRET"
)
2. 使用缓存优化性能
kotlin
@Component
class CachedInfoContributor : InfoContributor {
@Cacheable("info-cache")
override fun contribute(builder: Info.Builder) {
// 计算密集型的信息收集
val expensiveInfo = calculateExpensiveMetrics()
builder.withDetail("metrics", expensiveInfo)
}
private fun calculateExpensiveMetrics(): Map<String, Any> {
// 模拟耗时操作
Thread.sleep(1000)
return mapOf("calculated" to System.currentTimeMillis())
}
}
3. 监控和告警
结合监控系统使用 Info 端点:
kotlin
@RestController
class HealthCheckController {
@Autowired
private lateinit var infoEndpoint: InfoEndpoint
@GetMapping("/api/version")
fun getCurrentVersion(): ResponseEntity<Map<String, String>> {
val info = infoEndpoint.info()
val version = info["build"] as? Map<*, *>
return if (version != null) {
ResponseEntity.ok(mapOf("version" to version["version"].toString()))
} else {
ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE)
.body(mapOf("error" to "Version information not available"))
}
}
}
故障排查 🔧
常见问题
- Info 端点返回空对象
解决方案
检查是否正确配置了 InfoContributor,或者在 application.yml 中添加了 info 配置:
yaml
info:
app:
name: "My Application"
version: "1.0.0"
- Git 信息不显示
解决方案
确保构建过程中生成了 git.properties 文件。在 Gradle 中添加:
kotlin
plugins {
id("com.gorylenko.gradle-git-properties") version "2.4.1"
}
- 内存信息显示异常
解决方案
检查 JVM 参数配置,确保有足够的权限访问系统信息:
bash
java -Djava.security.manager=default -jar app.jar
# 移除安全管理器限制
java -jar app.jar
总结 📝
Spring Boot Actuator 的 Info 端点是一个强大而实用的监控工具,它能够:
- 🎯 快速识别:帮助快速识别应用程序版本和环境信息
- 🔍 问题排查:提供运行时信息辅助问题诊断
- 📊 监控集成:与监控系统集成,实现自动化运维
- 🛡️ 安全可控:通过合理配置保证信息安全
通过合理使用 Info 端点,你可以大大提升应用程序的可观测性和运维效率。记住,好的监控不仅仅是收集数据,更重要的是收集有用的数据! 🚀
IMPORTANT
在生产环境中使用 Info 端点时,务必考虑安全性,避免暴露敏感信息,并配置适当的访问控制。