使用 Go 构建我们的第一个 GraphQL 服务器:实施指南

2023年 10月 17日 34.3k 0

trivago 为旅行者提供了广泛的酒店选择,使他们能够比较价格并发现最佳的度假优惠。由于有这么多可用的特殊选项,我们引入了一项名为“收藏夹”的新功能来简化导航过程。此功能使用户能够轻松保存他们喜欢的住宿并稍后访问,确保易用性。

幕后花絮

我们已经开始实施强大的后端解决方案来支持该功能,并付出必要的努力来确保其成功。我们最初的计划是使用 GraphQL 服务器(GraphQL 整体)作为 API 和传入请求之间的中间层。这种方法意味着请求在到达 API 之前必须经过另一个服务。下图说明了我们最初的想法以及它的运作方式。

使用 Go 构建我们的第一个 GraphQL 服务器:实施指南-1

值得注意的是,我们的 GraphQL 设置是联合的,这意味着请求通过 GraphQL 网关分布在子图之间。我们的 GraphQL 整体架构就是这样的一个子图。然而,通过整体与网关通信会增加延迟和依赖性,因此我们试图避免这种情况。由于我们已经有一个 GraphQL 网关来减少资源消耗并提高响应时间,因此我们选择通过在网关后面实现专用 GraphQL 服务器来利用它,从而绕过整体。这一变化为我们带来了以下好处:

  • 客户端始终使用网关的架构,幕后更改不会影响任何客户端。
  • 由于我们通过绕过整体跳过了一个步骤,因此客户端可能应该直接从最喜欢的 GraphQL 服务器本身接收更快的响应。
  • 维护和支持更改更容易,因为我们只需更改最喜欢的 GraphQL 服务器上的代码和架构,而不必调整整体架构。
  • Go 支持在同一服务器中使用不同的路由运行 GraphQL 服务器和 REST API,这意味着在需要时迁移现有的 REST API 总是很容易。
  • 在 Go 中实现 GraphQL 服务器非常容易,唯一需要替换的是接口,其余实现保持不变,这意味着不需要额外的复杂实现。
  • 最喜欢的 GraphQL Server 可以完全依赖 GraphQL Gateway 来进行所有凭证身份验证。

下图显示了最终设计。

使用 Go 构建我们的第一个 GraphQL 服务器:实施指南-1

生成 GraphQL 服务器

通过使用名为的库,在 Go 中实现 GraphQL 服务器非常容易吉吉根。可以通过以下命令启动 GraphQL 服务器:

go run github.com/99designs/gqlgen init

然后将按照官方说明创建以下文件夹结构文档

├── go.mod
├── go.sum
├── gqlgen.yml               - The gqlgen config file, knobs for controlling the generated code.
├── graph
│   ├── generated            - A package that only contains the generated runtime
│   │   └── generated.go
│   ├── model                - A package for all your graph models, generated or otherwise
│   │   └── models_gen.go
│   ├── resolver.go          - The root graph resolver type. This file wont get regenerated
│   ├── schema.graphqls      - Some schema. You can split the schema into as many graphql files as you like
│   └── schema.resolvers.go  - the resolver implementation for schema.graphql
└── server.go                - The entry point to your app. Customize it however you see fit

生成文件后,必须定义 GraphQL 服务器的模式,该模式将在 GraphQL 网关的超级图中使用。定义架构后,可以通过运行以下命令来生成模型和解析器:

//go:generate go run github.com/99designs/gqlgen generate

但也可以执行一些make命令来生成所需的文件:

GRAPHQL = bin/gqlgen
$(GRAPHQL): export GOBIN := $(PWD)/bin
$(GRAPHQL): go.mod
    $(GO) install github.com/99designs/gqlgen
    $(GO) mod tidy

$(addprefix generate-graphql-,$(COMMANDS)):
generate-graphql-%: export PATH = $(GOROOT)/bin:$(PWD)/bin
generate-graphql-%: $(GRAPHQL)
    $(GO) generate ./cmd/$*/...

其余的代码非常类似于在 Go 中实现传统的 REST API。GraphQL 服务器的处理程序必须启动,并且可以将依赖项注入到resolver.go

qlSrv := handler.NewDefaultServer(
        generated.NewExecutableSchema(generated.Config{Resolvers: &graph.Resolver{
            Logger:      logger,
            Service:     service
        }}))

之后,依赖项将可在 schema.resolvers.go 中使用,因为它resolver.go默认嵌入为属性。

一旦定义了模式并生成了服务器,查询和突变解析器将在schema.resolvers.go. 这将是 GraphQL 服务器的处理程序文件。以下示例显示了架构定义和用于获取收藏夹的查询:

type Query {
  """
  Returns user's saved favorite accommodations.
  """
  getMyFavoriteAccommodations: MyFavoriteAccommodationsResponse!
}

代码如下所示:

type queryResolver struct{ *Resolver }

func (r *queryResolver) GetMyFavoriteAccommodations(ctx context.Context) (*model.MyFavoriteAccommodationsResponse, error) {...}

该函数是返回用户收藏夹的处理程序。从这一点来看,它与实现传统 REST API 的流程相同,您可以在这里简单地实现您的业务流程。

结论

转换现有 API 可能有些挑战性,但由于 Go 服务器可以支持 REST API 和 GraphQL,因此从一种 API 切换到另一种 API 非常容易。在我们的例子中,客户端仍处于实现阶段,因此我们不需要同时支持 REST API 和 GraphQL 服务器,我们只需切换到 GraphQL 服务器即可。

另一个重要的一点是为您的模式定义编写注释。当超级图收集您构建的模式时,它将呈现给客户,您写的注释越多,客户就越容易导航。

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论