大多数中间件 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 条消息。如需解决此差异,请按照以下步骤创建解决方案:
- P1 向 O2 发布消息。
- O2 读取一条消息并丢弃九条消息。
- O2 将读取的一条消息发送给 P2。
- P2 将读取的一条消息发送给 O1。
- 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 以及客户端与服务器之间的通信系统按预期运行,但客户端发出的请求在服务器中触发了错误。
修复:
使用客户端发出有效请求,或修复服务器以成功响应这些请求。