用于 Gremlin 服务器响应标头的 Azure Cosmos DB

本文介绍 Azure Cosmos DB for Gremlin 服务器在请求执行时返回到调用方标头。 这些标头可用于排查请求性能问题,构建与 Azure Cosmos DB 服务本机集成的应用程序并简化客户支持。

请记住,依赖于这些标头,可将应用程序的可移植性限制为其他 Gremlin 实现。 回报是,你将获得更紧密的与用于 Gremlin 的 Azure Cosmos DB 的集成。 这些标头不是 TinkerPop 标准。

Headers

Header 类型 示例值 包含时间 Explanation
x-ms-request-charge 翻倍 11.3243 成功和失败 部分响应消息 在请求单位(RU/s 或 RU) 中消耗的集合或数据库吞吐量。 对于具有多个区块的请求,此标头存在于每个延续中。 它反映特定响应区块的费用。 仅对于包含单个响应区块的请求,此标头与遍历的总成本匹配。 但是,对于大多数复杂的遍历,此值表示部分成本。
x-ms-total-request-charge 翻倍 423.987 成功和失败 整个请求 的请求单位(RU/s 或 RU) 中消耗的集合或数据库吞吐量。 对于具有多个区块的请求,此标头存在于每个延续中。 它指示自请求开始以来的累积费用。 最后一个区块中此标头的值表示完整的请求费用。
x-ms-server-time-ms 翻倍 13.75 成功和失败 此标头包含在延迟故障排除目的中。 它指示用于 Gremlin 服务器的 Azure Cosmos DB 执行并生成部分响应消息所花费的时间(以毫秒为单位)。 使用此标头的值并将其与总体请求延迟应用程序进行比较可以计算网络延迟开销。
x-ms-total-server-time-ms 翻倍 130.512 成功和失败 用于 Gremlin 服务器的 Azure Cosmos DB 执行整个遍历的总时间(以毫秒为单位)。 此标头包含在每个部分响应中。 它表示自请求开始以来的累积执行时间。 最后一个响应指示执行总时间。 此标头可用于区分客户端和服务器作为延迟源。 可以将客户端上的遍历执行时间与此标头的值进行比较。
x-ms-status-code long 200 成功和失败 标头指示请求完成或终止的内部原因。 建议应用程序查看此标头的值并采取纠正措施。
x-ms-substatus-code long 1003 仅失败 Azure Cosmos DB 是基于统一存储层构建的多模型数据库。 此标头包含有关在较低层的高可用性堆栈中发生故障时失败原因的其他见解。 建议应用程序存储此标头,并在联系 Azure Cosmos DB 客户支持时使用它。 此标头的价值对于 Azure Cosmos DB 工程师有助于快速进行故障排除。
x-ms-retry-after-ms string (TimeSpan) "00:00:03.9500000" 仅失败 此标头是 .NET TimeSpan 类型的字符串表示形式。 此值将仅包含在请求中,因为预配吞吐量耗尽而失败。 应用程序应在指示的时间段后再次重新提交遍历。
x-ms-activity-id string (Guid) “A9218E01-3A3A-4716-9636-5BD86B056613” 成功和失败 标头包含请求的唯一服务器端标识符。 服务器为每个请求分配一个唯一标识符,以便进行跟踪。 应用程序应记录服务器返回的活动标识符,以获取客户可能希望联系客户支持的请求。 Azure Cosmos DB 支持人员可以通过这些标识符在 Azure Cosmos DB 服务遥测中查找特定请求。

状态代码

下面列出了服务器为状态属性返回 x-ms-status-code 的最常见代码。

