排查中间件 API 失败问题

大多数中间件 API 都会返回一个 SdvResult 对象。成功后,此对象包含预期的结果对象。如果执行失败,此对象会包含一个 SdvStatus 对象,该对象表示意外行为或错误情况,通常由错误代码(例如 Internal、Unavailable 或 DataLoss)标识。

本页面可帮助您排查这些错误代码。

排查注册和创建失败问题

当您尝试创建或注册无效服务时,通常会出现注册和创建失败。

无法创建第二个服务

错误:

Internal 个错误。

原因:

您正尝试注册完全相同的服务包实例(名称和实例 ID)两次。

修复:

请勿尝试将完全相同的服务包实例(名称和实例 ID)注册两次。

无法删除重复的服务套装

错误:

Status(-3, EX_ILLEGAL_ARGUMENT)

原因:

您尝试删除的重复服务包不存在。

修复:

请勿尝试删除不存在的重复服务包。

无法检索用于发送消息的发布者实例

错误:

调用 take_publisher 会返回 none。

原因:

您从同一服务包实例中为同一变体调用了两次 take_publisher。

修复:

请勿从同一服务包实例中为同一变体调用 take_publisher 两次。

无法创建 Subscriber、Observer、History 或 InstantReader

错误:

Unavailable 个错误。

原因:

您尝试为不存在或已取消注册的发布者创建 Subscriber、Observer、History 或 InstantReader。

修复:

在尝试为发布商创建 Subscriber、Observer、History 或 InstantReader 之前,请先验证该发布商是否存在或已注册。

无法创建 RPC 客户端

错误:

Unavailable 个错误

原因:

您尝试为不存在或未注册的服务器单元名称创建 RPC 客户端。

修复:

在创建 RPC 客户端之前,请验证服务器是否存在并已注册。

排查通信故障

服务执行并开始与其他服务通信后,可能会发生通信故障。

排查发布商注销问题

如果发布商在读者仍处于活跃状态时注销,则可能会发生错误。

订阅者的 read_next_messages 返回空列表

错误:

read_next_messages 成功,但返回空列表。

原因:

发布者已注销,但其读取器处于活跃状态。

修复:

将订阅者或历史记录与可用性信息流搭配使用。如果可用性信息流的最后一条消息不可用,则发布者会被取消注册,并且不会有新消息。

观察方的 next 返回内部错误

错误:

next 会返回 Internal 错误。

原因:

发布者已注销,但其读取器处于活跃状态。

修复:

将订阅者或历史记录与可用性信息流搭配使用。如果可用性信息流的最后一条消息不可用,则表示发布者已消失,并且没有新消息。

History 的 read_from_history 不会返回新消息

错误:

read_from_history 不会返回任何新消息,只会返回旧消息。

原因:

发布者已注销,但其读取器处于活跃状态。

修复:

将订阅者或历史记录与可用性信息流搭配使用。如果可用性信息流的最后一条消息不可用,则表示发布者已消失,并且没有新消息。

InstantReader read_latest_message 返回内部错误

错误:

read_latest_message 会返回 Internal 错误。

原因:

发布者已注销,但其读取器处于活跃状态。

修复:

将订阅者或历史记录与可用性信息流搭配使用。如果可用性信息流的最后一条消息不可用,则表示发布者已消失,并且没有新消息。

排查消息队列为空的问题

尝试从空消息队列中读取数据时可能会出错。

订阅者的 read_next_messages 返回空列表

错误:

read_next_messages 成功返回空列表。

原因:

发布者处于活跃状态,但尚未发送消息。

修复:

将订阅者或历史记录与可用性信息流搭配使用。如果可用性信息流的最后一条消息可用,则发布者处于活跃状态,并且没有新消息。

观察方的 next 返回内部错误

错误:

next 会返回 Internal 错误。

原因:

发布者处于活跃状态,但尚未发送消息。

修复:

将订阅者或历史记录与可用性信息流搭配使用。如果可用性信息流的最后一条消息可用,则发布者处于活跃状态,并且没有新消息。

History 的 read_from_history 不会返回新消息

错误:

read_from_history 成功返回空列表。

原因:

发布者处于活跃状态,但尚未发送消息。

修复:

