Azure Cosmos DB 故障排除

数据 API 生成器中常见 Azure Cosmos DB 模拟器、连接和架构配置问题的解决方案。

常见问题

DAB 中的 Azure Cosmos DB 支持是什么?

数据 API 生成器支持将 Azure Cosmos DB 作为 NoSQL 后端。 DAB 使用 Azure Cosmos DB .NET SDK 连接到 Cosmos DB,并将实体公开为 GraphQL 类型。 对 Cosmos DB 的 REST 支持不可用;所有查询都通过 GraphQL 终结点提供。

DAB 与 Cosmos DB 配合使用的 API 是什么?

DAB 使用 Azure Cosmos DB for NoSQL API(前 SQL API)。 不支持其他 Cosmos DB API,例如 MongoDB、Gremlin 和 Table。 确保使用 Azure Cosmos DB for NoSQL API 创建 Cosmos DB 帐户。

是否支持 Cosmos DB 模拟器?

是的。 支持本地开发的有 Azure Cosmos DB 模拟器。 将连接字符串设置为模拟器的默认终结点: AccountEndpoint=https://localhost:8081/;AccountKey=<emulator-key>;。 在 DAB 连接之前,必须在开发计算机上信任模拟器的自签名证书。

常见问题

模拟器证书不受信任

症状: DAB 因 SSL 或证书验证错误而无法连接到模拟器。

原因: Azure Cosmos DB 模拟器使用在操作系统上默认不受信任的自签名证书。

分辨率:https://localhost:8081/_explorer/emulator.pem 本地计算机的受信任根证书存储中导出并安装仿真器证书。 在 Windows 上,打开证书文件并将其安装到 本地计算机 > 受信任的根证书颁发机构。 安装证书后重启 DAB。

无法连接到模拟器

症状: DAB 无法启动 The remote name could not be resolved: 'localhost' 或提示拒绝连接错误,指向端口 8081

原因: 模拟器未运行,或者连接字符串中的终结点或帐户密钥不正确。

分辨率: 从“开始”菜单或运行模拟器可执行文件启动 Azure Cosmos DB 模拟器。 确认连接字符串使用 AccountEndpoint=https://localhost:8081/ 以及正确的模拟器密钥,该密钥显示在模拟器的数据资源管理器页面上 https://localhost:8081/_explorer/index.html

找不到 GraphQL 架构文件

症状: DAB 无法启动并显示错误,例如 Schema file not foundgraphql-schema path is invalid

原因:dab-config.json 中的 graphql.schema 路径指向不存在的文件,或使用了不正确的相对路径。

分辨率: 验证架构文件是否存在于指定的路径中 dab-config.json。 路径相对于配置文件位置。 运行 dab init 并使用 --cosmosdb_nosql-schema 重新生成带有正确架构路径的配置,然后确认在该位置中存在 .gql.graphql 文件。

查询返回空结果

症状: 即使容器具有数据,GraphQL 查询也会返回空列表。

原因: 实体配置中的容器名称或分区键路径与实际的 Cosmos DB 容器不匹配,或者数据库名称不正确。

解决方案:请检查实体source的值在dab-config.json中,并确认它是否与容器名称完全匹配(区分大小写)。 检查 database 下的data-source字段是否与 Cosmos DB 数据库名称匹配。 在 Azure 门户中,打开帐户 的数据资源管理器 ,并确认数据库和容器名称。

使用 Linux 模拟器的直接模式 TCP 连接失败

症状: 在 Docker 中连接到 Cosmos DB Linux 模拟器时,即使设置了 AZURE_COSMOS_EMULATOR_IP_ADDRESS_OVERRIDE=127.0.0.1,DAB 仍会挂起或超时。 请求在连接重试期间停止。

原因: DAB 当前直接硬编码 ConnectionMode.Direct,这会导致 Cosmos SDK 获取物理分区终结点(例如 172.17.0.2:1025010255),并打开与其的 TCP 连接。 在主机中,这些容器地址无法访问。 网关模式会通过单个 HTTPS 终结点(模拟器上的端口 8081)路由所有流量,并完全避免问题。 这是 GitHub 问题 #3401 中跟踪的已知限制。

分辨率: 启动模拟器容器时设置 AZURE_COSMOS_EMULATOR_IP_ADDRESS_OVERRIDE=127.0.0.1。 这会强制模拟器播发 127.0.0.1 作为其地址,使发现的终结点可从主机访问。 在 DAB 的网关模式变得可配置之前,建议使用 IP 覆盖作为本地开发的替代方案。

不支持Behalf-Of(OBO)身份验证