状态 Explanation
401 身份验证密码与 Azure Cosmos DB 帐户密钥不匹配时,将返回错误消息 "Unauthorized: Invalid credentials provided" 。 在 Azure 门户中导航到 Azure Cosmos DB for Gremlin 帐户,确认密钥正确。
404 尝试同时删除和更新同一边缘或顶点的并发作。 错误消息 "Owner resource does not exist" 指示指定的数据库或集合的格式不正确 /dbs/<database name>/colls/<collection or graph name>
409 "Conflicting request to resource has been attempted. Retry to avoid conflicts." 当图形中已存在具有标识符的顶点或边缘时,通常会发生这种情况。
412 状态代码用错误消息 "PreconditionFailedException": One of the specified pre-condition is not met进行补充。 此错误表示读取边缘或顶点之间的乐观并发控制冲突,并在修改后将其写回到存储区。 发生此错误的最常见情况是属性修改,例如 g.V('identifier').property('name','value')。 Gremlin 引擎将读取顶点,对其进行修改,然后将其写回。 如果并行运行的另一个遍历尝试写入相同的顶点或边缘,其中一个将收到此错误。 应用程序应再次将遍历提交到服务器。
429 请求受到限制,应在 x-ms-retry-after-ms 中的值后重试
500 包含的 "NotFoundException: Entity with the specified id does not exist in the system." 错误消息指示已使用相同的名称重新创建数据库和/或集合。 此错误将在 5 分钟内消失,因为更改传播并使不同 Azure Cosmos DB 组件中的缓存失效。 若要避免此问题,请每次使用唯一的数据库和集合名称。
1000 服务器成功分析消息但无法执行时,将返回此状态代码。 它通常表示查询出现问题。
1001 当服务器完成遍历执行但无法将响应序列化回客户端时,将返回此代码。 当遍历生成复杂结果(太大或不符合 TinkerPop 协议规范)时,可能会出现此错误。 应用程序在遇到此错误时应简化遍历。
1003 "Query exceeded memory limit. Bytes Consumed: XXX, Max: YYY" 当遍历超过允许的内存限制时,将返回 。 每个遍历的内存限制为 2 GB
1004 此状态代码指示格式不正确的图形请求。 当请求失败反序列化时,请求格式不正确,非值类型正在反序列化为值类型或请求的不受支持的 gremlin作。 应用程序不应重试请求,因为它不会成功。
1007 通常返回此状态代码并显示错误消息 "Could not process request. Underlying connection has been closed."。 如果客户端驱动程序尝试使用服务器正在关闭的连接,则可能会出现这种情况。 应用程序应在不同的连接上重试遍历。
1008 Azure Cosmos DB for Gremlin 服务器可以终止连接以重新平衡群集中的流量。 客户端驱动程序应处理这种情况,并仅使用实时连接将请求发送到服务器。 有时,客户端驱动程序可能无法检测到连接已关闭。 当应用程序遇到错误时, "Connection is too busy. Please retry after sometime or open more connections." 它应该在不同的连接上重试遍历。
1009 该作未在分配的时间内完成,服务器已取消。 通过在遍历的每个跃点上筛选顶点或边缘以缩小搜索范围,优化遍历以快速运行。 请求超时默认值为 60 秒

Samples

基于读取一个状态属性 Gremlin.Net 的示例客户端应用程序:

// Following example reads a status code and total request charge from server response attributes.
// Variable "server" is assumed to be assigned to an instance of a GremlinServer that is connected to Azure Cosmos DB account.
using (GremlinClient client = new GremlinClient(server, new GraphSON2Reader(), new GraphSON2Writer(), GremlinClient.GraphSON2MimeType))
{
  ResultSet<dynamic> responseResultSet = await GremlinClientExtensions.SubmitAsync<dynamic>(client, requestScript: "g.V().count()");
  long statusCode = (long)responseResultSet.StatusAttributes["x-ms-status-code"];
  double totalRequestCharge = (double)responseResultSet.StatusAttributes["x-ms-total-request-charge"];

  // Status code and request charge are logged into application telemetry.
}

演示如何从 Gremlin Java 客户端读取状态属性的示例:

try {
  ResultSet resultSet = this.client.submit("g.addV().property('id', '13')");
  List<Result> results = resultSet.all().get();

  // Process and consume results

} catch (ResponseException re) {
  // Check for known errors that need to be retried or skipped
  if (re.getStatusAttributes().isPresent()) {
    Map<String, Object> attributes = re.getStatusAttributes().get();
    int statusCode = (int) attributes.getOrDefault("x-ms-status-code", -1);

    // Now we can check for specific conditions
    if (statusCode == 409) {
        // Handle conflicting writes
      }
    }

    // Check if we need to delay retry
    if (attributes.containsKey("x-ms-retry-after-ms")) {
      // Read the value of the attribute as is
      String retryAfterTimeSpan = (String) attributes.get("x-ms-retry-after-ms"));

      // Convert the value into actionable duration
			LocalTime locaTime = LocalTime.parse(retryAfterTimeSpan);
			Duration duration = Duration.between(LocalTime.MIN, locaTime);

      // Perform a retry after "duration" interval of time has elapsed
    }
  }
}