在微服务、分布式架构普及的今天,单个系统可能承载成千上万个接口,而动态 URL、多版本路径、个性化参数等场景更是加剧了接口命名的复杂性。传统监控工具在遇到接口名称高基数(High Cardinality)问题时,会引发接口名称发散,导致监控数据离散、统计失效,甚至引发监控系统的雪崩。为此,应用性能监控 APM 推出接口名称自动收敛功能,通过自动化归类与动态聚合,让应用管理更加精准、高效、可洞察。
接口名称发散问题
对于应用上报的可观测数据,APM 会按照接口名称(也就是 Span 名称)维度进行聚合统计,计算吞吐量、响应时间、错误率等重要的性能指标。基于接口名称维度的聚合统计,用户可以在接口监控等功能分析每一个接口的性能表现,例如特定接口最近24小时的平均错误率以及 P99响应时间。
接口名称是由应用上报的链路数据决定的,具有极高的灵活度,具备自动埋点能力的探针会根据实例情况选择接口 URL、内部方法名等信息作为接口名称,用户也可以通过 OpenTelemetry API 等方式自定义接口名称。当一个应用的接口名称呈现高基数(High Cardinality)状态时,就会引发接口名称发散问题。例如,当用作接口名的 URL 中包括了用户 ID 信息的时候,因为用户 ID 参数的不同,会生成无数个独立的 URL:
/api/user/123
,/api/user/124
,/api/user/125
,/api/user/126
… 在这种情况下,每个 URL 被视作独立的接口,系统中的接口名称数量极为庞大,在按照接口名称维度进行聚合统计时,实际上每个接口都只和一个特定的用户 ID 相关。这会导致极为严重的问题:统计失效:这在上述例子中有非常好的体现,
/api/user/{userid}
被分散在众多包括不同用户 ID 的接口中,无法定位这一类接口的整体性能。分析障碍:该应用还存在另外两个重要的接口,分别是
/api/product
和/api/order
,但因为大量以/api/user/
开头的接口充斥在监控数据中,导致这两个重要的接口被忽视掉。查询性能:高基数下聚合计算变得缓慢,报表加载卡顿甚至超时。尽量 APM 已经在技术架构层面对查询性能进行了优化,但当前端页面需要加载大量离散数据的时候,依然会影响用户体验。
告警误报与漏报:离散的接口名称使得阈值规则难以统一配置,可能忽略共性故障(如所有支付接口超时),却对偶发异常产生误警。
这些问题不仅导致 APM 的使用效率低下,还可能掩盖系统更严重的故障。
接口自动收敛
针对接口名称发散问题,APM 系统通过智能收敛技术,实现接口的自动归类,以更好的进行统一治理以及聚合分析,其中包括多项收敛手段:
URL 中的 parameter 与 anchor。当 APM 识别到指标数据中的接口名称为 URL 的时候,会截去
?
以及#
后面的部分。例如 www.example.com:80/path/to/myfile.html?key1=value1#SomewhereInTheDocument
会被处理为 www.example.com:80/path/to/myfile.html
。
URL 中的长分段。指标数据中的 URL 通过
/
切分后,如果其中一段的长度达到32,会被替换为 {LONG_STR}
。如果其中一段为纯数字,且长度达到10,则被替换为{LONG_NUM}
。例如:/path/to/1234567890/d4806b8c-2d5b-481d-9598-827b6dd49c10
会被处理为 /path/to/{LONG_NUM}/{LONG_STR}
。静态资源。当 APM 识别到指标数据中的接口名称带有静态资源后缀的时候,会将接口名称中的静态资源部分替换为
{STATIC_RESOURCE}.xxx
,其中 xxx 为静态资源的后缀。静态资源后缀包括 .jpg
、.gif
、.flv
等。例如:/path/to/user_icon_007.jpg
会被处理为/path/to/{STATIC_RESOURCE}.jpg
。IP 地址。当 APM 识别到指标数据中的接口名称中带有 IP 地址的时候,会将 IP 地址替换为
{IP}
。例如 11.146.86.42:9301/generateOrderInfo
会被处理为 {IP}:9301/generateOrderInfo
。限制单应用接口总数量。在比较极端的情况下,如果通过上述收敛手段依然未能彻底解决接口名称发散问题,APM 会将指标数据中的接口名称进行替换,尽量使一段时间内单应用的接口名称基数不超过1000个,超出此限制的接口名称会被替换为
{EXCEEDED}
。系统会基于应用上报的数据实时检测接口名称发散情况,如果识别接口发散的问题已经解除,会恢复接口名称的原始内容。APM 的接口自动收敛能力仅作用于指标数据,这代表链路数据(保存在 Span 中的数据)中的接口名称不会受任何影响。通过已经收敛后的接口名称,依然可以关联查询到接口所对应的链路数据。
SQL 收敛
在数据库调用分析等功能中,APM 会按照 SQL 维度进行聚合统计,计算调用次数、响应时间等性能指标。跟接口名称一样,SQL 也会导致发散问题,APM 会将数据库调用按照响应时间分为两类:响应时间在2秒以内的为正常调用,响应时间达到2秒的为慢调用。当出现 SQL 发散问题时,APM 也会将指标数据中的 SQL 进行替换,以降低单应用的 SQL 基数,超出限制的 SQL 会根据响应时间分别被替换为
{OTHER_SLOW_SQL}
和{OTHER_SQL}
。最佳实践
合理利用编程框架对 URL 中可变路径的识别能力,这样在探针侧就可以完成接口名称收敛。例如 Spring MVC 中的 PathVariable:
@GetMapping("/api/employeeswithvariable/{id}")@ResponseBodypublic String getEmployeesByIdWithVariableName(@PathVariable("id") String employeeId) {return "ID: " + employeeId;}
在应用访问数据库的场景,使用参数化 SQL 语句,例如 JDBC 中的 Prepared Statements。
在应用代码中使用 OpenTelemetry API 手动埋点的时候,不要在 Span 名称中加入可变参数,尽量降低 Span 名称的基数。