症状: 为 Azure Cosmos DB 支持的 DAB 实例配置 On-Behalf-Of (OBO) 身份验证失败,或者令牌未按预期转发。

原因: 目前仅 SQL Server 和 Azure SQL 支持 OBO 身份验证。 尚未实现对 Azure Cosmos DB 的支持。 这是 GitHub 问题 #3159 中跟踪的已知限制。

分辨率: 使用受支持的身份验证方法,例如 Cosmos DB 帐户密钥或托管标识。 在 OBO 支持扩展到非 SQL Server 数据库时,请关注 GitHub 上的问题以获取更新。

Cosmos DB 上的筛选器中的 GraphQL 失败

< c0>症状: 在针对 Cosmos DB 支持的实体的 GraphQL 查询中,以 in 运算符在运行时失败,因为无法生成未知的谓词操作 IN,即使该操作通过自省在架构中出现。

原因: in 运算符在生成的 GraphQL 架构中被 IdFilterInput 和 StringFilterInput 所暴露,但其底层的 Cosmos DB 过滤器翻译逻辑并未实现这一点。 架构与查询执行程序之间的这种不匹配是 GitHub 问题 #3061 中跟踪的已知 bug。

分辨率: 避免在 GraphQL 查询中针对 Cosmos DB 实体使用 in 运算符。 请改用以下解决方法之一:

  • 使用一个小型固定值列表中的多个或 + q 表达式进行替换。
  • 在通过已知 ID 列表进行查询时,请使用多个点读取别名(item_by_pk)。
  • 在检索到更广泛的结果集后,在客户端进行筛选。

Cosmos DB 不支持聚合

症状: 针对 Cosmos DB 后端实体的 GraphQL 聚合查询(例如计数、求和或 vg)失败或在架构中不可用。

原因: 数据 API 生成器目前不支持 Azure Cosmos DB 的聚合操作。 聚合仅适用于关系数据库。 这是 GitHub 问题 #2849 中跟踪的已知限制。

分辨率: 目前 DAB 中没有解决方法。 在检索结果集后,在客户端执行聚合,或者使用 Cosmos DB 的内置查询 API 直接进行聚合操作。 关注 GitHub 问题以获取更新。

无法禁用复数(列表)查询以强制执行点只读

症状: 当仅允许通过 item_by_pk 进行点读取时,客户端能够针对 Cosmos DB 实体发出广泛的项目列表查询,从而消耗大量请求单位 (RU)。

原因: 数据 API 生成器当前不提供一个配置选项来取消复数查询,并将实体限制为仅指向只读。 这是 GitHub 问题 #2433 中跟踪的已知限制。

解决方案: 作为部分解决方法,限制实体权限中的列表操作,以限制哪些角色可以发出查询请求。 尚不支持从架构中完全抑制复数查询类型。

不支持分层分区键(MultiHash)

症状: 针对使用分层分区键(多个分区键路径)的 Cosmos DB 容器的突变失败,并出现错误:分区键定义中指定的“kind”值“MultiHash”无效。 请选择“哈希”分区类型。

原因: 数据 API 生成器仅支持单键(哈希)分区键定义。 不支持使用分层分区键(MultiHash)配置的容器。 这是 GitHub 问题 #1733 中跟踪的已知限制。

分辨率: 目前 DAB 中没有解决方法。 如果可能,请重新设计容器以使用单个分区键。 如果数据模型需要分层分区键,请关注 GitHub 问题,以获取关于何时添加多哈希支持的最新信息。

不支持 MultiHash 分区键

症状: 对使用分层(多哈希)分区键的 Cosmos DB 容器的突变失败,分区键定义中指定的“kind”值“MultiHash”无效。 请选择“哈希”分区类型。

原因: 数据 API 生成器仅支持 Azure Cosmos DB 的单值哈希分区键。 不支持使用分层分区键(MultiHash)配置的容器,例如 /TenantId、/EntityType、/EntityId。 这是 GitHub 问题 #1733 中跟踪的已知限制。

分辨率: 目前 DAB 中没有解决方法。 请改用具有单个哈希分区键的容器。 如果需要分层分区,请考虑调整容器或关注 GitHub 相关问题,查看有关添加 MultiHash 分区键支持的更新。

Cosmos DB 上的多个突变不是原子性的

症状: 当在单个请求中针对 Cosmos DB 实体发送多个 GraphQL 变化时,一个变化失败不会回滚其他变化。 可能会发生部分写入。

原因: 数据 API 生成器不会在事务批处理中包装多个 Cosmos DB 突变。 与关系数据库不同的是,请求中的多个变更以原子方式执行,而 Cosmos DB 的变更是独立发出的。 这是 GitHub 问题 #1621 中跟踪的已知限制。

