蚊章汇 - GraphQL
type: channel
link: https://linuxcn.bwsl.wang/tag/GraphQL/
items: 扩展一个 GraphQL 网站
items: 使用 GraphQL 作为 API 网关来监控微服务
items: 为什么使用 GraphQL？
items: 什么是 GraphQL？
items: GraphQL 用例：使用 Golang 和 PostgreSQL 构建一个博客引擎 API

扩展一个 GraphQL 网站
type: item
date: 2021-11-14T19:34:20+08:00
description: 我通常会抽象地总结我为他人所做的工作（出于显而易见的原因），但是我被允许公开谈论一个网站：Vocal 。我去年为它做了一些 SRE 工作。实际上早在 2 月份，我就在 GraphQL 悉尼会议上做过一次演讲，不过这篇博客推迟了一点才发表。Vocal 是一个基于 GraphQL 的网站，它获得了人们的关注，然后就遇到了可扩展性问题，而我是来解决这个问题的。这篇文章会讲述我的工作。显然，如果你正在扩展一个 GraphQL 站点，你会发现这篇文章很有用，但其中大部分内容讲的都是当一个站点获得了足够的流量而出现的必须解决的技术问题。如果你对站点可扩展性有兴趣，你可能想先阅读 最近我发表的一系列关于可扩展性的文章。VocalVocal 是一个博客平台，内容包括日记、电影评论、文章评论、食谱、专业或业余摄影、美容和生活小贴士以及诗歌，当然，还有可爱的猫猫和狗狗照片。Vocal 的不同之处在于，它允许人们制作观众感兴趣的作品而获得报酬。作者的页面每次被浏览都可以获得一小笔钱，还能获得其他用户的捐赠。有很多专业人士在这个平台上展示他们的工作，但对于大多数普通用户来说，他们只是把 Vocal 当作一个兴趣爱好，碰巧还能赚些零花钱作为奖励。Vocal 是新泽西初创公司 Jerrick Media 的产品，更新：Jerrick Media 已经更名为 Creatd，在纳斯达克上市。2015 年，他们与 Thinkmill 合作一起开发，Thinkmill 是一家悉尼中型软件开发咨询公司，擅长 JavaScript、React 和 GraphQL 开发。剧透不幸的是，有人告诉我，由于法律原因，我不能提供具体的流量数字，但公开的信息可以说明。Alexa 对所有网站按照流量进行排名。这是我演讲中展示的 Alexa 排名图，从 2019 年 11 月到今年 2 月，Vocal 流量增长到全球排名第 5567 位。曲线增长变慢是正常的，因为它需要越来越多的流量来赢得每个位置。Vocal 现在排名 4900 名左右，显然还有很长的路要走，但对于一家初创公司来说，这一点也不寒酸。大多数初创公司都很乐意与 Vocal 互换排名。在网站升级后不久，Creatd 开展了一项营销活动，使流量翻了一番。在技术方面，我们要做的就是观察仪表盘上的上升的数字。自发布以来的 9 个月里，只有两个平台问题需要员工干预：3 月份每五年一次的 AWS RDS 证书轮换，以及一款应用推出时遇到的 Terraform 错误。作为一名 SRE，我很高兴看到 Vocal 不需要太多的平台工作来保持运行。更新：该系统也抗过了 2020 年的美国大选，没有任何意外。以下是本文技术内容的概述：技术和历史背景从 MongoDB 迁移到 Postgres部署基础设施的改造使应用程序兼容扩展措施让 HTTP 缓存发挥作用其他一些性能调整一些背景信息Thinkmill 使用 Next.js（一个基于 React 的 Web 框架）构建了一个网站，和 Keystone 在 MongoDB 前面提供的 GraphQL API 进行交互。Keystone 是一个基于 GraphQL 的无头 CMS 库：在 JavaScripy 中定义一个模式，将它与一些数据存储挂钩，并获得一个自动生成的 GraphQL API 用于数据访问。这是一个自由开源软件项目，由 Thinkmill 提供商业支持。Vocal V2Vocal 的第一版就受到了关注，它找到了一个喜欢它的用户群，并不断壮大，最终 Creatd 请求 Thinkmill 帮助开发 V2，并于去年 9 月成功推出。Creatd 员工避免了 第二个系统效应，他们一般都是根据用户的反馈进行改变，所以他们 主要是 UI 和功能更改，我就不赘述了。相反，我将讨论下我的工作内容：使新站点更加健壮和可扩展。声明：我很感谢能与 Creatd 以及 Thinkmill 在 Vocal 上的合作，并且他们允许我发表这个故事，但 我仍然是一名独立顾问，我写这篇文章没有报酬，甚至没有被要求写它，这仍然是我自己的个人博客。迁移数据库Thinkmill 在使用 MongoDB 时遇到了几个可扩展性问题，因此决定升级到 Keystone 5 以利用其新的 Postgres 支持。如果你从事技术工作的时间足够长，那你可能还记得 00 年代末的 “NOSQL” 营销，这可能听起来很有趣。NoSQL 的一个重要特点是，像 Postgres 这样的关系数据库（SQL）不像 MongoDB 这样“网站级规模”的 NoSQL 数据库那样具有可扩展性。从技术上将，这种说法是正确的，但 NoSQL 数据库的可扩展性来自它可以有效处理各种查询的折衷。简单的非关系数据库（如文档数据库和键值数据库）有其一席之地，…

