在Golang中实现GraphQL的3个技巧

2020年12月30日11:07:29 发表评论 48 次浏览

本文概述

什么是GraphQL?

后端技术人员通常会说GraphQL是REST API之后的"闪亮新手"。最初由Facebook开发, 成为内部使用的功能强大的数据提取API, 如今, 它每天为数十亿个API调用提供动力。

官方文档将GraphQL定义为API的查询语言, 可提供API数据的360度视图。但是从自由码阵营说:

" GraphQL是一种语法, 描述了如何请求数据, 通常用于将数据从服务器加载到客户端。它使客户端可以准确地指定请求中需要哪些数据, 从而使从多个源中选择数据更加容易。"

先决条件

本教程将重点介绍在使用Golang实施GraphQL时要注意的一些要点。要继续进行, 强烈建议你了解以下方面的工作知识:

  • 去编程语言
  • GraphQL

让我们回顾一下GraphQL

在讨论GraphQL的任何情况下, 某些关键字的使用都会比其他关键字更多。因此, 必须提醒自己其中一些单词:

GraphQL类型:这些是GraphQL模式定义的最基本组成部分。它们是JSON字段, 表示可以从服务中获取的对象的类型。看看这个教程详细了解GraphQL类型。

例如, 下面是一个具有三个字段的作者的样本类型定义:名称, id和书:

type author {
  name: String! //the `!` sign shows it’s required
  id: ID!
  book: String!
}

GraphQL查询:GraphQL查询是从GraphQL服务器请求或获取数据的一种方式。查询的结构方式将确定数据将被过度获取还是不足。这个教程详细解释查询。

以下是根据我们上面的类型定义对作者姓名进行查询的示例:

query {                     
  authors {                 
    name      
  }
}

GraphQL模式:模式就像地图。它们通过描述它们在服务器中的关系来帮助我们理解数据。这可以帮助客户知道在尝试访问数据时如何构造其请求。它们以SDL(即架构定义语言)编写。

我们为制作了一个自定义演示.
不完全是。点击这里查看.

在Golang中实现GraphQL的3个技巧1

解析器:解析程序在服务器中搜寻所需的数据。它们是特定领域的功能。这是GraphQL用于根据每个查询请求返回数据的唯一机制。

GraphQL突变:突变用于在GraphQL中创建和修改对象, 类似于REST API中的PUT和POST。它们遵循与查询类似的语法, 只是它们需要以关键字开头突变.

GraphQL订阅:此功能允许服务器针对其配置的每个特定事件向其客户端发送数据。为此, 服务器与订阅它的客户端保持稳定的连接

为什么使用GraphQL和Golang?

Go编程语言(也称为Golang)是最初由Google设计的通用编程语言。 Golang以其简单性, 并发性和快速性能以及许多其他精美功能而位居榜首。因此, 在实现GraphQL时, 它仍然是最重要的选择之一。

随着许多人意识到这种二重奏的潜力(GraphQL和Golang), 多年来的软件工程师开始构建库以将GraphQL与Golang无缝集成。

以下是一些使实现顺利的库:

  • Graph-gophers / graphql-go:这提供了解析GraphQL架构语言的支持, 同时在编译时提供了解析器信息, 而不必等到运行时才发现架构和解析器的问题。
  • GraphQL-go / graphql:与其他库一样, 它支持查询, 变异和订阅。它还模拟了官方实施GraphQL-js图书馆
  • 格列根:这优先于类型安全, 并基于架构优先方法。

在本教程中, 我们将不着重于这些库的实现。但是, 每个库都有一个例子你可以浏览到该文件夹​​以直接了解这些库的实现方式。

灯泡时刻来了

让我们探讨将GraphQL与Golang集成时我们会遇到的一些情况以及解决方案。

提示1:架构同质

的graphql-go / graphql是Golang中GraphQL的功能齐全的实现, 它支持查询, 变异和订阅以及许多其他功能。

