路网分析服务最容易被忽视的故障,往往不是最短路算法算错,而是一个不存在的节点或负数阈值让 API 给出崩溃、空结果或前后不一致的响应。pgRouting 4.0.2 的官方发布聚焦这类边界:修复 pgr_dijkstraViapgr_withPointsViabad_alloc,并把 pgr_drivingDistancepgr_withPointsDD 对负 distance 的处理统一为抛错。对以 PostGIS 提供路径、等时圈或服务覆盖分析的团队,这是一份很具体的提醒:路由的输入语义、错误结构和零值边界,都应成为版本升级的验收对象。

本文依据 pgRouting 4.0.2 的 GitHub Release 与关联 issue #3110、#3091 整理。文中给出的测试路径是工程建议,不能替代团队对自身图数据、成本字段、权限和业务口径的验证。

可核查事实

  • pgRouting 4.0.2 在 GitHub 上发布于 2026 年 9 月 5 日,发布包同时提供英文与西班牙文文档压缩包,以及源码 tar.gz 与 zip。

  • Release 记录 pgr_dijkstraViabad alloc 修复,并将问题关联到 #3110。

  • #3110 的复现条件是:传给 pgr_dijkstraVia 的节点数组中有一个节点不存在于图中;报告曾得到 std::bad_alloc,而提案的期望是不要抛出该异常。

  • 4.0.2 同时修复 pgr_withPointsViabad alloc

  • Release 表明 pgr_drivingDistancepgr_withPointsDDdistance < 0 改为抛异常,并采用统一的错误消息和 hint。

  • #3091 记录了 4.0.1 中四类 catchment 函数的差异:pgr_primDDpgr_kruskalDD 已对负数报错,pgr_drivingDistance 曾只给 NOTICE 后返回 0 行,pgr_withPointsDD 使用不同错误且错误拒绝 distance = 0

  • #3091 的期望行为是:负 distance 报错,distance = 0 合法并只返回根节点;该 issue 在与发布相同的 2026 年 9 月 5 日关闭。

这些事实说明,此版本的价值不在于引入新路线算法,而在于让异常输入更可预测。对调用者来说,“0 行”“NOTICE”“数据库内部异常”和结构化参数错误是完全不同的控制流。

核心机制

路网服务至少有三层合同。第一层是图合同:edge SQL 返回的 idsourcetargetcostreverse_cost 是否满足建图假设,节点是否确实存在。第二层是参数合同:起终点、途经点、distance、方向和点位投影是否处于函数可接受的范围。第三层是响应合同:非法请求应当产生稳定、可分类的错误;合法但没有可达结果才应产生空集合。

4.0.2 所处理的问题正处于后两层的交界。若一个不存在节点把服务带到 std::bad_alloc,调用方无法区分“查询无路径”和“服务异常”。若负的 catchment 阈值静默返回空行,业务系统又可能把参数错误解释为“附近没有设施”。统一拒绝负数、接受零值的语义,能让客户端把输入校验、重试和用户提示建立在明确的状态上。

GIS 场景

设想应急调度系统要返回指定医院在 15 分钟或 5 公里网络阈值内的补给点。请求到达后,服务先核查医院映射的图节点是否仍在当前网络版本中,再验证阈值非负。阈值为 0 时,应把它当作可复现的边界请求:结果只允许包含起点本身或业务规则明确允许的同位实体;不能把它误报成系统故障。阈值为负时,应在 API 边界直接返回明确的 4xx 参数错误,而非把负数送入数据库等待不同函数各自处理。

路径经由多个站点时,同样要覆盖不存在的中间节点。应用可先根据网络版本查节点表,再调用 pgr_dijkstraVia;即使数据库升级后已避免特定的 bad_alloc,前置校验仍能给用户指出哪个 ID 不存在,并防止把基础设施异常暴露为业务错误。对历史路线重跑,应记录图版本、edge SQL 哈希、节点数组和 pgRouting 版本,否则无法解释同一请求为什么在更新后得到不同结果。

技术路径

把回归集按“有效输入、无可达路径、缺失节点、负阈值、零阈值”分类。每个用例固定一个最小 edge 表、请求参数和期望的 HTTP/SQL 结果类别。升级前后分别运行 pgr_dijkstraViapgr_withPointsViapgr_drivingDistancepgr_withPointsDD:至少断言缺失节点不会转化为进程级异常、负 distance 不会被默认为空结果、零 distance 的处理与业务口径一致。

服务层不要依赖数据库错误文本来承担全部产品语义。对可提前发现的输入,返回机器可读的错误码,如 node_not_foundinvalid_distance;同时保留数据库错误类别、pgRouting/PostGIS 版本和请求追踪 ID 到受控日志。对于合法的无路径响应,单独返回 no_route 或空 FeatureCollection,并明确与参数错误区分。这样客户端的地图提示、批处理重试和监控告警都不会把三种情况混在一起。

发布时,把网络数据更新与扩展更新拆开验收。先在副本图上跑最小回归集,再以固定城市区域的真实 OD 样本比较命中、总 cost、边数与响应时间。若 edge SQL、方向字段或 cost 的单位发生改变,就把它视为图合同改变,而不是将差异归因于 pgRouting 小版本。

风险边界

4.0.2 的发布说明覆盖的是列出的函数和问题,不保证所有 routing、turn restriction、拓扑构建或自定义 edge SQL 都具有相同表现。一个节点存在也不表示它与目标可达;空结果仍可能来自方向、成本、孤岛、过滤条件或图版本。统一负数检查也不能替代业务阈值上限、坐标系检查、输入授权和查询资源限制。生产升级必须在实际 PostgreSQL、PostGIS、数据规模和并发条件下复验。

检查清单

  1. 固定图版本、edge SQL、PostgreSQL、PostGIS 与 pgRouting 版本,并随路由结果记录。

  2. 对起终点和途经点先做节点存在性检查,再调用路线函数。

  3. 为负 distance 返回稳定的参数错误;明确验证 0 distance 的结果只含允许的根节点语义。

  4. 分别测试合法无路径、缺失节点、负阈值与零阈值,禁止把它们都解释为空结果。

  5. 升级后覆盖 pgr_dijkstraViapgr_withPointsViapgr_drivingDistancepgr_withPointsDD 的最小复现用例。

  6. 用真实 OD 样本比较升级前后的命中、cost、边数与时延,并保留差异证据。

  7. 在 API 与日志中区分 node_not_foundinvalid_distanceno_route 和数据库故障,避免错误重试。

结论

可靠的网络分析不是只验证一条路线能否画在地图上,而是让异常节点、负阈值、零阈值和不可达结果都拥有稳定含义。pgRouting 4.0.2 提供了可复核的边界修复;团队把这些边界写入回归合同,才能让版本升级真正降低路由服务的不确定性。

参考来源

  1. pgRouting v4.0.2 Release:https://github.com/pgRouting/pgrouting/releases/tag/v4.0.2

  2. pgRouting issue #3110:https://github.com/pgRouting/pgrouting/issues/3110

  3. pgRouting issue #3091:https://github.com/pgRouting/pgrouting/issues/3091