使用 GraphQL 作为 API 网关来监控微服务
type: item
date: 2020-09-07T04:51:36+08:00
description: 在问题导致关键的微服务瘫痪之前，使用 GraphQL 的监控功能帮助你及早发现问题。微服务和 GraphQL 就像面包和黄油一样，是一个很好的组合。它们本身都很棒，结合起来就更棒了。了解你的微服务的健康状况是很重要的，因为它们运行着重要的服务。如果等到某个关键的服务崩溃了才诊断问题，那是很愚蠢的。让 GraphQL 帮助你及早发现问题并不需要花费太多精力。常规的健康检查可以让你观察和测试你的服务，在问题影响到你的业务、客户或项目之前，尽早得到通知。说起来很简单，但健康检查到底要做什么呢？以下是我在设计服务检查时考虑的因素：服务器健康检查的要求：我需要了解我的微服务的可用性状态。我希望能够管理服务器的负载。我希望对我的微服务进行端到端（e2e）测试。我应该能够预测中断。做服务器健康检查的方法进行健康检查可能比较棘手，因为理论上，你可以检查的东西几乎是无穷无尽的。我喜欢从小处着手，运行最基本的测试：ping 测试。这只是测试运行应用的服务器是否可用。然后，我加强测试以评估特定问题，思考服务器中最重要的元素。我想到那些如果突然消失的话将是灾难性的事情。**Ping 检查：**Ping 是最简单的监控类型。它只是检查你的应用是否在线。**脚本化浏览器：**脚本化浏览器比较高级。像 Selenium 这样的浏览器自动化工具可以让你实现自定义的监控规则集。**API 测试：**API 测试用于监控 API 端点。这是 ping 检查模型的高级版本，你可以根据 API 响应来定义监控计划。使用 GraphQL 进行健康检查在一个典型的基于 REST 的微服务中，你需要从头开始构建健康检查功能。这是一个时间密集型的过程，但使用 GraphQL 就不用担心了。根据它的网站称：“GraphQL 是一种用于 API 的查询语言，也是一种用现有数据完成这些查询的运行时环境。GraphQL 为你的 API 中的数据提供了一个完整的、可理解的描述，让客户有能力精确地仅查询他们所需要的东西，让 API 更容易随着时间的推移而进化，并实现强大的开发者工具。”当你启动一个 GraphQL 微服务时，你还可以获得监控微服务的运行状况的供给。这是一个隐藏的宝贝。正如我上面提到的，你可以用 GraphQL 端点执行 API 测试以及 ping 检查。Apollo GraphQL 服务器提供了一个默认的端点，它可以返回有关你的微服务和服务器健康的信息。它不是很复杂：如果服务器正在运行，它就会返回状态码 200。默认端点是 <server-host>/.well-known/apollo/server-health。高级健康检查在某些情况下，基本的健康检查可能不足以确保系统的完整性。例如，紧密耦合的系统需要更多的业务逻辑来确保系统的健康。Apollo GraphQL 在定义服务器的同时，通过声明一个 onHealthCheck 函数来有效地管理这种情况。* Defining the Apollo Server */ const apollo = new ApolloServer({ playground: process.env.NODE_ENV !== 'production', typeDefs: gqlSchema, resolvers: resolver, onHealthCheck: () => { return new Promise((resolve, reject) => { // Replace the `true` in this conditional with more specific checks! if (true) { resolve(); } else { reject(); } }); } }); 当你定义一个 onHealthCheck 方法时，它返回一个 promise，如果服务器准备好了，它就会返回 resolve，如果有错误，它就会返回 reject。GraphQL 让监控 API 变得更容易。此外，在你的服务器基础架构中使用它可以使代码变得可扩展。如果你想尝试采用 GraphQL 作为你的新基础设施定义，请参见我的 GitHub 仓库中的示例代码和配置。via: https://opensource.com/article/20/8/microservices-graphql作者：Rigin Oommen 选题：lujun9972 译者：geekpi 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出

为什么使用 GraphQL？
type: item
date: 2020-04-05T18:58:35+08:00
description: 以下是 GraphQL 在标准 REST API 技术上获得发展的原因。正如我以前所写，GraphQL 是一种下一代 API 技术，它正在改变客户端应用程序与后端系统的通信方式以及后端系统的设计方式。由于一开始就从创建它的组织 Facebook 获得了支持，并得到了其他技术巨头（如 Github、Twitter 和 AirBnB）的支持，因此 GraphQL 作为应用程序系统的关键技术的地位似乎是稳固的 —— 无论现在还是将来。GraphQL 的崛起移动应用程序性能和组织敏捷性重要性的提高为 GraphQL 登上现代企业体系结构的顶端提供了助推器。鉴于 REST 是一种非常流行的体系结构风格，早已提供了数据交互机制，与 REST 相比，GraphQL 这项新技术具有哪些优势呢？GraphQL 中的 “QL” 代表着查询语言，而这是一个很好的起点。借助 GraphQL，组织内的不同客户端应用程序可以轻松地仅查询所需数据，这一点超越了其它 REST 方法，并带来了实际应用程序性能的提高。使用传统的 REST API 端点，客户端应用程序将详询服务器资源，并接受包含了与请求匹配的所有数据的响应。如果来自 REST API 端点的成功响应返回 35 个字段，那么客户端应用程序就会收到 35 个字段。获取的问题传统上，REST API 没有为客户端应用程序提供简便的方法来仅检索或只更新它们关心的数据。这通常被描述为“ 过度获取 over-fetching ”的问题。随着移动应用程序在人们的日常生活中的普遍使用，过度获取问题会给现实世界带来不良后果。移动应用程序发出的每个请求、每一个字节的接受和发送，对终端用户的性能影响越来越大。数据连接速度较慢的用户尤其会受到不太好的 API 设计方案的影响。使用移动应用程序而性能体验不佳的客户更有可能不购买产品或不使用服务。低效的 API 设计只会浪费企业的钱。并非只有“过度获取”是问题，“欠缺获取”同样也是问题。默认情况下，端点只返回客户端实际需要的部分数据，这需要客户端进行额外的调用以满足其数据需求，这就产生了额外的 HTTP 请求。由于过度和欠缺的获取问题及其对客户端应用程序性能的影响，促进有效获取的 API 技术才有机会在市场上引起轰动 —— GraphQL 大胆地介入并填补了这一空白。REST 的应对REST API 设计师不甘心不战而退，他们试图通过以下几种方式来应对移动应用程序性能问题：“包含”和“排除”查询参数，允许客户端应用程序通过可能较长的查询格式来指定所需的字段。“复合”服务，将多个端点组合在一起，以使客户端应用程序在其发出的请求数量和接收到的数据方面更高效。 尽管这些模式是 REST API 社区为解决移动客户端所面临的挑战而做出的英勇尝试，但它们在以下几个关键方面仍存在不足：包含和排除查询键/值对很快就会变得混乱，特别是对于需要用嵌套“点表示法”语法（或类似方法）以对目标数据进行包含和排除的深层对象图而言，更是如此。此外，在此模型中调试查询字符串的问题通常需要手动分解 URL。包含和排除查询的服务器的实现往往是自定义的，因为基于服务器的应用程序没有标准的方式来处理包含和排除查询的使用，就像没有定义包含和排除查询的标准方式一样。复合服务的兴起形成了更加紧密耦合的后端和前端系统，这就需要加强协调以交付项目，并且将曾经的敏捷项目转回瀑布式开发。这种协调和耦合还有一个痛苦的副作用，那就是减宦了组织的敏捷性。此外，顾名思义，组合服务不是 RESTful。GraphQL 的起源对于 Facebook 来说，从其 2011-2012 年基于 HTML5 版本的旗舰移动应用程序中感受到的痛点和体验，才造就了 GraphQL。Facebook 工程师意识到提高性能至关重要，因此意识到他们需要一种新的 API 设计来确保最佳性能。可能考虑到上述 REST 的局限性，并且需要支持许多 API 客户端的不同需求，因此人们可以理解是什么导致其共同创建者 Lee Byron 和 Dan Schaeffer（那时尚是 Facebook 员工）创建了后来被称之为 GraphQL 的技术的早期种子。通过 GraphQL 查询语言，客户端（通常是单个 GraphQL 端点）应用程序通常可以显著减少所需的网络调用数量，并确保仅检索所需的数据。在许多方面，这可以追溯到早期的 Web 编程模型，在该模型中，客户端应用程序代码会直接查询后端系统 —— 比如说，有些人可能还记得 10 到 15 年前在 JSP 上用 JSTL 编写 SQL 查询的情形吧！现在最大的区别是使用 GraphQL，我们有了一个跨多种客户端和服务器语言和库实现的规范。借助 GraphQL 这样一种 API 技术，我们通过引入 GraphQL 应用…

什么是 GraphQL？
type: item
date: 2020-04-04T19:30:27+08:00
description: GraphQL 是一种查询语言、一个执行引擎，也是一种规范，它让开发人员重新思考如何构建客户端和 API 应用。GraphQL 是当今软件技术中最大的流行语之一。但它究竟是什么？是像 SQL 一样的查询语言吗？是像 JVM 这样的执行引擎？还是像 XML 这样的规范？如果你回答上面这些都是，那么你是对的！GraphQL 是一种查询语言的语法、是一种编程语言无关的执行引擎，也是一种不断发展的规范。让我们深入了解一下 GraphQL 如何成为所有这些东西的，并了解一下人们为什么对它感到兴奋。查询语言GraphQL 作为查询语言似乎是合理的 —— 毕竟 “QL” 似乎重要到出现在名称中。但是我们查询什么呢？看一个示例查询请求和相应的响应可能会有所帮助。以下的用户查询：{ user(id: 4) { name email phoneNumber } }可能会返回下面的 JSON 结果：{ "user": { "name": "Zach Lendon" “email”: “zach@hydrate.io” “phoneNumber”: “867-5309” } }想象一下，客户端应用查询用户详细信息、获取结果，并使用它填充配置屏幕。作为查询语言，GraphQL 的核心优势之一是客户端应用可以只请求它需要的数据，并期望以一致的方式返回这些数据。那么 GraphQL 响应返回的什么呢？这就是执行引擎发挥的作用，通常是以 GraphQL 服务器的形式出现。执行引擎GraphQL 执行引擎负责处理 GraphQL 查询并返回 JSON 响应。所有 GraphQL 服务器由两个核心组件组成，分别定义了执行引擎的结构和行为：模式和解析器。GraphQL 模式是一种自定义类型语言，它公开哪些查询既允许（有效），又由 GraphQL 服务器实现处理。上面用户示例查询的模式可能如下所示：type User { name: String email: String phoneNumber: String } type Query { user: User }此模式定义了一个返回用户的用户查询。客户端可以通过用户查询请求用户上的任何字段，并且 GraphQL 服务器将仅返回请求的字段。通过使用强类型模式，GraphQL 服务器可以根据定义的模式验证传入的查询，以确保是有效的。确定查询有效后，就会由 GraphQL 服务器的解析器处理。解析器函数支持每个 GraphQL 类型的每个字段。我们的这个用户查询的示例解析器可能如下所示：Query: { user(obj, args, context, info) { return context.db.loadUserById(args.id).then( userData => new User(userData) ) } }虽然上面的例子是用 JavaScript 编写的，但 GraphQL 服务器可以用任意语言编写。这是因为 GraphQL 也是也是一种规范！规范GraphQL 规范定义了 GraphQL 实现必须遵循的功能和特性。作为一个在开放网络基金会的最终规范协议（OWFa 1.0）下提供的开放规范，技术社区可以审查 GraphQL 实现必须符合规范的要求，并帮助制定 GraphQL 的未来。虽然该规范对 GraphQL 的语法，什么是有效查询以及模式的工作方式进行了非常具体的说明，但它没有提供有关如何存储数据或 GraphQL 服务器应使用哪种编程语言实现的指导。这在软件领域是非常强大的，也是相对独特的。它允许以各种编程语言创建 GraphQL 服务器，并且由于它们符合规范，因此客户端会确切知道它们的工作方式。GraphQL 服务器已经有多种语言实现，人们不仅可以期望像 JavaScript、Java和 C# 这样的语言，还可以使用 Go、Elixir 和 Haskell 等。服务器实现所使用的语言不会成为采用过程的障碍。它不仅存在多种语言实现，而且它们都是开源的。如果没有你选择的语言的实现，那么可以自己实现。总结GraphQL 是开源 API 领域中一个令人兴奋的、相对较新的参与者。它将查询语言、执行引擎与开源规范结合在一起，它定义了 GraphQL 实现的外观和功能。GraphQL 已经开始改变企业对构建客户端和 API 应用的看法。通过将 GraphQL 作为技术栈的一部分，前端开发人员可以自由地查询所需的数据，而后端开发人员可以将客户端应用需求与后端系统架构分离。通常，公司在使用 GraphQL 的过程中，首先会在其现有的后端服务之上构建一个 GraphQL API “层”。这使得客户端应用开始获得他们所追求的性能和运营效率，同时使后端团队有机会确定他们可能需要在 GraphQL 层后面的“幕…

GraphQL 用例：使用 Golang 和 PostgreSQL 构建一个博客引擎 API
type: item
date: 2017-05-19T19:18:22+08:00
description: 摘要GraphQL 在生产环境中似乎难以使用：虽然对于建模功能来说图接口非常灵活，但是并不适用于关系型存储，不管是在实现还是性能方面。在这篇博客中，我们会设计并实现一个简单的博客引擎 API，它支持以下功能：三种类型的资源（用户、博文以及评论）支持多种功能（创建用户、创建博文、给博文添加评论、关注其它用户的博文和评论，等等。）使用 PostgreSQL 作为后端数据存储（选择它因为它是一个流行的关系型数据库）。使用 Golang（开发 API 的一个流行语言）实现 API。我们会比较简单的 GraphQL 实现和纯 REST 替代方案，在一种普通场景（呈现博客文章页面）下对比它们的实现复杂性和效率。介绍GraphQL 是一种 IDL（ 接口定义语言 （ Interface Definition Language ） ），设计者定义数据类型和并把数据建模为一个 图 （ graph ） 。每个顶点都是一种数据类型的一个实例，边代表了节点之间的关系。这种方式非常灵活，能适应任何业务领域。然而，问题是设计过程更加复杂，而且传统的数据存储不能很好地映射到图模型。阅读附录1了解更多关于这个问题的详细信息。GraphQL 在 2014 年由 Facebook 的工程师团队首次提出。尽管它的优点和功能非常有趣而且引人注目，但它并没有得到大规模应用。开发者需要权衡 REST 的设计简单性、熟悉性、丰富的工具和 GraphQL 不会受限于 CRUD（LCTT 译注：Create、Read、Update、Delete） 以及网络性能（它优化了往返服务器的网络）的灵活性。大部分关于 GraphQL 的教程和指南都跳过了从数据存储获取数据以便解决查询的问题。也就是，如何使用通用目的、流行存储方案（例如关系型数据库）为 GraphQL API 设计一个支持高效数据提取的数据库。这篇博客介绍构建一个博客引擎 GraphQL API 的流程。它的功能相当复杂。为了和基于 REST 的方法进行比较，它的范围被限制为一个熟悉的业务领域。这篇博客的文章结构如下：第一部分我们会设计一个 GraphQL 模式并介绍所使用语言的一些功能。第二部分是 PostgreSQL 数据库的设计。第三部分介绍了使用 Golang 实现第一部分设计的 GraphQL 模式。第四部分我们以从后端获取所需数据的角度来比较呈现博客文章页面的任务。相关阅读很棒的 GraphQL 介绍文档。该项目的完整实现代码在 github.com/topliceanu/graphql-go-example。在 GraphQL 中建模一个博客引擎下述列表1包括了博客引擎 API 的全部模式。它显示了组成图的顶点的数据类型。顶点之间的关系，也就是边，被建模为指定类型的属性。type User { id: ID email: String! post(id: ID!): Post posts: [Post!]! follower(id: ID!): User followers: [User!]! followee(id: ID!): User followees: [User!]! } type Post { id: ID user: User! title: String! body: String! comment(id: ID!): Comment comments: [Comment!]! } type Comment { id: ID user: User! post: Post! title: String body: String! } type Query { user(id: ID!): User } type Mutation { createUser(email: String!): User removeUser(id: ID!): Boolean follow(follower: ID!, followee: ID!): Boolean unfollow(follower: ID!, followee: ID!): Boolean createPost(user: ID!, title: String!, body: String!): Post removePost(id: ID!): Boolean createComment(user: ID!, post: ID!, title: String!, body: String!): Comment removeComment(id: ID!): Boolean } 列表1模式使用 GraphQL DSL 编写，它用于定义自定义数据类型，例如 User、Post 和 Comment。该语言也提供了一系列原始数据类型，例如 Stri…