将订阅者或历史记录与可用性信息流搭配使用。如果可用性信息流的最后一条消息可用,则发布者处于活跃状态,并且没有新消息。

InstantReader read_latest_message 返回内部错误

错误:

read_latest_message 会返回 Internal 错误。

原因:

发布者处于活跃状态,但尚未发送消息。

修复:

将订阅者或历史记录与可用性信息流搭配使用。如果可用性信息流的最后一条消息可用,则发布者处于活跃状态,并且没有新消息。

排查缓冲区溢出或数据丢失问题

如果发布者发送消息的速度快于读取器使用消息的速度,则可能会发生错误。

发生溢出后,订阅者的首次读取操作会返回 DataLoss 错误

错误:

read_next_messages 会返回 DataLoss 错误。

原因:

发布者发送消息的速度快于读取器使用消息的速度。

修复:

可能的解决方法包括:

  • 在 VSIDL 架构定义中增加发布者环形缓冲区 capacity,以便队列可以在订阅者读取消息之前吸收突发消息。
  • 在订阅者中更频繁地使用消息,或降低发布者消息速率。
  • 如果您的服务只需要最新的消息值,而不需要处理每个中间更新,请使用 InstantReader 而不是 Subscriber。

溢出后观察者的第一个 next 返回 DataLoss 错误

错误:

next 会返回 DataLoss 错误。

原因:

发布者发送消息的速度快于读取器使用消息的速度。

修复:

可能的解决方法包括:

  • 发布者以较慢的速度发布。例如,您可能有一个包含最新消息时间戳的变量。如果当前时间小于最新发布时间加上增量,则不发布消息。使用此机制,每个增量最多发布一条消息。

  • Consumer 使用 InstantRead 对象,而不是观察器。InstantRead 对象不会返回溢出错误,并且始终返回最后一条消息。如果只有最后一条消息对您重要,那么您可以使用 InstantRead 对象,而不是观察器。

  • 使用方实现采样。如果您的解决方案有一个发布者 (P1) 发布消息的速度快于观察方 (01) 读取消息的速度,您可以创建一个新的发布者 (P2) 和观察方 (02) 来适应发布和读取速度的差异。

    例如,假设 P1 每 10 毫秒发布一条消息,但 O1 每 100 毫秒只能读取一条消息,并丢弃其余 9 条消息。如需解决此差异,请按照以下步骤创建解决方案:

    1. P1 向 O2 发布消息。
    2. O2 读取一条消息并丢弃九条消息。
    3. O2 将读取的一条消息发送给 P2。
    4. P2 将读取的一条消息发送给 O1。
    5. O1 每 10 秒读取一条消息。

    以下示例代码展示了如何实现此采样场景:

    int discarded_message = 10;
    
    while (true) {
    message m = O2.read_message();
    if discarded_message == 10 {
      discarded_message = 0;
      P2.publish(m);
    } else {
     discarded_message ++;
    }
    }
    

历史记录的读取不完整

错误:

在复制历史记录之前,消息已丢失。读取时没有直接错误通知。

原因:

发布者发送消息的速度快于读取器使用消息的速度。

修复:

可能的解决方法包括:

  • 在 VSIDL 架构定义中增加发布者环形缓冲区 capacity,以便 History 为读取器的轮询间隔保留足够多的近期消息。
  • 更频繁地从 History 读取数据,或降低发布者发送消息的速率。

InstantReader 仅朗读最后一条消息

错误:

在复制历史记录之前,消息已丢失。读取时没有直接错误通知。

原因:

发布者发送消息的速度快于读取器使用消息的速度。

修复:

不适用

RPC 客户端调用了不可用的方法

错误:

方法调用失败并显示 Unavailable 错误。

原因:

SDV 不知道服务器名称,并返回 Unavailable。如果服务发现未返回有效的服务器名称,中间件会返回此错误。

修复:

启动一个服务包,该服务包为客户端要使用的给定接口定义一个 server。

服务器端实现返回 SdvStatus 错误

错误:

服务器端实现会返回包含 SdvStatus 错误的 SdvResult,例如 SdvStatusCode::NotFound。错误会传播回调用客户端。

原因:

SDV 以及客户端与服务器之间的通信系统按预期运行,但客户端发出的请求在服务器中触发了错误。

修复:

使用客户端发出有效请求,或修复服务器以成功响应这些请求。