发布在即!企业 AIGC 应用程度测评,3 步定制专属评估报告。抢首批测评权益>>> 了解详情
写点什么

超越 REST

  • 2021-03-31
  • 本文字数:4140 字

    阅读完需:约 14 分钟

超越 REST

娱乐业一直在努力应对 COVID-19 对全球制作的影响冲击。自 2020 年初以来,Netflix 一直在迭代开发系统,以向内部利益相关方和企业领导者提供有关疫情最新信息的最新工具和仪表盘。这些软件解决方案使得管理层可以就给定的实体产品是否以及何时能够安全地开始在全球范围内创建引人注目的内容而做出最明智的决策。在 Netflix Studio Engineering 内部,一种备受关注的方法是将 GraphQL 微服务(GQLMS)作为后端平台来促进应用程序的快速开发。


许多组织都在拥抱 GraphQL,以其作为统一企业范围内数据模型的一种方式,并提供了一个用其相关实体网络来导航大量结构化数据的单一入口点。这种努力值得称赞,但往往需要内部组织之间历经几个季度的协调,然后将所有相关实体开发并集成到一个单一的单体图中。


与“用一张图来管理所有对象”的方法不同,GQLMS 只是利用 GraphQL 来作为构建 CRUD 应用程序的丰富 API 规范。我们使用 GQLMS 进行了快速的概念验证应用,其经验证实了 GraphQL 宣传其好处时所提出两个理论:


  • GraphiQLIDE 在模式(schema)旁边显示任何可用的 GraphQL 文档,从而极大地改善了 API 使用者的人机工程学(与同类中最好的 Swagger UI 相比)

  • GraphQL 的强类型系统和多语言客户端支持,意味着 API 提供者无需关心特定于语言的 API 客户端的生成、版本控制和维护(比如,那些使用优秀的 Swagger Codegen 生成的客户端)。GraphQL API 的使用者可以简单地利用自己喜欢的开源 GraphQL 客户端。



GraphiQL:为 《星球大战》API 自动生成的测试 GUI


我们的经验已经为对 GQLMS 作为快速开发平台感兴趣的团队带来了一个具有许多最佳实践的架构。


Graphile


在早期的 GraphQL 探索过程中,Netflix 的工程师意识到 Graphile 库可以将 PostgreSQL 数据库对象(表、视图和函数)作为 GraphQL API 来呈现。Graphile 支持 智能注解,支持通过使用特定格式的 PostgreSQL 注解标记数据库的表、视图、列和类型来控制各种特性。文档甚至可以嵌入到数据库注解中,以便在 Graphile 生成的 GraphQL 模式中显示。


我们假设有一个 Docker 容器,其上运行了一个带有 Graphile 库的非常简单的 NodeJS Web 服务器(以及一些用于安全、日志、度量和监控的 Netflix 内部组件),可以为快速开发工作提供“比 REST 更好的 REST”或“REST++”平台。使用 Docker,我们定义了一个轻量级的独立容器,它允许我们将 Graphile 库及其支持的代码打包成一个独立的包,任何团队都可以在 Netflix 上使用它,而无需额外的编码。只需下拉定义 Docker 的基础镜像,并使用适当的数据库连接符运行它即可。这种方法被证明是非常成功的,并且对 Graphile 的使用产生了一些深刻洞察。


具体来说:


  • 使用数据库视图作为“API 层”来保持灵活性,以允许在不变更现有 GraphQL 模式(构建在数据库视图上)的情况下修改表。

  • 使用 PostgreSQL 聚合函数 时,请使用 PostgreSQL 复合类型。

  • 通过允许 GraphQL 客户端“所用权限”(“full access”)自动生成的 GraphQL 查询和 Graphile 生成的突变(在所有表和视图上公开的 CRUD 操作)来提高灵活性;然后在开发过程的后期,删除在应用程序投产之前未被 UI 使用到的模式元素。

数据库视图作为 API


我们决定将数据表放在一个 PostgreSQL 模式中,然后在另一个模式中定义这些表的视图,同时 Graphile Web 应用程序使用专用的 PostgreSQL 用户角色连接到数据库。这最终能实现几个不同的目标:


  • 可以独立于 GraphQL 模式中公开的视图来更改底层表。

  • 视图可以进行基本的格式化(比如将 TIMESTAMP 字段呈现为 ISO8601 字符串)。

  • 底层表上的所有权限必须显式地授权给 Web 应用程序的 PostgreSQL 用户,以避免意外的写操作。

  • 表和视图可以在同一个事务中进行修改,这样就可以原子地对公开的 GraphQL 模式进行更改。


关于最后一点:更改表中列的类型将会打破关联的视图,但是通过封装在事务中的更改,可以删除视图、更新该列,然后可以在提交事务之前重新创建视图。我们在启用 pgWatch 的情况下运行 Graphile,只要对数据库做任何更新,GraphQL 模式就会立即更新以反映所做的更改。

