速读摘要文章源自JAVA秀-https://www.javaxiu.com/10142.html
Netflix Studio Engineering内部,一种备受关注的方法是将GraphQL微服务(GQLMS)作为后端平台来促进应用程序的快速开发。与"用一张图来管理所有对象"的方法不同,GQLMS只是利用GraphQL来作为构建CRUD应用程序的丰富API规范。更改表中列的类型将会打破关联的视图,但是通过封装在事务中的更改,可以删除视图、更新该列,然后可以在提交事务之前重新创建视图。文章源自JAVA秀-https://www.javaxiu.com/10142.html
原文约 3483 字 | 图片 7 张 | 建议阅读 7 分钟 | 评价反馈文章源自JAVA秀-https://www.javaxiu.com/10142.html
超越 REST
Dane Avilla InfoQ 文章源自JAVA秀-https://www.javaxiu.com/10142.html
文章源自JAVA秀-https://www.javaxiu.com/10142.html
作者 | Dane Avilla文章源自JAVA秀-https://www.javaxiu.com/10142.html
译者 | 刘雅梦文章源自JAVA秀-https://www.javaxiu.com/10142.html
策划 | 田晓旭文章源自JAVA秀-https://www.javaxiu.com/10142.html
娱乐业一直在努力应对 COVID-19 对全球制作的影响冲击。自 2020 年初以来,Netflix 一直在迭代开发系统,以向内部利益相关方和企业领导者提供有关疫情最新信息的最新工具和仪表盘。这些软件解决方案使得管理层可以就给定的实体产品是否以及何时能够安全地开始在全球范围内创建引人注目的内容而做出最明智的决策。在 Netflix Studio Engineering 内部,一种备受关注的方法是将 GraphQL 微服务(GQLMS)作为后端平台来促进应用程序的快速开发。文章源自JAVA秀-https://www.javaxiu.com/10142.html
许多组织都在拥抱 GraphQL,以其作为统一企业范围内数据模型的一种方式,并提供了一个用其相关实体网络来导航大量结构化数据的单一入口点。这种努力值得称赞,但往往需要内部组织之间历经几个季度的协调,然后将所有相关实体开发并集成到一个单一的单体图中。文章源自JAVA秀-https://www.javaxiu.com/10142.html
与“用一张图来管理所有对象”的方法不同,GQLMS 只是利用 GraphQL 来作为构建 CRUD 应用程序的丰富 API 规范。我们使用 GQLMS 进行了快速的概念验证应用,其经验证实了 GraphQL 宣传其好处时所提出两个理论:文章源自JAVA秀-https://www.javaxiu.com/10142.html
GraphiQLIDE 在模式(schema)旁边显示任何可用的 GraphQL 文档,从而极大地改善了 API 使用者的人机工程学(与同类中最好的 Swagger UI 相比)文章源自JAVA秀-https://www.javaxiu.com/10142.html
GraphQL 的强类型系统和多语言客户端支持,意味着 API 提供者无需关心特定于语言的 API 客户端的生成、版本控制和维护(比如,那些使用优秀的 Swagger Codegen 生成的客户端)。GraphQL API 的使用者可以简单地利用自己喜欢的开源 GraphQL 客户端。文章源自JAVA秀-https://www.javaxiu.com/10142.html
GraphiQL:为 《星球大战》API 自动生成的测试 GUI文章源自JAVA秀-https://www.javaxiu.com/10142.html
我们的经验已经为对 GQLMS 作为快速开发平台感兴趣的团队带来了一个具有许多最佳实践的架构。文章源自JAVA秀-https://www.javaxiu.com/10142.html
文章源自JAVA秀-https://www.javaxiu.com/10142.html
1Graphile文章源自JAVA秀-https://www.javaxiu.com/10142.html
在早期的 GraphQL 探索过程中,Netflix 的工程师意识到 Graphile 库可以将 PostgreSQL 数据库对象(表、视图和函数)作为 GraphQL API 来呈现。Graphile 支持 智能注解,支持通过使用特定格式的 PostgreSQL 注解标记数据库的表、视图、列和类型来控制各种特性。文档甚至可以嵌入到数据库注解中,以便在 Graphile 生成的 GraphQL 模式中显示。文章源自JAVA秀-https://www.javaxiu.com/10142.html
我们假设有一个 Docker 容器,其上运行了一个带有 Graphile 库的非常简单的 NodeJS Web 服务器(以及一些用于安全、日志、度量和监控的 Netflix 内部组件),可以为快速开发工作提供“比 REST 更好的 REST”或“REST++”平台。使用 Docker,我们定义了一个轻量级的独立容器,它允许我们将 Graphile 库及其支持的代码打包成一个独立的包,任何团队都可以在 Netflix 上使用它,而无需额外的编码。只需下拉定义 Docker 的基础镜像,并使用适当的数据库连接符运行它即可。这种方法被证明是非常成功的,并且对 Graphile 的使用产生了一些深刻洞察。文章源自JAVA秀-https://www.javaxiu.com/10142.html
具体来说:文章源自JAVA秀-https://www.javaxiu.com/10142.html
使用数据库视图作为“API 层”来保持灵活性,以允许在不变更现有 GraphQL 模式(构建在数据库视图上)的情况下修改表。文章源自JAVA秀-https://www.javaxiu.com/10142.html
使用 PostgreSQL 聚合函数 时,请使用 PostgreSQL 复合类型。文章源自JAVA秀-https://www.javaxiu.com/10142.html
通过允许 GraphQL 客户端“所用权限”(“full access”)自动生成的 GraphQL 查询和 Graphile 生成的突变(在所有表和视图上公开的 CRUD 操作)来提高灵活性;然后在开发过程的后期,删除在应用程序投产之前未被 UI 使用到的模式元素。文章源自JAVA秀-https://www.javaxiu.com/10142.html
2数据库视图作为 API文章源自JAVA秀-https://www.javaxiu.com/10142.html
我们决定将数据表放在一个 PostgreSQL 模式中,然后在另一个模式中定义这些表的视图,同时 Graphile Web 应用程序使用专用的 PostgreSQL 用户角色连接到数据库。这最终能实现几个不同的目标:文章源自JAVA秀-https://www.javaxiu.com/10142.html
可以独立于 GraphQL 模式中公开的视图来更改底层表。文章源自JAVA秀-https://www.javaxiu.com/10142.html
视图可以进行基本的格式化(比如将 TIMESTAMP 字段呈现为 ISO8601 字符串)。文章源自JAVA秀-https://www.javaxiu.com/10142.html
底层表上的所有权限必须显式地授权给 Web 应用程序的 PostgreSQL 用户,以避免意外的写操作。文章源自JAVA秀-https://www.javaxiu.com/10142.html
表和视图可以在同一个事务中进行修改,这样就可以原子地对公开的 GraphQL 模式进行更改。文章源自JAVA秀-https://www.javaxiu.com/10142.html
关于最后一点:更改表中列的类型将会打破关联的视图,但是通过封装在事务中的更改,可以删除视图、更新该列,然后可以在提交事务之前重新创建视图。我们在启用 pgWatch 的情况下运行 Graphile,只要对数据库做任何更新,GraphQL 模式就会立即更新以反映所做的更改。文章源自JAVA秀-https://www.javaxiu.com/10142.html
3PostgreSQL 复合类型文章源自JAVA秀-https://www.javaxiu.com/10142.html
Graphile 在读取 PostgreSQL 数据库模式以及将表和基本视图转换为 GraphQL 模式方面做得非常出色,但我们的经验表明,当视图中存在 PostgreSQL 聚合函数 或 JSON 函数 时,Graphile 在如何描述嵌套类型方面存在局限性。原生 PostgreSQL 函数,比如 json_build_object,将被转换成 GraphQLJSON 类型,该类型只是一个 String,没有任何内部结构。例如,以这个返回 JSON 对象的简单视图为例:文章源自JAVA秀-https://www.javaxiu.com/10142.html
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)
文章源自JAVA秀-https://www.javaxiu.com/10142.html在生成的模式中,数据类型为 JSON:文章源自JAVA秀-https://www.javaxiu.com/10142.html
文章源自JAVA秀-https://www.javaxiu.com/10142.html
json 字段的内部结构(hello world 和 2 这两个子字段)在生成的 GraphQL 模式中是不透明的。文章源自JAVA秀-https://www.javaxiu.com/10142.html
为了进一步描述 json 字段的内部结构(将其在生成的模式中公开),定义一个复合类型,并创建一个返回该类型的视图:文章源自JAVA秀-https://www.javaxiu.com/10142.html
postgres_test_db=# CREATE TYPE postgraphile.custom_type AS ( "hello world" integer, "2" integer);
文章源自JAVA秀-https://www.javaxiu.com/10142.html接下来,创建一个返回该类型的函数:文章源自JAVA秀-https://www.javaxiu.com/10142.html
postgres_test_db=# CREATE FUNCTION postgraphile.custom_type( "hello world" integer, "2" integer)RETURNS postgraphile.custom_typeAS 'select $1, $2'LANGUAGE SQL;
文章源自JAVA秀-https://www.javaxiu.com/10142.html最后,创建一个返回该类型的视图:文章源自JAVA秀-https://www.javaxiu.com/10142.html
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)
文章源自JAVA秀-https://www.javaxiu.com/10142.html乍一看,这似乎没有什么用,但要记住:在查看生成的模式之前,请在视图、自定义类型和自定义类型的字段上定义注解,以利用 Graphile 的智能注解:文章源自JAVA秀-https://www.javaxiu.com/10142.html
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’;
文章源自JAVA秀-https://www.javaxiu.com/10142.html现在,当查看模式时,json 字段不再显示为不透明的类型 JSON,而是显示为 CustomType:文章源自JAVA秀-https://www.javaxiu.com/10142.html
(还要注意,对视图所做的注解(A description for the view)显示在查询字段的文档中)。文章源自JAVA秀-https://www.javaxiu.com/10142.html
单击 CustomType 将显示自定义类型的字段及其注解:文章源自JAVA秀-https://www.javaxiu.com/10142.html
文章源自JAVA秀-https://www.javaxiu.com/10142.html
请注意,在自定义类型中,第二个字段被命名为 field_2,但 Graphile 智能注解将该字段重命名为 field_two,通过 Graphile 将驼峰式大小写转换为 fieldTwo。另外,对这两个字段的描述都被显示在生成的 GraphQL 模式中。文章源自JAVA秀-https://www.javaxiu.com/10142.html
4允许 Graphile 生成的模式具有“所有权限”(在开发期间)文章源自JAVA秀-https://www.javaxiu.com/10142.html
最初,当讨论使用 Graphile 作为“一种模式来管理所有模式”架构中的一个选项时,该提议遭到了强烈的反对。关于安全性(如何将其与我们的 IAM 基础设施集成,以及如何在数据库中实施行级访问控制?)和性能(如何限制查询以避免一次选择所有行来对数据库进行 DDoS 攻击?)的合法性问题引起了人们的关注,提出了使用类似于 SQL 的查询接口以提供对数据库表的打开权限(open access)。然而,在小团队快速开发内部应用程序的 GQLMS 环境中,默认的 Graphile 行为是让所有列都可用来过滤,这允许 UI 团队可以快速迭代大量新特性,而无需后端团队的参与。这与其他开发模型不同,在其他模型中,UI 和后端团队首先就初始 API 契约达成一致,后端团队实现 API,UI 团队使用 API,然后 API 契约随着 UI 需求在开发生命周期中的变化而演变。文章源自JAVA秀-https://www.javaxiu.com/10142.html
最初,整个应用程序的性能很差,因为 UI 通常需要多次查询才能获取所需的数据。然而,一旦应用程序的行为被充实起来,我们就可以快速创建新视图,以满足每个 UI 交互的需求,这样每次交互只需要一个调用即可。因为这些请求是以本机代码运行在数据库上,所以我们可以通过适当地使用索引、去规范化、集群等来执行复杂的查询并获得高性能。文章源自JAVA秀-https://www.javaxiu.com/10142.html
一旦 UI 和后端之间的“公共 API”(“public API”)固化,我们就“加固”了 GraphQL 模式,通过使用智能注解 @omit 标记表和视图来删除所有不必要的查询(由 Graphile 的默认设置创建)。另外,Graphile 的默认行为是为表和视图生成突变,但是智能注解 @omit create,update,delete 将从模式中删除突变。文章源自JAVA秀-https://www.javaxiu.com/10142.html
5结论文章源自JAVA秀-https://www.javaxiu.com/10142.html
对于那些采用模式优先方法进行 GraphQL API 开发中的用户来说,Graphile 的自动 GraphQL 模式生成功能可能会对模式设计者造成难以接受的限制。如果需要细粒度的访问控制,Graphile 可能很难集成到现有的企业 IAM 基础设施中。向 Graphile 生成的模式中添加自定义查询和突变(即公开 UI 所需的 gRPC 服务调用)是我们目前在 Docker 镜像中不支持的。然而,我们最近注意到 Graphile 的 makeExtendSchemaPlugin,它允许将自定义类型、查询和突变合并到 Graphile 生成的模式中。文章源自JAVA秀-https://www.javaxiu.com/10142.html
也就是说,在初始需求有限并且有一个临时的分布式团队(之前没有合作过)的情况下,一个内部应用在 4-6 周内就能成功实现,这引起了整个 Netflix Studio 的极大兴趣。Netflix 的其他团队也正在寻找对应的 GQLMS 方法:文章源自JAVA秀-https://www.javaxiu.com/10142.html
使用标准的 GraphQL 构造函数和实用程序将数据库公开为 API文章源自JAVA秀-https://www.javaxiu.com/10142.html
利用自定义的 PostgreSQL 类型构建 GraphQL 模式文章源自JAVA秀-https://www.javaxiu.com/10142.html
通过从数据库自动生成大型 API 来提高灵活性文章源自JAVA秀-https://www.javaxiu.com/10142.html
并在 Graphile 生成的业务逻辑和数据类型之外,额外公开其他自定义的业务逻辑和数据类型文章源自JAVA秀-https://www.javaxiu.com/10142.html
这是一个替代之前使用 REST 实现内部 CRUD 工具的可行解决方案。拥有托管 Graphile 的标准化 Docker 容器为团队提供了必要的基础设施,通过这些基础设施,他们可以快速迭代新工具的原型以及快速开发应用程序,从而解决全球媒体工作室在这个充满挑战时期内不断变化的需求。文章源自JAVA秀-https://www.javaxiu.com/10142.html
原文链接:文章源自JAVA秀-https://www.javaxiu.com/10142.html
https://netflixtechblog.com/beyond-rest-1b76f7c20ef6文章源自JAVA秀-https://www.javaxiu.com/10142.html
点击文末【阅读原文】移步InfoQ官网,内容更多更精彩!文章源自JAVA秀-https://www.javaxiu.com/10142.html
今日好文推荐文章源自JAVA秀-https://www.javaxiu.com/10142.html
90亿美元Java纠纷案反转:安卓中复制的代码属于合理使用文章源自JAVA秀-https://www.javaxiu.com/10142.html
Java 微服务能像 Go 一样快吗?文章源自JAVA秀-https://www.javaxiu.com/10142.html
用Rust重写Linux内核,这可能吗?文章源自JAVA秀-https://www.javaxiu.com/10142.html
InfoQ 读者交流群上线啦!各位小伙伴可以扫描下方二维码,添加 InfoQ 小助手,回复关键字“进群”申请入群。回复“资料”,获取资料包传送门,注册 InfoQ 网站后,可以任意领取一门极客时间课程,免费滴!大家可以和 InfoQ 读者一起畅所欲言,和编辑们零距离接触,超值的技术礼包等你领取,还有超值活动等你参加,快来加入我们吧!文章源自JAVA秀-https://www.javaxiu.com/10142.html
文章源自JAVA秀-https://www.javaxiu.com/10142.html
文章源自JAVA秀-https://www.javaxiu.com/10142.html
点个在看少个 bug ?文章源自JAVA秀-https://www.javaxiu.com/10142.html
阅读原文文章源自JAVA秀-https://www.javaxiu.com/10142.html

评论