尽管此库利用其他库的优势来帮助你构建可用于生产环境的GraphQL服务器, 但它是GraphQL.js的官方参考实现。换句话说, 它是GraphQL.js库的Golang版本。

它与GraphQL.js几乎相同的API的优点使读取为Node.js / JavaScript编写的另一个GraphQL模式变得非常容易, 而且你仍然可以为Golang重写它。让我们来看看:

Golang的GraphQL模式定义graphql-go

我们导入graphql-go打包并定义名为的GraphQL对象类型基本查询与你好字段以创建架构。

package main
 
import (
   "log"
   "github.com/graphql-go/graphql"
)
 
var queryType = graphql.NewObject(graphql.ObjectConfig{
   Name: "BaseQuery", Fields: graphql.Fields{
       "hello": &graphql.Field{
           Type: graphql.String, Resolve: func(p types.ResolveParams) interface{} {
               return "World!"
           }, }, }, })
 
var Schema, err = graphql.NewSchema(graphql.SchemaConfig{
   Query: queryType, })
if err != nil {
   log.Fatalf("failed to create new schema, error: %v", err)
}

在架构创建之后创建GraphQL服务器遵循官方中突出显示的正常步骤graphql-go文件资料这里.

带有GraphQL.js的JavaScript的Graphql模式定义

从下面的代码片段中, 我们需要GraphQL包, 并定义名为的GraphQL对象类型。基本查询与你好领域。这遵循上面的模式中突出显示的类似过程。

var graphql = require('graphql');
 
var queryType = new graphql.GraphQLObjectType({
   name: 'BaseQuery', fields: {
       hello: {
           type: graphql.GraphQLString, resolve: function () {
               return 'World!';
           }
       }
   }
});
 
var schema = new graphql.GraphQLSchema({
   query: queryType
});

仔细研究以上两种表示, 我们可以得出结论, 使用Golang在Golang中实现GraphQLgraphql-go无论你熟悉哪种编程语言, 图书馆都是在公园散步。

这是因为graphql-go该库非常类似于GraphQL.js的官方参考实现, 它是首选的事实上的库。结果, 它为GraphQL.js库提供了几乎相同的API。

提示2:解决n + 1问题

与每个API终结点使用一个解析器(请参阅上面的定义)的REST API不同, GraphQL每个字段执行一个解析器。这意味着每个请求可能有太多额外的解析器, 尤其是对于嵌套数据。这是n + 1问题。

这是一个示例查询, 可进一步支持此操作:

query {                     
 authors {            # fetches authors - query 1
   name      
   book {             # fetches books for each author (N queries for N authors)
     title
   }
 }
}                     # N+1 round trips

这是查询的响应:

{
 "writers": [{
   "name": "Tom Wolfe", "book": {
     "title": "The Bonfire of the Vanities"
   }
 }, {
   "name": "ALice Walker", "book": {
     "title": "The Color Purple"
   }    
 }]
}

上面的示例可能没有显示出升级到问题的速度。但是, 假设我们需要获取100位作者的数据, 则解析程序将进行100 + 1次行程以获取响应。同时, 只需完成两次旅行即可完成此操作;即请求和响应。

解决此问题的方法是批量处理。

批处理是Dataloader的主要功能。的数据加载器最初由Facebook在2010年为GraphQL.js开发, 用作应用程序数据提取层的一部分。它通过批处理和缓存在远程数据源上提供了简化且一致的API。但是, 还开发了其他几个数据加载器库用于graphql-go, 如:

  • 图形算法/数据加载器:这是官方facebook的副本实施数据加载器(用JavaScript编写)在Golang中
  • 数据加载来自作者Gqlgen:这会在Golang中生成类型安全的数据加载器, 以便与gglgen优先考虑类型安全性的库。它也受到官方数据加载器库的启发

还有许多其他。

