排查中间件 API 失败问题

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

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

排查注册和创建失败问题

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

无法创建第二个服务

错误:

Internal 错误。

原因:

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

修复:

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

无法删除重复的服务软件包

错误:

Status(-3, EX_ILLEGAL_ARGUMENT)

原因:

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

修复:

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

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

错误:

对 take_publisher() 的调用返回 none。

原因:

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

修复:

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

无法创建订阅者、观察者、历史记录或 InstantReader

错误:

Unavailable 错误。

原因:

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

修复:

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

无法创建 RPC 客户端

错误:

Unavailable 错误

原因:

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

修复:

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

排查通信失败问题

服务执行完毕并开始与其他服务通信后,可能会发生通信失败。

排查发布者取消注册问题

当发布者取消注册时,如果其读取器仍处于活跃状态,则可能会发生错误。

订阅者的 read_next_messages() 返回空列表

错误:

read_next_messages() 成功,但返回空列表。

原因:

发布者取消注册时,其读取器处于活跃状态。

修复:

使用具有可用性流的订阅者或历史记录。如果可用性流的最后一条消息不可用,则发布者已取消注册,并且没有新消息。

观察者的 next() 返回内部错误

错误:

next() 返回 Internal 错误。

原因:

发布者取消注册时,其读取器处于活跃状态。

修复:

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

历史记录的 read_from_history() 不返回新消息

错误:

read_from_history() 不返回任何新消息,仅返回旧消息。

原因:

发布者取消注册时,其读取器处于活跃状态。

修复:

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

InstantReader read_latest_message() 返回内部错误

错误:

read_latest_message() 返回 Internal 错误。

原因:

发布者取消注册时,其读取器处于活跃状态。

修复:

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

排查消息队列为空的问题

尝试从空消息队列中读取内容时,可能会发生错误。

订阅者的 read_next_messages() 返回空列表

错误:

read_next_messages() 成功返回空列表。

原因:

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

修复:

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

观察者的 next() 返回内部错误

错误:

next() 返回 Internal 错误。

原因:

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

修复:

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

历史记录的 read_from_history() 不返回新消息

错误:

read_from_history() 成功返回空列表。

原因:

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

修复:

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

InstantReader read_latest_message() 返回内部错误

错误:

read_latest_message() 返回 Internal 错误。

原因:

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

修复:

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

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

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

溢出后订阅者的首次读取返回 DataLoss 错误

错误:

read_next_message() 返回 DataLoss 错误。

原因:

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

修复:

溢出后观察者的首次 next() 返回 DataLoss 错误

错误:

next() 返回 DataLoss 错误。

原因:

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

修复: 可能的修复方法包括:

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

  • 使用者使用 InstantRead 对象,而不是观察者。InstantRead 对象不会返回溢出错误,并且始终返回最后一条消息。如果您只关心最后一条消息,则可以使用 InstantRead 对象而不是观察者。

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

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

    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 ++;
    }
    }
    

历史记录的读取不完整

错误:

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

原因:

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

修复:

InstantReader 仅读取最后一条消息

错误:

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

原因:

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

修复:

不适用

RPC 客户端调用方法,但该方法不可用

错误:

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

原因:

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

修复:

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

服务器端实现返回 SdvStatus 错误

错误:

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

原因:

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

修复:

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