解决方案: 设计应用程序以将每个 Cosmos DB 变更视为独立。 如果需要原子性,请直接将 Cosmos DB SDK 与事务批处理支持配合使用,范围限定为同一逻辑分区中的项。 关注 GitHub 议题,以获取关于何时为 Cosmos DB 增加事务性变更支持的更新。

架构文件中的 GraphQL 类型名称与实体配置不匹配

症状: DAB 不出错,但查询返回意外结果或错误类型,因为 schema.gql 中定义的 GraphQL 类型名称与为 dab-config.json中实体配置的单一类型名称不匹配。

原因: 数据 API 生成器当前不验证架构文件中的 GraphQL 类型名称是否与为实体声明的单一类型名称匹配。 不匹配悄无声息地生成不一致的模式。 这是 GitHub 问题 #1556 中跟踪的已知限制。

分辨率: 手动验证 schema.gql(通过 @model 指令设置)中的类型名称是否与 dab-config.json实体的 graphql.type 配置中的单一值匹配。 例如,如果 dab-config.json 声明“单一”:“位置”,则架构文件应包含 type Location@model(name:“Location”。

架构文件中的 GraphQL 类型名称与实体单一类型名称不匹配

症状: DAB 不出错,但查询返回意外结果或错误类型,因为 schema.gql 中定义的 GraphQL 类型名称与为 dab-config.json中实体配置的单一类型名称不匹配。

原因: 数据 API 生成器当前不验证 GraphQL 架构文件中的 @model 指令名称是否与实体设置的单一类型名称匹配。 当它们不同时,不匹配会以无提示方式生成不正确的架构行为。 这是 GitHub 问题 #1556 中跟踪的已知限制。

分辨率: 手动确保 schema.gql 中的类型名称与 dab-config.json中实体 graphql.type 配置中的单一值完全匹配。 例如,如果实体定义“单一”:“位置”,架构文件应声明 ype Location :“Location @model(name”。 完成更改后,运行 dab 验证以捕获其他配置错误。

GraphQL 架构文件中的枚举类型会导致架构生成失败

症状: DAB 无法以 HotChocolate.SchemaException 开头:无法解析类型引用...当 Cosmos DB schema.gql 文件定义对象类型字段上使用的 GraphQL num 类型时,OrderByInput 错误。

原因: 数据 API 生成器目前不支持 Cosmos DB 架构文件中的 GraphQL 枚举类型。 当枚举用作字段类型时,架构生成器无法生成相应的 OrderByInput 类型并引发未经处理的异常。 这是 GitHub 问题 #748 中跟踪的已知限制。

分辨率: 将枚举字段替换为其标量等效项(例如,在 schema.gql 中使用 String 而不是自定义枚举类型)。 在应用程序层而不是 DAB 架构定义中应用枚举验证。

GraphQL 架构中的枚举类型导致 DAB 在启动时失败

症状: 当 Cosmos DB GraphQL 架构文件定义模型中使用的枚举类型时,DAB 无法启动 HotChocolate.SchemaException 错误,例如无法解析类型引用“None: FooOrderByInput”。

原因: 数据 API 生成器的架构生成器无法正确处理 schema.gql 中定义的 GraphQL 枚举类型。 当枚举作为模型上的字段类型引用时,内部的 OrderByInput 类型生成过程无法解析它,导致架构初始化崩溃。 这是 GitHub 问题 #748 中跟踪的已知限制。

分辨率: 避免在 Schema.gql 中为 Cosmos DB 实体定义 GraphQL 枚举类型。 解决方法是将枚举字段替换为 String,并在应用程序层中强制实施有效值。 请关注 GitHub 的问题,以获取有关何时添加枚举支持的更新。

Cosmos DB 实体不支持字段映射(字段别名)

症状: 在 dab-config.json 中为 Cosmos DB 实体定义的映射部分没有生效,原始字段名称仍在 GraphQL 架构中显示,而不是使用配置的别名。

原因: 映射功能允许在 API 中的不同字段名称下公开数据库列名称,仅针对关系数据库实现。 Cosmos DB 实体目前不支持字段映射。 这是 GitHub 问题 #1512 中跟踪的已知限制。

解决方案: 使用与 Cosmos DB 文档中显示的字段名称完全相同。 如果需要别名,请将其应用于客户端应用层。 请关注 GitHub 上的相关问题以获取有关何时为 Cosmos DB 添加映射支持的更新。

GraphQL 突变变量存储的是变量名,而不是解析后的值。

症状: 使用变量(例如 createExample(item: { id: , name: })) 的 GraphQL mutation 将变量名 "" 和 "" 存储在数据库中,而不是传入变量有效负载的实际值。

原因: 数据 API 生成器当前不会解析 Cosmos DB 的突变输入中的 GraphQL 变量引用。 略过变量替换,按字面书写变量名称作为字段值。 这是 GitHub 问题 #1482 中跟踪的已知 bug。

解决方案: 直接在变更正文中内联变量值,而不是使用 GraphQL 变量。 例如,将 ID 替换为 ID:“1234”。 这不适合用于生产,因此,请关注 GitHub 上的问题,以了解何时修复 Cosmos DB 变更的变量处理。

GraphQL 架构文件中的联合类型会导致 500 错误

症状: 当 schema.gql 定义 GraphQL 联合类型时,DAB 在所有 GraphQL 请求上返回 500 状态代码。 启动日志显示 HotChocolate.SchemaException:无法解析类型引用 ... OrderByInput。

原因: 数据 API 生成器不支持 Cosmos DB 架构文件中的 GraphQL 联合类型。 与枚举类型一样,联合类型会导致架构生成器在生成排序/筛选输入类型时失败。 这是 GitHub 问题 #1384 中跟踪的已知 bug。

分辨率: 从 schema.gql 中删除联合类型定义。 使用具有可选字段的单个对象类型为多态数据建模,或将数据拆分到不同的实体。 请关注 GitHub 问题以获取联合类型支持何时添加的更新。

当在架构中将 ID 定义为可为空时,运行时的创建变更操作会失败

症状: 即使架构看起来有效,创建突变也会返回运行时错误。 发生错误的原因是未提供 ID 字段或为 null。

原因: Cosmos DB 需要每个文档的 ID 字段,并将其用作分区键的一部分。 如果 schema.gql 将 id 声明为可为 null(例如,id: ID 而不是 id: ID!),DAB 会接受该架构,但在运行时如果创建操作省略了该字段则会失败。 模式应在模式验证时强制执行非空,但目前未强制执行。 GitHub 问题 #1238 中跟踪了此差距。

解决方案: 始终在 Cosmos DB GraphQL 架构中将 ID 字段声明为非空:

graphql type MyEntity @model(name: "MyEntity") { id: ID! ... }

确保ID:ID! 如果省略 ID 而不是不透明的运行时故障,则会导致客户端收到明确的架构级错误。

循环 GraphQL 关系在启动时导致堆栈溢出异常

症状: 当 schema.gql 定义循环中相互引用的类型(例如玩家引用游戏和游戏引用玩家)时,DAB 在启动时崩溃并出现堆栈溢出异常。

原因: 架构生成器以递归方式引导所有类型引用以生成突变输入类型。 循环关系会导致无限递归,耗尽调用堆栈。 这是 GitHub 问题 #746 中跟踪的已知 bug。

分辨率: 避免 schema.gql 中的循环类型引用。 通过从其中一种类型中删除后引用来中断循环,或将关系建模为 ID 列表(标量字段),而不是嵌套对象类型。 关注 GitHub 问题,了解何时支持循环关系的更新。

分区键始终是 ID,不支持自定义分区键路径。

症状: DAB 仅适用于将 /id 用作分区键的 Cosmos DB 容器。 无法正确查询或改变由任何其他字段(例如 /userId 或 /category)分区的容器。

原因: 数据 API 生成器将 ID 硬编码为所有 Cosmos DB 实体的分区键。 在 dab-config.json 或 schema.gql 中无法指定自定义分区键路径。 这是 GitHub 问题 #747 中跟踪的已知限制。

解决方案: 在使用 DAB 时,以 /id 作为分区键设计新容器。 对于具有不同分区键的现有容器,目前不支持 DAB。 关注 GitHub 上的问题以获取有关何时添加可配置分区键的更新。

不支持在文档(项内联接)中查询嵌套数组

症状: 不能使用 DAB 筛选或遍历 Cosmos DB 文档中的嵌套数组属性。 会导致 Cosmos DB 在数组元素之间进行 JOIN 的查询不会返回结果或会引发错误。

原因: 数据 API 生成器不支持 Cosmos DB 文档内联接 (也称为项内联接),这需要查询单个文档中的嵌套数组。 这是 GitHub 问题 #262 中跟踪的已知限制。

分辨率: 如果需要筛选嵌套数组的内容,将嵌套数组平展到单独的实体或子文档中。 或者,在应用程序层中执行完整文档的后期处理。 请关注 GitHub 上的问题,以获取有关何时添加文档内连接支持的更新。