服务Actuator监控端点分析
服务Actuator监控端点分析
1 背景
调研当业务端口的性能出现瓶颈,导致undertow的XNIO线程池打满后,新的接口请求无法正常处理只能等待。等待过程会导致健康检查无法获取到数据而timeout问题。
希望通过优化配置解决该问题

2 分析过程
2.1 分析timeout原因
健康检查接口/health 出现timeout的原因,是因为业务端口与监控端口默认保持一致,导致资源竞争出现/health接口无法响应而timeout问题。
在现代技术架构下生产环境通常采用Kubernate云原生架构,其中探针会通过服务的端口暴露的/health接口进行周期性的健康检查,当/health接口无法正常返回健康状态并超过一定的频次时,Kubenates会认为服务出现异常而强制kill Pod。
这个策略在生产环境则表现为服务集体雪崩,出现致命的错误。
2.2 Actuator端口与业务端口一致对比
Actuator端口 | 优点 | 缺点 |
不特殊设置management.server.port,使用与主服务相同端口 | ● 部署简单,无需额外网络配置 ● 减少开放端口数量,降低防火墙复杂度 ● 天然继承主服务的认证/授权体系 ● 监控流量与业务流量统一管理 | ● 安全风险:暴露监控端点可能增加攻击面 ● 资源竞争:监控请求可能影响业务性能 ● 无法单独做网络隔离策略 ● 监控端点故障可能连带影响主服务 |
actuator使用独立端口 | ● 安全性:可以完全隔离监控端点(内网访问/VPC访问) ● 资源隔离:避免监控请求影响业务性能 ● 灵活管控:可单独配置TLS、限流、ACL等策略 ● 故障隔离:监控组件问题不影响主服务 | ● 增加运维复杂度(需管理额外端口) ● 需要额外的安全配置(跨端口认证) ● 可能增加基础设施成本(LB配置等) |
actuator监控独立端口配置方式:
management:
server:
port: 8081
2.3 将actuator监控端口独立后模拟业务端口阻塞
验证业务端口和监控端口独立后的情况。将监控端口配置为固定端口(在dev、test、prod环境将通过环境变量固定8000端口)本地运行还是与业务接口一致。
-Dmanagement.server.port=8000

在springbootadmin监控中,服务注册的监控端口更变为8000,业务端口8113端口已经隔离。


在线程dump监控中,XNIO-1 和XNIO-2 线程池,XNIO-1按照CPU*8 配置,而XNIO-2 按照固定5个工作线程配置(监控线程池的请求频率一般不会突增)
2.3.1 监控端口隔离后进行压力测试
Jemeter启动200线程 ,业务XNIO线程池满,打到77QPS 无异常,其他请求排队等待处理。springbootadmin监控正常,CPU无异常,监控无明显卡顿。


2.4 结论
这种业务端口和监控端口隔离虽然增加了复杂度,但能有效降低攻击面,是生产环境推荐的安全实践。将Actuator监控端口与业务端口隔离是一种安全最佳实践,目前生产环境33个服务,逐步推进监控端口隔离。
2.5 端口隔离后的监控问题
1、新增加了一套XNIO的核心线程和工作线程,会占用一定的资源。但资源占用通常较小
2、线程阻塞如何告警通知?
3、独立端口后对运行环境带来那些影响?
‒ Prometheus 是否采集acutator端口数据?
4、业务端口的线程池打满后不一定CPU负载高,这个时候服务健康检查是ok的,但是慢接口已经积压了,需要考虑扩容问题!
3 监控端口安全控制
监控端口独立后,目前还是无认证机制,在内网环境可访问,通过网关隔离。如果黑客攻击到服务内部,远程脚本攻击可能扫描到敏感接口。
这种隔离虽然增加了复杂度,但能有效降低攻击面,是生产环境推荐的安全实践。
4 监控端口改造工作
1、服务配置监控端口 8000
JAVA_OPTS 环境变量追加 -Dmanagement.server.port=8000

当全面覆盖后,可以在基础镜像中配置固定值,java命令后面追加 -Dmanagement.server.port=8000
2、k8s 健康检查改端口8000;

3、K8s shutdown hook 改端口为8000;

关注微信公众帐号