排查中间件 API 失败问题

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

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

排查注册和创建失败问题

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

无法创建第二个服务

错误

Internal 错误。

原因

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

修复

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

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

错误

Status(-3, EX_ILLEGAL_ARGUMENT)

原因

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

修复

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

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

错误

take_publisher() 的调用返回 none

原因

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

修复

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

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

错误

Unavailable 错误。

原因

您尝试为不存在或已取消注册的发布者创建 SubscriberObserverHistoryInstantReader

修复

在尝试为发布者创建 SubscriberObserverHistoryInstantReader 之前,请验证发布者是否存在或已注册。

无法创建 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 以及客户端和服务器之间的通信系统按预期运行,但客户端发出的请求触发了服务器中的错误。

修复

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