数据加载器(与库无关)通过允许解析器请求数据并为数据返回承诺, 而不是立即返回所请求的确切字段来解决n + 1问题。然后, 这将批量处理来自请求的所有响应, 并立即做出响应, 因此需要两次旅行-请求和响应。

但是, 让我们看一下graphql-gophers / dataloader库的更多细节。

这是一个示例实现, 说明如何在不使用缓存的情况下使用该库。有关更多示例, 请遵循库的examples目录这里.

package no_cache_test
 
import (
 "context"
 "fmt"
 
 dataloader "github.com/graph-gophers/dataloader/v6"
)
 
func ExampleNoCache() {
 // go-cache will automaticlly cleanup expired items on given diration
 cache := &dataloader.NoCache{}
 loader := dataloader.NewBatchedLoader(batchFunc, dataloader.WithCache(cache))
 
 result, err := loader.Load(context.TODO(), dataloader.StringKey("some key"))()
 if err != nil {
   // handle error
 }
 
 fmt.Printf("identity: %s", result)
 // Output: identity: some key
}
 
func batchFunc(_ context.Context, keys dataloader.Keys) []*dataloader.Result {
 var results []*dataloader.Result
 // do some pretend work to resolve keys
 for _, key := range keys {
   results = append(results, &dataloader.Result{Data: key.String()})
 }
 return results
}

提示3:客户端-服务器数据架构不匹配

通常, 从头开始编写GraphQL后端涉及重复许多类似的代码(架构), 例如, 数据库和API端点的不同但相似的架构。

这是因为不同的架构影响了文档的存储方式。

范例:从数据库将返回一个authorID属性, 但对作者的相同查询服务器直接会返回作者属性。这使得难以在客户端和服务器之间共享代码以简化代码库。

const fetchBookTitleClient = author => {
   return author.book.title
}
 
const fetchBookTitleServer = author => {
   const authorDeets = Books.findOne(author.bookId)
   return authorDeets.title
}

解决此问题的方法是服务器间查询

回想起来, 这是通过将GraphQL模式添加到GraphQL函数来完成的, 如下所示:

graphql(
 schema: GraphQLSchema, requestString: string, rootValue?: ?any, contextValue?: ?any, variableValues?: ?{[key: string]: any}, operationName?: ?string
): Promise<GraphQLResult>

但是在实现中, 在我的代码中, 我以这种方式运行服务器到服务器查询:

const result = await graphql(executableSchema, query, {}, context, variables);

这可以极大地简化代码, 而无需提高性能。

总结

正如我们在本教程中所看到的, GraphQL不仅仅是一种API查询语言。它有可能完全改变数据和API查询方面的游戏。

有这样的潜力, 必须通过Golang等编程语言来利用GraphQL的全部好处。

Go编程语言的并发性, 简单性和快速的性能使其轻松地位居榜首。

我希望你喜欢在Golang中实现GraphQL时阅读这篇有关陷阱的文章。随时留下任何问题或反馈。

监视生产中失败的和缓慢的GraphQL请求

尽管GraphQL具有一些调试请求和响应的功能, 但要确保GraphQL能够可靠地为你的生产应用程序提供资源, 将使事情变得更加棘手。如果你有兴趣确保对后端或第三方服务的网络请求成功完成,

尝试notlogy

.

在Golang中实现GraphQL的3个技巧2
LogRocket仪表板免费试用横幅

https://notlogy.com/signup/

日志火箭就像Web应用程序的DVR一样, 实际上记录了你网站上发生的一切。你可以猜测问题的GraphQL请求并进行汇总, 以快速了解根本原因, 而不必猜测为什么会出现问题。此外, 你可以跟踪Apollo客户端状态并检查GraphQL查询的键/值对。

notlogy用你的应用程序记录基线性能计时, 例如页面加载时间, 到第一个字节的时间, 缓慢的网络请求, 并记录Redux, NgRx和Vuex的操作/状态。

免费开始监控

.

一盏木

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: