PAYATHON 2026

Eclipse Hono 2.7.0 管理 API 为何周期性返回 HTML 404?

数据小许

已有与该现象高度一致的上游报告,但现有日志还不足以证明根因是“路由没有绑定到所有 event loop 线程”。应先检查不同 HTTP server 实例实际使用的 Router、请求进入的端口,以及配置是否生效。目前也没有足够依据给出一个保证修复问题的环境变量。

Eclipse Hono 官方仓库的 Issue #3749 报告了 DeviceRegistryHttpServer 管理 API 的部分请求返回 HTML 404,以及 Router 在 HTTP server verticle 实例之间的使用问题。报告中对根因的描述不能代替维护者确认,也不能据此认定某个版本已修复;该条目可在官方问题列表中查到。

为什么应先检查 HTTP 请求分发和 Router

同一路径稳定地交替返回 JSON 200 和 HTML 404,说明请求可能经过了行为不同的处理链。Vert.x 支持多个 HTTP server 共享相同地址和端口,并在它们的 handler 之间分发请求。因此,值得检查是否有 server 使用了不同的 Router。Vert.x Core 的 Server sharing 说明介绍了这一机制。

检查时需要区分 event loop 线程、verticle 实例、HTTP server 和 Router。增加 event loop 线程,并不等于必须逐个线程注册路由。需要核实的是,每个接收管理请求的 server 是否挂载了包含目标 endpoint 的 handler,以及开始接收请求时初始化是否已经完成。

当前证据还有三个限制:

  • Content-Type: text/html 有助于区分响应来源,但不能单独证明 Router 为空。错误端口、其他 HTTP 服务或代理也可能返回 HTML 404。
  • main 线程上的注册日志和 event loop 上的启动日志,不能单独证明初始化出错。日志没有给出 Router 和 server 的对象对应关系。
  • 同一线程上的两条日志不一定属于同一次请求。没有 request ID 时,HTTP 404 sent 早于 retrieving tenant,不能证明同一个请求在查询前就返回了响应。

AMQP 查询正常,GET 和 POST 都受影响,这些现象使 HTTP 接入和路由层更值得优先排查,但还不足以完全排除数据库或认证链路中的其他问题。

第一步:核对实际访问的服务和端口

先确认宿主机 28080 映射到哪个容器、哪个容器内端口。不要仅凭外部端口号就判断它是 Device Registry Management API。

检查 Compose 的最终配置和容器状态:

docker compose config
docker compose ps

重点核对端口映射、实际镜像标签、是否有多个 registry 容器,以及请求是否经过反向代理。配置输出可能包含凭据,分享前应先脱敏。

Hono 2.7 的 MongoDB Device Registry 文档分别提供 HTTP 的 TLS 和非 TLS 端口配置:HONO_REGISTRY_HTTP_PORT 控制 TLS 端口,HONO_REGISTRY_HTTP_INSECUREPORT 控制非 TLS 端口。默认 TLS 端口为 8443,启用默认非 TLS 端口时使用 8080。宿主机上的 28080 是否指向它们,需要以实际映射为准。Hono 2.7 官方配置说明

然后,在能访问目标容器的网络环境中绕过代理,直接测试该 registry 的管理端口。如果直连全部正常,只有外部入口失败,就继续检查入口转发和后端实例差异;如果直连同一容器时仍稳定交替失败,再深入检查进程内部的 HTTP server 和 Router。

第二步:用独立连接复现并关联请求

下面的示例假设 http://127.0.0.1:28080 已确认为目标管理入口。每次启动独立的 curl 进程,并要求关闭连接,以减少连接复用对观察结果的影响:

for i in $(seq 1 12); do
  printf '\n--- request %s ---\n' "$i"
  curl --noproxy '*' --http1.1 \
    --connect-timeout 5 --max-time 15 \
    -H 'Connection: close' \
    -H 'Accept: application/json' \
    -H "X-Debug-Request-ID: hono-check-$i" \
    -i 'http://127.0.0.1:28080/v1/tenants/airechemistry'
done

如果接口需要认证,应使用已有的有效凭据。Accept: application/json 只是客户端偏好,不能让缺失的路由自动恢复,也不能保证错误响应一定采用 JSON。

X-Debug-Request-ID 不会自动出现在服务日志中,需要日志或临时诊断代码显式记录。应将每次请求的入口、路径、响应状态、数据库查询和最终响应关联起来,再判断 404 是否确实先于该请求的数据库操作。

同时比较独立连接和同一持久连接上的重复请求。如果结果随连接稳定分组,就更支持连接被分配到不同处理实例的推断,但仍需要 server 标识来确认。

第三步:验证配置是否真正影响了运行实例

环境变量写进 Compose 后,还需要确认应用读取并采用了该配置。调整后应确认容器已按新配置重建,并检查启动日志中的实际部署数量、监听端口和配置警告。

对已经尝试过的参数,应分别判断:

  • HONO_REGISTRY_HTTP_AUTHENTICATIONREQUIRED 控制认证要求,不能修复 Router 挂载问题。
  • HONO_REGISTRY_HTTP_INSTANCES 未列在 Hono 2.7 MongoDB Device Registry 的专用配置表中;不能仅凭名称认定它受支持,也不能据此断言它一定被忽略。
  • HONO_APP_MAXINSTANCES 是否控制当前 registry 的目标 verticle,需要结合该版本实现和部署日志确认。
  • QUARKUS_VERTX_EVENT_LOOPS_POOL_SIZE 是否作用于实际创建 HTTP server 的 Vert.x 实例,也需要验证。失败比例没有变化,不能直接证明 event loop 数量没有作用。

上述配置范围应以对应版本的官方配置文档和实际实现为准。还应记录镜像 digest,并核对运行中的 Quarkus、Vert.x 版本;环境记录中的版本号不应直接当作镜像依赖清单。

第四步:确认每个 server 挂载的路由

如果直连单个容器时也能复现问题,下一步需要增加请求级和实例级诊断信息。建议在 HTTP 初始化及请求入口记录:

  • verticle 实例、deployment ID 和 Vert.x context 的标识。
  • HTTP server、Router 的对象标识,以及监听地址和端口。
  • Router 中已注册的路径和 HTTP method。
  • 请求最终由哪个 server、哪个 Router 处理,以及返回状态。

需要确认失败请求是否总落到同一组 server,以及这些 server 是否确实缺少 /v1/tenants 对应路由。只统计线程名或 endpoint 注册日志次数,无法建立这个对应关系。

如果确认部分实例缺少路由,修复时应保证每个接收管理请求的 server 都挂载完整的管理 Router,并在必要初始化完成后才开始监听。具体采用每个 verticle 独立构建 Router,还是框架支持的其他组装方式,需要依据 Hono 的实现决定;不宜直接把 Router 改成全局单例作为通用补丁。

可以采用什么临时方案

只有日志确认目标 HTTP server 的实际部署数量可控时,才值得把单实例部署作为临时验证方案。原有测试中设置实例数后失败率反而上升,因此不能直接推荐继续使用这些参数作为修复。

关闭认证、延长 MongoDB 超时,以及为 POST 自动重试,都不应作为路由问题的通用处理办法。尤其是创建租户等写操作,重试前必须考虑前一次请求是否已经执行成功。

若确认是上游同类缺陷,可在 Issue #3749 中核对维护者结论、补丁及对应发行版本,再用相同复现流程验证。当前材料和查到的报告还不能支持“升级到某版本必然解决”或“设置某个环境变量即可解决”的结论。

备注:内容仅供参考。