在现代前端开发中,GraphQL 已经成为了越来越流行的 API 查询语言。它的优势在于可以让前端开发者精确地获取需要的数据,而不用担心过多或过少的数据。然而,对于大型应用程序来说,管理多个 GraphQL 服务可能会变得非常复杂。这时候,单一来源 GraphQL 服务器就会变得非常有用。
在本篇文章中,我们将讨论如何创建单一来源 GraphQL 服务器,并提供一些示例代码来帮助您入门。
什么是单一来源 GraphQL 服务器
单一来源 GraphQL 服务器是指将多个 GraphQL 服务聚合到一起,从而形成一个单一的 GraphQL 端点。这个端点可以向客户端提供来自多个服务的数据,同时也可以对客户端发出的查询进行路由和转发。
单一来源 GraphQL 服务器的优点在于,它可以让客户端只与一个 GraphQL 端点通信,从而简化了客户端代码。此外,它还可以提高性能,因为可以将多个查询合并为一个,从而减少了网络请求的数量。
下面是一个简单的单一来源 GraphQL 服务器的架构图:
如上图所示,单一来源 GraphQL 服务器由三个部分组成:
- GraphQL 端点:客户端将向此端点发送所有 GraphQL 查询。
- Schema Stitching:将多个服务的 GraphQL schema 合并成一个。
- Query Routing:将客户端的查询路由到正确的服务上,并将结果聚合返回给客户端。
步骤 1:合并 GraphQL Schema
要创建单一来源 GraphQL 服务器,首先需要将多个服务的 GraphQL schema 合并成一个。这个过程被称为 schema stitching。
有多种方法可以进行 schema stitching,其中一种是使用 Apollo Server。Apollo Server 提供了一个名为 mergeSchemas
的函数,可以将多个 schema 合并成一个。
以下是一个示例代码,演示如何使用 mergeSchemas
函数将两个 schema 合并成一个:
// javascriptcn.com 代码示例 const { ApolloServer, mergeSchemas } = require('apollo-server'); const { makeExecutableSchema } = require('graphql-tools'); const schema1 = makeExecutableSchema({ typeDefs: ` type Query { hello: String } `, resolvers: { Query: { hello: () => 'Hello from schema 1!' } } }); const schema2 = makeExecutableSchema({ typeDefs: ` type Query { world: String } `, resolvers: { Query: { world: () => 'World from schema 2!' } } }); const server = new ApolloServer({ schema: mergeSchemas({ schemas: [schema1, schema2] }) }); server.listen().then(({ url }) => { console.log(`Server ready at ${url}`); });
在上面的示例中,我们先定义了两个 schema,然后使用 mergeSchemas
函数将它们合并成一个。最后,我们创建了一个 Apollo Server 实例,并将合并后的 schema 传递给它。
步骤 2:查询路由
一旦将多个 schema 合并成一个,就需要将客户端的查询路由到正确的服务上。这可以通过编写一个自定义的数据源来实现。
以下是一个示例代码,演示如何编写一个自定义的数据源:
// javascriptcn.com 代码示例 const { RESTDataSource } = require('apollo-datasource-rest'); class Service1API extends RESTDataSource { constructor() { super(); this.baseURL = 'http://service1.com/'; } async getHello() { return this.get('hello'); } } class Service2API extends RESTDataSource { constructor() { super(); this.baseURL = 'http://service2.com/'; } async getWorld() { return this.get('world'); } } const server = new ApolloServer({ schema: mergeSchemas({ schemas: [schema1, schema2] }), dataSources: () => ({ service1API: new Service1API(), service2API: new Service2API() }), context: ({ dataSources }) => ({ service1API: dataSources.service1API, service2API: dataSources.service2API }), resolvers: { Query: { hello: (_, __, { service1API }) => service1API.getHello(), world: (_, __, { service2API }) => service2API.getWorld() } } }); server.listen().then(({ url }) => { console.log(`Server ready at ${url}`); });
在上面的示例中,我们定义了两个数据源 Service1API
和 Service2API
,它们分别连接到两个服务。然后,我们在 Apollo Server 的配置中将这两个数据源注册,并将它们传递给 context。最后,我们编写了两个 resolver,将客户端的查询路由到正确的数据源上。
步骤 3:执行查询
一旦客户端的查询被路由到正确的数据源上,就需要将每个数据源的结果聚合到一起,并将结果返回给客户端。这可以通过编写一个自定义的 executor 来实现。
以下是一个示例代码,演示如何编写一个自定义的 executor:
// javascriptcn.com 代码示例 const { ApolloServer, mergeSchemas } = require('apollo-server'); const { makeExecutableSchema } = require('graphql-tools'); const schema1 = makeExecutableSchema({ typeDefs: ` type Query { hello: String } `, resolvers: { Query: { hello: () => 'Hello from schema 1!' } } }); const schema2 = makeExecutableSchema({ typeDefs: ` type Query { world: String } `, resolvers: { Query: { world: () => 'World from schema 2!' } } }); const server = new ApolloServer({ schema: mergeSchemas({ schemas: [schema1, schema2] }), dataSources: () => ({ service1API: new Service1API(), service2API: new Service2API() }), context: ({ dataSources }) => ({ service1API: dataSources.service1API, service2API: dataSources.service2API }), executor: async ({ document, variables, context }) => { const service1Promise = context.service1API.process({ query: document, variables }); const service2Promise = context.service2API.process({ query: document, variables }); const [service1Result, service2Result] = await Promise.all([ service1Promise, service2Promise ]); return { data: { hello: service1Result.data.hello, world: service2Result.data.world } }; } }); server.listen().then(({ url }) => { console.log(`Server ready at ${url}`); });
在上面的示例中,我们编写了一个自定义的 executor,并在 Apollo Server 的配置中将它注册。这个 executor 会将客户端的查询路由到正确的数据源上,并将每个数据源的结果聚合到一起。
总结
单一来源 GraphQL 服务器是管理多个 GraphQL 服务的有效方法。在本文中,我们讨论了如何创建单一来源 GraphQL 服务器,并提供了一些示例代码来帮助您入门。希望这篇文章对您有所帮助,让您更好地理解 GraphQL 和如何使用它来构建现代应用程序。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65556d6ad2f5e1655df91f2e