子图
了解联邦超级图中的子图
每个联邦 超级图 都包含一个或多个 子图。每个 子图 都是一个单独的 GraphQL 服务,负责超级图的各个部分的数据。
以下是一个基本的 supergraph,它包含两个 子图(用户和产品):
您可以使用完全不同的编程语言和 GraphQL 服务器 库来实现不同的子图。
选择子图库
您超级图中的每个 subgraph 都应该使用与子图兼容的 GraphQL 服务器 库。这些库遵循 Apollo Federation 子图规范,以确保您的超级图能充分利用联邦特性,如 实体。
在选择子图库后,请参阅其文档以了解如何配置其作为子图运行。
ⓘ 注意
如果您使用 Apollo Server 作为您的 subgraph 库,请参阅 使用 Apollo Server 实现 subgraph。
保护您的子图
在您的环境中实施任何必要的防火墙规则、访问控制列表或其他安全措施,以确保只有您的超级图 路由器 可以访问您的各个 subgraphs。
客户端不应该直接查询一个子图。相反,客户端应始终查询您的路由器,通过与子图进行通信来解决这些查询。
这样做有多个原因
- 子图库会自动将一些强大的字段添加到您的模式中,客户端不应该访问这些字段。
- 路由器使用这些字段在解决复杂操作时跨越子图边界。
- 为您的整个超级图提供一个单一端点可以减少其攻击面。
除了上述安全问题外,任何GraphQL API的一个显著好处是客户端只需与一个端点交互。这对于超级图来说尤其正确,尤其是拥有数十甚至数百个子图的情况。
有关如何使用GraphOS云超级图来保护您的子图的信息,请参阅这篇文章。
禁用CORS
我们建议子图不要启用CORS(或者至少,不要使用通配符access-control-allow-origin: *
头)。这可以阻止攻击者利用用户的浏览器直接访问子图。
对于Apollo Server子图,您需要禁用默认的通配符CORS策略(这种策略适用于许多单体公开API服务器,但不适用于子图)。有关详细信息,请参阅Apollo Server CORS文档。
特定于子图的字段
兼容子图的服务器库会自动将一些特定的联盟定义添加到您的子图模式中。除了指令定义,如@key
之外,这些定义中用于调试最有用的两个字段是Query类型的两个字段:_service
和_entities
:
type Query {# ...your field definitions...# Added automatically_service: _Service!_entities(representations: [_Any!]!): [_Entity]!}
查询._entities
💡 提示
了解实体(Entities)(如果您尚未了解的话)。
此字段接受实体表示列表并返回对应实体的列表。
每当一个子图(subgraph)引用另一个子图的实体时,它会使用实体表示来进行引用。实体表示是一个对象,它只包含实体的__typename
和实体'的关键字段'。
_entities(representations: [_Any!]!): [_Entity]!
- _Any类型是一个特殊的标量(scalar)类型,允许您提供任何有效形状的实体表示。
- _Entity类型是一个生成的联合类型(union type),它包含您的子图模式中定义的所有实体。
您可以通过如下方式查询此字段,并为$representations
变量提供值,如下所示:
query ($representations: [_Any!]!) {_entities(representations: $representations) {... on User {idusername}}}
{"representations": [{"__typename": "User","id": "5"}]}
用于测试和调试
如果您正在编写针对 子图 的集成测试,您可以测试 _entities
字段 对于其他 子图 使用的不同 实体 表示的返回值。
如果您在本地环境中开发 子图,您可以 模拟 其他 子图 _entities
字段 的返回值,这样您不需要将这些子图连接到它们各自的数据存储。
Query._service
此 字段 返回一个 _Service
对象,该对象有一个自己的 字段sdl
。您可以
query GetSubgraphSchema {_service {sdl}}
的 sdl
字段 返回您的 子图'的模式作为 SDL 字符串。此字段与标准 检查查询有一些重要区别,该工具Apollo Sandbox 使用:
- 与内省不同,
sdl
字段在生成环境中默认不是禁用的(如果您正确地保护您的子图),这是安全的)。 - 与内省不同,
sdl
字段返回的字符串包括特定的指令,例如@key
。