PostgreSQL 复合类型


Graphile 在读取 PostgreSQL 数据库模式以及将表和基本视图转换为 GraphQL 模式方面做得非常出色,但我们的经验表明,当视图中存在 PostgreSQL 聚合函数 或 JSON 函数 时,Graphile 在如何描述嵌套类型方面存在局限性。原生 PostgreSQL 函数,比如json_build_object,将被转换成 GraphQLJSON类型,该类型只是一个String,没有任何内部结构。例如,以这个返回JSON对象的简单视图为例:


postgres_test_db=# create view postgraphile.json_object_example as  select json_build_object(‘hello world’::text, 1, ‘2’::text, 3)  as json;postgres_test_db=# select * from postgraphile.json_object_example;          json— — — — — — — — — — — — -{“hello world”: 1, “2”: 3}(1 row)
复制代码


在生成的模式中,数据类型为JSON



json字段的内部结构(hello world2这两个子字段)在生成的 GraphQL 模式中是不透明的。


为了进一步描述json字段的内部结构(将其在生成的模式中公开),定义一个复合类型,并创建一个返回该类型的视图:


postgres_test_db=# CREATE TYPE postgraphile.custom_type AS (  "hello world" integer,  "2" integer);
复制代码


接下来,创建一个返回该类型的函数:


postgres_test_db=# CREATE FUNCTION postgraphile.custom_type(  "hello world" integer,  "2" integer)RETURNS postgraphile.custom_typeAS 'select $1, $2'LANGUAGE SQL;
复制代码


最后,创建一个返回该类型的视图:


postgres_test_db=# create view postgraphile.json_object_example2 as  select postgraphile.custom_type(1, 3)  as json;postgres_test_db=# select * from postgraphile.json_object_example2; json— — — -(1,3)(1 row)
复制代码


乍一看,这似乎没有什么用,但要记住:在查看生成的模式之前,请在视图、自定义类型和自定义类型的字段上定义注解,以利用 Graphile 的智能注解:


postgres_test_db=# comment on  type postgraphile.custom_type  is E’A description for the custom type’;postgres_test_db=# comment on  view postgraphile.json_object_example2  is E’A description for the view’;postgres_test_db=# comment on  column postgraphile.custom_type.”hello world”  is E’A description for hello world’;postgres_test_db=# comment on  column postgraphile.custom_type.field_2  is E’@name field_two\nA description for the second field’;
复制代码


现在,当查看模式时,json字段不再显示为不透明的类型JSON,而是显示为CustomType



(还要注意,对视图所做的注解(A description for the view)显示在查询字段的文档中)。


单击CustomType将显示自定义类型的字段及其注解:



请注意,在自定义类型中,第二个字段被命名为field_2,但 Graphile 智能注解将该字段重命名为field_two,通过 Graphile 将驼峰式大小写转换为fieldTwo。另外,对这两个字段的描述都被显示在生成的 GraphQL 模式中。

允许 Graphile 生成的模式具有“所有权限”(在开发期间)


最初,当讨论使用 Graphile 作为“一种模式来管理所有模式”架构中的一个选项时,该提议遭到了强烈的反对。关于安全性(如何将其与我们的 IAM 基础设施集成,以及如何在数据库中实施行级访问控制?)和性能(如何限制查询以避免一次选择所有行来对数据库进行 DDoS 攻击?)的合法性问题引起了人们的关注,提出了使用类似于 SQL 的查询接口以提供对数据库表的打开权限(open access)。然而,在小团队快速开发内部应用程序的 GQLMS 环境中,默认的 Graphile 行为是让所有列都可用来过滤,这允许 UI 团队可以快速迭代大量新特性,而无需后端团队的参与。这与其他开发模型不同,在其他模型中,UI 和后端团队首先就初始 API 契约达成一致,后端团队实现 API,UI 团队使用 API,然后 API 契约随着 UI 需求在开发生命周期中的变化而演变。


最初,整个应用程序的性能很差,因为 UI 通常需要多次查询才能获取所需的数据。然而,一旦应用程序的行为被充实起来,我们就可以快速创建新视图,以满足每个 UI 交互的需求,这样每次交互只需要一个调用即可。因为这些请求是以本机代码运行在数据库上,所以我们可以通过适当地使用索引、去规范化、集群等来执行复杂的查询并获得高性能。


一旦 UI 和后端之间的“公共 API”(“public API”)固化,我们就“加固”了 GraphQL 模式,通过使用智能注解@omit标记表和视图来删除所有不必要的查询(由 Graphile 的默认设置创建)。另外,Graphile 的默认行为是为表和视图生成突变,但是智能注解@omit create,update,delete将从模式中删除突变。

结论


