用GraphQL介绍有关性能相关的问题

你好,今天是Openlogi的Advent Calendar活动的第18天。

上次和上上次我写了关于GraphQL的实现。接下来继续讲解GraphQL。

在GraphQL中最常讨论的是关于无法通过REST API实现的灵活查询,但在实际应用中,需要克服一些障碍才能使用它。

如果要提出个人意见,那么认证、授权和绩效可能是其中的几个方面。在本文中,我打算介绍与绩效相关的方法和措施。

在REST的情况下,并没有特别困难来估计特定终端点的数据量和所需时间。但是,在GraphQL中,由于需要在客户端定义需要获取的数据,可能会执行非常高负荷的查询。

例如,在上一篇文章中,我举了以下的模式作为例子。
在这里,表示了存在用户和用户能够浏览的订阅内容。

type Query {
  viewer: User
}
type User {
  id: String
  name: String
  feeds: [Feed]
}
type Feed {
  id: String
  title: String
  body: String
  author: User
}

我写了这样的查询,考虑显示首页的时间线。

query {
  viewer {
    id
    name
    feeds {
      title
      body
      author {
        id
        name
      }
    }
  }
}

然而,对于这个架构,也可以编写这样的查询。(不考虑是否应该查看他人的动态列表。)

query {
  viewer {
    id
    name
    feeds {
      title
      body
      author {
        id
        name
        feeds {
          title
          body
          author {
            id
            name
            feeds {
              // 以下無限ループ
            }
          }
        }
      }
    }
  }
}

这样一来,GraphQL可能存在着让数千、数万次数据库访问轻而易举地发生的危险。因此,我将介绍一些关于GraphQL性能的方法。

对查询进行验证

请求大小验证

首先,在底层的方法上,可以通过限制传递给请求的查询的大小来进行限制。简单地通过查询的大小来进行控制。

对于查询结构的验证。

如果需要更复杂的操作,还可以考虑查看查询的嵌套层次的方法。由于GraphQL查询可以转换为AST表示,因此限制其最大深度或者禁止特定结构的查询也是可行的方法之一。

执行超时操作

在每个Resolver的处理中,设置超时也是有用的。有关GraphQL查询超时和复杂性管理的详细信息,请点击 这里 。这是一种在超过一定时间后停止处理并阻止后续Resolver触发的方法。

持续查询

問題是可能收到未预料的查询。因此,我们采取的方法是只允许预先确定的查询。这可以通过使用类似persistgraphql的库来实现,简单概括一下,

    在构建时,获取用于客户端的查询列表。对每个查询进行哈希处理,并创建实际查询与哈希值之间的映射。客户端发送哈希值,服务器端解析并执行查询。

我們將進行類似的活動。

网络性能

由于GraphQL在客户端中包含数据结构来获取数据,这可能会导致请求的查询大小变得庞大。尽管可以通过使用上述持久化查询中的哈希值来解决此问题,但也可以使用后面提到的Apollo Engine的“自动持久化查询”来解决。
与上述的持久化查询不同,这只是为了减小请求大小。通过在首次执行时在服务器端缓存查询和哈希值,可以通过仅向服务器发送哈希值来执行查询,从而使得在第二次及以后的请求中可以减少数据传输量。

n + 1问题

尽管主题有些不同,但在GraphQL中基本上无法使用类似Eager loading的机制,因此简单地实现总是会引发n+1问题。Facebook的dataloader可以简洁地解决这个问题。除了js之外,还有类似的库可供查找。

关于测量

无论采取哪种方法,都需要进行性能改进的测量。GraphQL的测量很容易通过使用名为Apollo Engine的服务来进行,我将介绍一下。

可以做什么呢?

在阿波罗引擎上,您可以看到以下信息:

执行日期和处理时间的查询信息

スクリーンショット 2017-12-18 0.07.24.png

各查询的处理时间和数量的统计数据

スクリーンショット 2017-12-17 23.14.59.png

各节点的处理时间统计

スクリーンショット 2017-12-17 23.15.51.png

每个节点的处理时间针对特定请求。

スクリーンショット 2017-12-17 23.15.17.png

另外,您还可以查看错误发生率等信息。顺便说一下,免费的请求限额是1M/月。即使只是开发环境,也可以轻松发现有问题的查询,所以安装是没有损失的。

如果使用Node.js,可以像这样嵌入。


var { Engine } = require('apollo-engine');

const engine = new Engine({
  engineConfig: {
    apiKey: process.env.APOLLO_ENGINE_API_KEY,
    logging: {
      level: 'DEBUG'
    }
  },
  graphqlPort: PORT,
  endpoint: '/graphql',
  dumpTraffic: true
});
engine.start()

app.use(engine.koaMiddleware());

最后

在AWS的App Sync中,宣布了利用Apollo进行离线支持和实时更新的功能。希望这能推动GraphQL生态系统进一步发展。

广告
将在 10 秒后关闭
bannerAds