- 后端
【免费下载链接】valhalla
Open Source Routing Engine for OpenStreetMap
导读
/status是 Valhalla 路由引擎暴露的一个轻量级状态服务端点:默认返回 HTTP 200 以及version、tileset_last_modified两个字段,可直接充当 HTTP API 的健康检查(health check)端点;传入"verbose": true后,它会额外返回当前加载 tileset 的完整状态信息(是否含行政边界、时区、实时交通、范围 bbox 等)。读完本文,你将掌握/status的请求方式、全部响应字段含义、service_limits.status.allow_verbose配置开关的作用,以及该端点背后的源码实现与测试验证方式。
一、端点概览:默认行为与健康检查用途
Valhalla 的 Loki 服务在启动时会挂载一组 HTTP 端点(/route、/locate、/status等),其中/status的设计初衷就是让运维与监控系统能够低成本地判断服务实例是否存活、tileset 是否就绪。
默认(不传任何参数)情况下,向/status发起GET请求会:
- 返回 HTTP 状态码200;
- 返回
version与tileset_last_modified两个基础字段; tileset_last_modified以UNIX 时间戳(秒)形式表示 tile_extract 或 tile_dir 的最后修改时间。
这两个字段始终返回、无需额外计算,因此/status非常适合被接入 Prometheus 探针、K8s liveness/readiness probe 或负载均衡器的健康检查脚本。官方 API 文档原文即明确说明其"can also be used as a health endpoint for the HTTP API"(关联文档)。
从源码实现看,这一"始终返回"的逻辑位于 src/loki/status_action.cc:
// info that's always returned auto* status = request.mutable_status(); status->set_version(VALHALLA_PRINT_VERSION); status->set_tileset_last_modified(get_tileset_last_modified(reader)); for (size_t i = 0; i < actions.size(); ++i) if (actions[i]) *status->mutable_available_actions()->Add() = Options_Action_Enum_Name(static_cast<Options::Action>(i));其中get_tileset_last_modified通过valhalla::filesystem_utils::last_write_time_t(path)读取GraphReader的 tileset 所在路径(tile_dir 或 tile_extract 文件)的最后写入时间;若读取失败则返回 0。此外,源码还在处理请求前检查了服务是否处于排空(draining)或关闭(shutting down)状态,若是则抛出valhalla_exception_t{102},让负载均衡器收到明确的服务下线信号(status_action.cc)。
二、请求方式与 verbose 参数
/status支持 GET 请求,参数以 JSON 形式通过jsonquery string 传递:
# 1. 基础健康检查(返回 version + tileset_last_modified) curl http://localhost:8002/status # 2. 获取完整的 tileset 状态信息 curl "http://localhost:8002/status?json={\"verbose\": true}"关键点在于:
"verbose": true作为请求参数传入后,服务端才会返回有关已加载 tileset 的附加信息;- 官方文档特别提醒:收集这些附加信息在计算上可能很昂贵(computationally expensive),因此
verbose开关可以由配置项service_limits.status.allow_verbose统一管制,其默认值为false(关联文档)。
配置 JSON 中对应的写法为:
{ "service_limits": { "status": { "allow_verbose": false } } }在 src/loki/worker.cc 中,该配置被读取并保存为成员变量:
allow_verbose = config.get<bool>("service_limits.status.allow_verbose", false);随后在 status_action.cc 中作为 verbose 输出的双重门禁:
// only return more info if explicitly asked for (can be very expensive) if (!request.options().verbose() || !allow_verbose) return;也就是说,只有同时满足"请求携带verbose: true"与"配置允许 verbose"两个条件,才会进入附加信息组装分支;任一不满足,响应都只包含基础字段。配置生成脚本 scripts/valhalla_build_config 中对该键的说明也印证了这一设计意图:"Allow verbose output for the /status endpoint, which can be computationally expensive"。
三、响应字段详解
当"verbose": true被允许并传入时,/status会返回下表所列的全部字段:
| Response key | Type | Description |
|---|---|---|
version | string | 当前 Valhalla 版本号,例如3.1.4。 |
tileset_last_modified | integer | tile_extract 或 tile_dir 的最后修改时间(UNIX 时间戳),例如1634903519。 |
has_tiles | bool | 当前是否加载了有效的 tileset。 |
has_admins | bool | 当前 tileset 是否使用 admin 数据库构建(即是否包含行政边界数据)。 |
has_timezones | bool | 当前 tileset 是否使用时区数据库构建。 |
has_live_traffic | bool | 实时交通 tiles 当前是否可用。 |
bbox | object | tileset 范围的 GeoJSON。 |
osm_changeset(可选) | integer | tileset 的dataset_id字段,用于数据变更识别。 |
warnings(可选) | array | 包含警告对象(如已废弃的请求参数、被 clamp 的值等)的数组。 |
字段语义与源码对应关系
各布尔字段的判定逻辑可以在 status_action.cc 中逐一对上:
// get _some_ tile const static baldr::graph_tile_ptr tile = get_graphtile(reader); if (connectivity_map) { status->set_bbox(connectivity_map->to_geojson(2)); const bool has_transit_tiles = connectivity_map->level_color_exists(TileHierarchy::GetTransitLevel().level); status->set_has_transit_tiles(has_transit_tiles); } else { const static bool has_transit_tiles = !reader->GetTileSet(3).empty(); status->set_has_transit_tiles(has_transit_tiles); } status->set_has_tiles(static_cast<bool>(tile)); status->set_has_admins(tile && tile->header()->admincount() > 0); status->set_has_timezones(tile && tile->node(0)->timezone() > 0); status->set_has_live_traffic(reader->HasLiveTraffic()); status->set_osm_changeset(tile ? tile->header()->dataset_id() : 0);对应关系如下:
has_tiles:get_graphtile会遍历GraphReader的 tileset,找到第一个层级低于 transit level 且nodecount > 0的瓦片;能找到有效瓦片即为true。has_admins:取到的瓦片头部admincount() > 0,表示瓦片内存在行政边界记录。has_timezones:瓦片第一个节点node(0)->timezone() > 0,表示瓦片带有时区信息。has_live_traffic:直接询问GraphReader::HasLiveTraffic(),反映实时交通 tile 是否已就绪。bbox:优先由connectivity_map->to_geojson(2)生成连通分量的 GeoJSON 范围;该字段在响应中以嵌套 JSON 对象的形式输出。osm_changeset:取自瓦片头部的dataset_id()字段,即文档中提到的"变更识别"依据,详细机制可参阅 Change identification 概念文档。
需要说明的是:虽然 proto/descriptors/status.proto 中还定义了has_transit_tiles字段(是否包含 transit tiles),但官方 API 参考文档的响应表中并未列出该键,因此它属于实现层信息,实际 HTTP 输出时也仅在 verbose 分支中随 bbox 一同写入(见 src/tyr/serializers.cc)。关于warnings字段,它由 Loki 层通用警告机制注入(用于报告已废弃请求参数、数值被 clamp 等情况),在基础请求中通常不出现。
JSON 序列化细节
HTTP 输出的 JSON 组装位于 src/tyr/serializers.cc 的serializeStatus函数中,两个值得注意的细节:
osm_changeset为 0 时不出现在输出中——源码注释明确写道 "a 0 changeset indicates there's none, so don't write in the output",这正是该字段被标记为"可选"的原因:if (request.status().has_osm_changeset_case() && request.status().osm_changeset()) status_doc.AddMember("osm_changeset", ...);bbox以二次解析的 JSON 对象写入:Loki 层将其序列化为字符串,tyr 层再用 RapidJSON 解析后挂到status_doc的/bbox路径下,保证最终输出是结构化对象而非字符串。
四、verbose 响应示例
综合以上实现,一次被允许的 verbose 请求响应大致如下(字段顺序与具体值依 tileset 而定):
{ "version": "3.1.4", "tileset_last_modified": 1634903519, "available_actions": ["locate", "route", "height", "optimized_route", "isochrone", "trace_route", "trace_attributes", "transit_available", "expansion", "centroid", "status", "tile"], "has_tiles": true, "has_admins": true, "has_timezones": true, "has_live_traffic": false, "has_transit_tiles": false, "bbox": { "type": "Polygon", "coordinates": [...] } }注意:available_actions虽然未出现在官方文档的字段表中,但它是 status.proto 中定义的固定字段(字段号 8),且由 serializers.cc 无条件写入输出,用于告知客户端当前 Loki 实例启用了哪些 action(如locate、route、isochrone等)。
五、调用链与测试验证
底层调用链
一次/status请求的完整链路为:
- HTTP 路由层(prime_server)将请求分发到 Loki 的
statusaction; - Loki 层
loki_worker_t::status()填充Api::mutable_status()(status_action.cc)——检查服务排空状态、写入基础字段、按需写入 verbose 字段; - tyr 层
serializeStatus()将 protobuf 状态对象序列化为 JSON 或 PBF(当请求format=pbf时走serializePbf分支,serializers.cc)。
该端点还被纳入 Loki 的 action 白名单体系:service_limits下的status配置段与max_locations等通用限制解耦,loki/worker.cc 在遍历service_limits时明确跳过了status与allow_hard_exclusions这类非位置型服务限制,避免对其误用max_locations校验。
测试用例
仓库测试对该端点有直接覆盖,可作为你验证自身部署行为是否正确的参照:
- test/loki_service.cc 构造了
GET /status与GET /status?json={"verbose": true}两组 HTTP 请求,用于验证路由层对该端点的分发与参数解析; - test/actor.cc 通过 Actor API 分别以空参数和
{"verbose": true}调用status(),验证两种模式下的序列化输出; - test/bindings/valhalla.json 与 test/test.cc 中的测试配置展示了
service_limits.status.allow_verbose在开启/关闭两种配置下的测试环境设定。
如果你需要在本机复现,可以参考 valhalla_build_config 生成的默认配置模板,确认service_limits.status.allow_verbose的当前取值后再启动valhalla_service进行实测。
六、典型使用场景小结
- 健康检查 / 存活探测:监控系统只需解析
version与tileset_last_modified两个低成本字段,确认实例存活且 tileset 未过期(通过比较时间戳与预期更新时间)。 - 部署变更验证:升级 tileset 后调用 verbose 模式,检查
has_tiles、has_admins、has_timezones、has_live_traffic是否符合预期,快速定位数据构建时遗漏 admin/时区/交通数据的问题。 - 范围与版本审计:通过
bbox(GeoJSON)核对服务所辖地理范围,通过version与osm_changeset确认二进制与数据集的版本匹配情况。 - 服务下线协调:利用源码中"排空/关闭时返回异常 102"的行为,配合负载均衡器实现优雅摘流。
参考文件索引
- 官方 API 文档:docs/docs/api/status.md
- Loki 层实现:src/loki/status_action.cc
- 配置读取:src/loki/worker.cc
- tyr 层 JSON 序列化:src/tyr/serializers.cc
- 响应消息定义:proto/descriptors/status.proto
- 配置模板生成脚本:scripts/valhalla_build_config
- 相关测试:test/loki_service.cc、test/actor.cc
- 变更识别概念:docs/docs/concepts/change-identification.md
- 后端
【免费下载链接】valhalla
Open Source Routing Engine for OpenStreetMap
相关推荐
Crater服务健康检查端点:自定义健康状态实现
Crater服务健康检查端点:自定义健康状态实现 健康检查端点概述 在现代应用开发中,服务健康检查(Health Check)是保障系统稳定性的关键组件。它通过
后端前端企业应用免费离线音频转录终极指南:用Buzz在本地电脑上实现专业级语音转文字
免费离线音频转录终极指南:用Buzz在本地电脑上实现专业级语音转文字 还在为音频转录发愁吗?每次开会、听课、采访都要手动记录,既费时又容易出错?今天我要向你介绍
人工智能语音音频本地部署桌面应用SkyWalking OAP 健康检查:使用 /healthcheck HTTP 端点检测服务健康状态
SkyWalking OAP 健康检查:使用 /healthcheck HTTP 端点检测服务健康状态 SkyWalking OAP(Observability
可观测性后端微服务云原生
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考