对于那些采用模式优先方法进行 GraphQL API 开发中的用户来说,Graphile 的自动 GraphQL 模式生成功能可能会对模式设计者造成难以接受的限制。如果需要细粒度的访问控制,Graphile 可能很难集成到现有的企业 IAM 基础设施中。向 Graphile 生成的模式中添加自定义查询和突变(即公开 UI 所需的 gRPC 服务调用)是我们目前在 Docker 镜像中不支持的。然而,我们最近注意到 Graphile 的 makeExtendSchemaPlugin,它允许将自定义类型、查询和突变合并到 Graphile 生成的模式中。


也就是说,在初始需求有限并且有一个临时的分布式团队(之前没有合作过)的情况下,一个内部应用在 4-6 周内就能成功实现,这引起了整个 Netflix Studio 的极大兴趣。Netflix 的其他团队也正在寻找对应的 GQLMS 方法:


  1. 使用标准的 GraphQL 构造函数和实用程序将数据库公开为 API

  2. 利用自定义的 PostgreSQL 类型构建 GraphQL 模式

  3. 通过从数据库自动生成大型 API 来提高灵活性

  4. 并在 Graphile 生成的业务逻辑和数据类型之外,额外公开其他自定义的业务逻辑和数据类型


这是一个替代之前使用 REST 实现内部 CRUD 工具的可行解决方案。拥有托管 Graphile 的标准化 Docker 容器为团队提供了必要的基础设施,通过这些基础设施,他们可以快速迭代新工具的原型以及快速开发应用程序,从而解决全球媒体工作室在这个充满挑战时期内不断变化的需求。


原文链接:


https://netflixtechblog.com/beyond-rest-1b76f7c20ef6

2021-03-31 15:023373

评论

发布
暂无评论
发现更多内容

Python 基础知识:语法、数据类型和控制结构

3D建模设计

Python 数据工程

为什么当下MES如此火热,各大制造业工厂都在推行?

万界星空科技

MES系统

大规模流量下的云边端一体化流量调度体系

火山引擎边缘云

边缘计算 数字孪生 边缘云 火山引擎边缘云

App Tamer for Mac(CPU智能控制管理) v2.8.1激活版

mac

苹果mac Windows软件 App Tamer 优化管理软件

OpenHarmony—应用间HSP开发指导

OpenHarmony开发者

OpenHarmony

Numpy和Pandas简介

3D建模设计

Python 数据科学

“智算聚芯力 津彩新未来”天津市人工智能计算中心200P上线仪式暨天津人工智能应用创新论坛成功举办

彭飞

NFT游戏模式开发,外包技术公司团队搭建

V\TG【ch3nguang】

NFT平台搭建,如何开发一个NFT平台

V\TG【ch3nguang】

安全可靠的文件传输服务助力完成更高效的医疗保健工作(上)

镭速

文件传输服务 医疗保健

未来3-5年,前端开发往哪个方向发展更好就业?

互联网工科生

前端 前端开发 低代码

电气设计软件有哪些?EPLAN让你成为专业工程师

智造软件

EPLAN 电器辅助设计 电气设计

一文秒懂!腾讯云ES HTTPS 集群访问通信最佳实践

腾讯云大数据

ES

前端开发纷繁复杂,是否有更高效的开发方式?

高端章鱼哥

前端开发 低代码 低代码前端

Python数据科学入门

3D建模设计

Python 生成式AI

kill -15 与kill -9的区别

源字节1号

开源 软件开发 前端开发 后端开发 小程序开发

大语言模型测试

赤色闪电

电子行业云MES解决方案

万界星空科技

MES系统

喜讯!广通优云两大产品入选软博会“年度优秀创新软件产品推广目录”

广通优云

议题征集中| KCD 2023 杭州站,共话云原生技术

OpenAnolis小助手

云原生 杭州 龙蜥社区 议题征集 KCD

国产“芯”突破 | 优博讯携手海思推出AI新零售创新方案

Geek_2d6073

夯实金融云基础设施底座,天翼云助力金融行业释放发展新活力

天翼云开发者社区

云计算 安全

关于前端就业前景的一点看法

树上有只程序猿

前端 前端开发

大模型时代的 AI 原生云

Baidu AICLOUD

AI 原生云

使用LlamaIndex构建自己的PandasAI

3D建模设计

人工智能 ChatGPT

Python数据结构5步入门

3D建模设计

Python 数据工程

工业互联网的破局密钥——低代码开发

力软低代码开发平台

昇腾 AI 创新大赛2023河北区域赛成功举办,22支优秀团队脱颖而出

彭飞

HTTPS的安全体现在什么地方?

巨量HTTP

https HTTP

安全可靠的文件传输服务助力完成更高效的医疗保健工作(下)

镭速

文件传输服务 医疗保健

研发管理的挑战、本原与方案

iSoftBook

项目管理 软件工程 研发管理平台 敏捷方法 研发云平台

超越 REST_架构_Dane Avilla_InfoQ精选文章