点击上方“朱小厮的博客”,选择“设为星标”

后台回复"书",获取近百本电子书入口

封面:重庆洪崖洞

来源:http://suo.im/5W1XNE

REST作为一种现代网络应用非常流行的软件架构风格,自从Roy Fielding博士在2000年他的博士论文中提出来到现在已经有了20年的历史。它的简单易用性,可扩展性,伸缩性受到广大Web开发者的喜爱。

REST 的 API 配合JSON格式的数据交换,使得前后端分离、数据交互变得非常容易,而且也已经成为了目前Web领域最受欢迎的软件架构设计模式。

但随着REST API的流行和发展,它的缺点也暴露了出来:

  • 滥用REST接口,导致大量相似度很高(具有重复性)的API越来越冗余。

  • 对于前端而言:REST API粒度较粗,难以一次性符合前端的数据要求,前端需要分多次请求接口数据。增加了前端人员的工作量。

  • 对于后端而言:前端需要的数据往往在不同的地方具有相似性,但却又不同,比如针对同样的用户信息,有的地方只需要用户简要信息(比如头像、昵称),有些地方需要详细的信息,这就需要开发不同的接口来满足这些需求。当这样的相似但又不同的地方多的时候,就需要开发更多的接口来满足前端的需要。增加了后端开发人员的工作量和重复度。

那我们来分析一下,当前端需求变化,涉及到改动旧需求时,会有以下这些情况:

做加法:

产品需求增加,页面需要增加功能,数据也就相应的要增加显示,那么REST接口也需要做增加,这种无可厚非。

做减法:

产品需求减少,页面需要减少功能,或者减少某些信息显示,那么数据就要做减法。

一种通常懒惰的做法是,前端不与后端沟通,仅在前端对数据选择性显示。

因为后端接口能够满足数据需要,仅仅是在做显示的时候对数据进行了选择性显示,但接口的数据是存在冗余的,这种情况一个是存在数据泄露风险,另外就是数据量过大时造成网络流量过大,页面加载缓慢,用户流量费白白消耗,用户体验就会下降。

另外一种做法就是告知后端,要么开发新的接口,要么,修改旧接口,删掉冗余字段。

但一般来说,开发新接口往往是后端开发人员会选择的方案,因为这个方案对现有系统的影响最低,不会有额外的风险。

修改旧接口删除冗余数据的方案往往开发人员不会选择,这是为什么呢?

这就涉及到了系统的稳定性问题了,旧接口往往不止是一个地方在用,很有可能很多页面、设置不同客户端、不同服务都调用了这个接口获取数据,不做详细的调查,是不可能知道到底旧接口被调用了多少次,一旦改动旧接口,涉及范围可能非常大,往往会引起其他地方出现崩溃。改动旧接口成本太高,所以往往不会被采取。

同时做加减法:

既有加法,又有减法,其实这种就跟新需求没啥区别,前端需要重做页面,后端需要新写接口满足前端需要,但是旧接口还是不能轻举妄动(除非确定只有这一处调用才可以删除)。

往往这个时候,其实用到的数据大多都是来自于同一个DO或者DTO,不过是在REST接口组装数据时,用不同的VO来封装不同字段,或者,使用同样的VO,组装数据时做删减。

看到这些问题是不是觉得令人头大?

所以需求频繁改动是万恶之源,当产品小哥哥改动需求时,程序员小哥哥可能正提着铁锹赶来......

那么有没有一种方案或者框架,可以使得在用到同一个领域模型(DO或者DTO)的数据时,前端对于这个模型的数据字段需求的改动,后端可以根据前端的改动和需要,自动适配,自动组装需要的字段,返回给前端呢?如果能这样做的话,那么后端程序猿小哥可能要开心死了,前端妹子也不用那么苦口婆心地劝说后端小哥哥了。

所以GraphQL隆重出世了!那么问题来了!


Part 1 What is GraphQL

GraphQL简介

  • GraphQL是一种新的API标准,它提供了一种比REST更有效、更强大和更灵活的替代方案。

  • 它是由Facebook开发并开源的,现在由来自世界各地的公司和个人组成的大型社区维护。

  • GraphQL本质上是一种基于api的查询语言,现在大多数应用程序都需要从服务器中获取数据,这些数据存储可能存储在数据库中,API的职责是提供与应用程序需求相匹配的存储数据的接口。

  • 它是数据库无关的,而且可以在使用API的任何环境中有效使用,我们可以理解为GraphQL是基于API之上的一层封装,目的是为了更好,更灵活的适用于业务的需求变化。

简单的来说,它

它的工作模式是这样子的:

GraphQL 对比 REST API 有什么好处?

REST API 的接口灵活性差、接口操作流程繁琐,GraphQL 的声明式数据获取,使得接口数据精确返回,数据查询流程简洁,照顾了客户端的灵活性。

客户端拓展功能时要不断编写新接口(依赖于服务端),GraphQL 中一个服务仅暴露一个 GraphQL 层,消除了服务器对数据格式的硬性规定,客户端按需请求数据,可进行单独维护和改进。

REST API 基于HTTP协议,不能灵活选择网络协议,而传输层无关、数据库技术无关使得 GraphQL 有更加灵活的技术栈选择,能够实现在网络协议层面优化应用。

举个经典的例子:前端向后端请求一个book对象的数据及其作者信息。我用动图来分别演示下REST和GraphQL是怎么样的一个过程。先看REST API的做法:

REST API获取数据

再来看GraphQL是怎么做的:

GraphQL获取数据

可以看出其中的区别:

与REST多个endpoint不同,每一个的 GraphQL 服务其实对外只提供了一个用于调用内部接口的端点,所有的请求都访问这个暴露出来的唯一端点。

Endpoints对比

REST API's Endpoints

GraphQL 实际上将多个 HTTP 请求聚合成了一个请求,将多个 restful 请求的资源变成了一个从根资源 POST 访问其他资源的 Comment 和 Author 的图,多个请求变成了一个请求的不同字段,从原有的分散式请求变成了集中式的请求,因此GraphQL又可以被看成是图数据库的形式。

图数据库模式的数据查询

那我们已经能看到GraphQL的先进性,接下来看看它是怎么做的。

GraphQL 思考模式

使用GraphQL接口设计获取数据需要三步:

GraphQL获取数据三步骤

1、首先要设计数据模型,用来描述数据对象,它的作用可以看做是VO,用于告知GraphQL如何来描述定义的数据,为下一步查询返回做准备;

2、前端使用模式查询语言(Schema)来描述需要请求的数据对象类型和具体需要的字段(称之为声明式数据获取);

3、后端GraphQL通过前端传过来的请求,根据需要,自动组装数据字段,返回给前端。

GraphQL的这种思考模式是不是完美解决了之前遇到的问题呢?先总结它的好处:

在它的设计思想中,GraphQL 以图的形式将整个 Web 服务中的资源展示出来,客户端可以按照其需求自行调用,类似添加字段的需求其实就不再需要后端多次修改了。

创建GraphQL服务器的最终目标是:允许查询通过图和节点的形式去获取数据。

GraphQL执行逻辑

有人会问:

  • 使用了GraphQL就要完全抛弃REST了吗?

  • GraphQL需要直接对接数据库吗?

  • 使用GraphQL需要对现有的后端服务进行大刀阔斧的修改吗?

答案是:NO!不需要!

它完全可以以一种不侵入的方式来部署,将它作为前后端的中间服务,也就是,现在开始逐渐流行的 前端 —— 中端 —— 后端 的三层结构模式来部署!

那就来看一下这样的部署模式图:

GraphQL执行逻辑

也就是说,完全可以搭建一个GraphQL服务器,专门来处理前端请求,并处理后端服务获取的数据,重新进行组装、筛选、过滤,将完美符合前端需要的数据返回。

新的开发需求可以直接就使用GraphQL服务来获取数据了,以前已经上线的功能无需改动,还是使用原有请求调用REST接口的方式,最低程度的降低更换GraphQL带来的技术成本问题!

如果没有那么多成本来支撑改造,那么就不需要改造!

只有当原有需求发生变化,需要对原功能进行修改时,就可以换成GraphQL了。

GraphQL应用的基本架构

下图是一个 GraphQL 应用的基本架构,其中客户端只和 GraphQL 层进行 API 交互,而 GraphQL 层再往后接入各种数据源。这样一来,只要是数据源有的数据, GraphQL 层都可以让客户端按需获取,不必专门再去定接口了。

GraphQL应用基本架构

一个GraphQL服务仅暴露一个 GraphQL Endpoint,可以按照业务来进行区分,部署多个GraphQL服务,分管不同的业务数据,这样就可以避免单服务器压力过大的问题了。

GraphQL特点总结

  • 声明式数据获取(可以对API进行查询): 声明式的数据查询带来了接口的精确返回,服务器会按数据查询的格式返回同样结构的 JSON 数据、真正照顾了客户端的灵活性。

  • 一个微服务仅暴露一个 GraphQL 层:一个微服务只需暴露一个GraphQL endpoint,客户端请求相应数据只通过该端点按需获取,不需要再额外定义其他接口。

  • 传输层无关、数据库技术无关:带来了更灵活的技术栈选择,比如我们可以选择对移动设备友好的协议,将网络传输数据量最小化,实现在网络协议层面优化应用。


Part 2 Schema & Type

GraphQL支持的数据操作

GraphQL对数据支持的操作有:

  • 查询(Query):获取数据的基本查询。

  • 变更(Mutation):支持对数据的增删改等操作。

  • 订阅(Subscription):用于监听数据变动、并靠websocket等协议推送变动的消息给对方。

GraphQL支持的操作

GraphQL的核心概念:图表模式(Schema)

要想要设计GraphQL的数据模型,用来描述你的业务数据,那么就必须要有一套Schema语法来做支撑。

想要描述数据,就必须离不开数据类型的定义。所以GraphQL设计了一套Schema模式(可以理解为语法),其中最重要的就是数据类型的定义和支持。

那么类型(Type)就是模式(Schema)最核心的东西了。

什么是类型?

  • 对于数据模型的抽象是通过类型(Type)来描述的,每一个类型有若干字段(Field)组成,每个字段又分别指向某个类型(Type)。这很像Java、C#中的类(Class)。

  • GraphQL的Type简单可以分为两种,一种叫做Scalar Type(标量类型),另一种叫做Object Type(对象类型)。

那么就分别来介绍下两种类型。

标量类型(Scalar Type)

标量是GraphQL类型系统中最小的颗粒。类似于Java、C#中的基本类型。

其中内建标量主要有:

  • String

  • Int

  • Float

  • Boolean

  • Enum

  • ID

Scalar Type

上面的类型仅仅是GraphQL默认内置的类型,当然,为了保证最大的灵活性,GraphQL还可以很灵活的自行创建标量类型。

对象类型(Object Type)

仅有标量类型是不能满足复杂抽象数据模型的需要,这时候我们可以使用对象类型。

通过对象模型来构建GraphQL中关于一个数据模型的形状,同时还可以声明各个模型之间的内在关联(一对多、一对一或多对多)。

对象类型的定义可以参考下图:

对象模型引入关联关系

是不是很方便呢?我们可以像设计类图一样来设计GraphQL的对象模型。

类型修饰符(Type Modifier)

那么,类型系统仅仅只有类型定义是不够的,我们还需要对类型进行更广泛性的描述。

类型修饰符就是用来修饰类型,以达到额外的数据类型要求控制。

比如:

  • 列表:[Type]

  • 非空:Type!

  • 列表非空:[Type]!

  • 非空列表,列表内容类型非空:[Type!]!

在描述数据模型(模式Schema)时,就可以对字段施加限制条件。

例如定义了一个名为User的对象类型,并对其字段进行定义和施加限制条件:

User字段控制

那么,返回数据时,像下面这种情况就是不允许的:

错误的表示

Graphql会根据Schema Type来自动返回正确的数据:

正确的表示

其他类型

除了上面的,Graphql还有一些其他类型来更好的引入面向对象的设计思想:

接口类型(Interfaces):其他对象类型实现接口必须包含接口所有的字段,并具有相同的类型修饰符,才算实现接口。

比如定义了一个接口类型:

那么就可以实现该接口:

联合类型(Union Types):联合类型和接口十分相似,但是它并不指定类型之间的任何共同字段。几个对象类型共用一个联合类型。

输入类型(Input Types):更新数据时有用,与常规对象只有关键字修饰不一样,常规对象时 type 修饰,输入类型是 input 修饰。

比如定义了一个输入类型:

前端发送变更请求时就可以使用(通过参数来指定输入的类型):

所以,这样面向对象的设计方式,真的对后端开发人员特别友好!而且前端MVVM框架流行以来,面向对象的设计思想也越来越流行,前端使用Graphql也会得心应手。


Part 3 GraphQL技术接入架构

Graphql 技术接入架构

那么,该怎么设计来接入我们现有的系统中呢?

将Graphql服务直连数据库的方式:最简洁的配置,直接操作数据库能减少中间环节的性能消耗。

直连数据库的接入

集成现有服务的GraphQL层:这种配置适合于旧服务的改造,尤其是在涉及第三方服务时、依然可以通过原有接口进行交互。

集成现有服务的GraphQL层

直连数据库和集成服务的混合模式:前两种方式的混合。

混合接入方式

可以说是非常灵活了!你都不用担心会给你带来任何的麻烦。


服务端实现

在服务端, GraphQL 服务器可用任何可构建 Web 服务器的语言实现。有以下语言的实现供参考:

C# / .NET、Clojure、Elixir、Erlang、Go、Groovy、Java、JavaScript、Julia、Kotlin、Perl、PHP、Python、R、Ruby、Rust、Scala、Swift... 种类繁多,几乎流行的语言都有支持。

客户端实现

在客户端,Graphql Client目前有下面的语言支持:C# / .NET、Clojurescript、Elm、Flutter、Go、Java / Android、JavaScript、Julia、Swift / Objective-C、iOS、Python、R。覆盖了众多客户端设计语言,而其他语言的支持也在推进中。

想知道更多?描下面的二维码关注我

后台回复"书",获取近百本电子书入口

【精彩推荐】

  • 超清晰的DNS入门指南

  • 深入理解Java Stream流水线

  • 干掉Swagger,试试这个

  • 干掉GuavaCache:Caffeine才是本地缓存的王

  • 如何用ELK搭建TB级的日志系统

  • 深度好文:Linux系统内存知识

  • 日志系统新贵Loki,确实比笨重的ELK轻

  • 日志采集系统都用到哪些技术?

  • 面试官:为什么HashMap的加载因子是0.75?

点个赞+在看,少个 bug ????


http://www.taodudu.cc/news/show-775171.html

相关文章:

  • Linux 思维导图整理(建议收藏)
  • 详解MySQL基准测试和sysbench工具
  • 突发!Redis之父退出:不在维护Redis项目
  • 5分钟理解一致性哈希算法
  • SQL 查询总是先执行SELECT语句吗?
  • SpringSecurity + JWT,从入门到精通!
  • 阿里开源的Arthas竟然还不会用?最佳实践来了!
  • 详解实时查看网卡流量的几款工具
  • 看了这个高并发系统架构,才知道我对秒杀的误解有多深
  • 谈谈前后端分离实践中如何提升RESTful API开发效率
  • Redis的内存淘汰策略问题
  • 最棒 Spring Boot 干货总结
  • 被 Kafka 虐的日子,太惨了……
  • 面试官问:讲讲IP地址的分配原理?
  • Spring循环依赖的三种方式,你都清楚吗?
  • 两张动图,彻底明白TCP的三次握手与四次挥手
  • 今天才知道,MySQL 的 binlog 编号可以这么大!
  • 我用 Redis 干掉了一摞简历
  • 后端不哭!最新优化性能经验分享来啦
  • 卧槽,又一款Markdown组合神器!!!
  • 全世界最顶级的开发者都在使用什么数据库
  • 搞懂这些SQL优化技巧,面试横着走
  • 深度好文:Netflix奈飞微服务架构设计解析
  • Docker 部署不香吗?
  • 一文讲懂什么是三层交换机、网关、DNS、子网掩码、MAC地址
  • Java 8 Lambda 表达式被编译成了什么?
  • Kylin、Druid、ClickHouse核心技术对比
  • 查询速度提升200倍,ClickHouse到底有多快?
  • 老司机给我们解读 Spring Boot 最流行的 16 条实践
  • 菜鸟网络技术专家:技术架构的战略和战术原则

干掉RESTful:GraphQL真香!相关推荐

  1. 干掉 RESTful!GraphQL 真香!

    -     前言    - REST作为一种现代网络应用非常流行的软件架构风格,自从Roy Fielding博士在2000年他的博士论文中提出来到现在已经有了20年的历史.它的简单易用性,可扩展性,伸 ...

  2. 【CuteJavaScript】GraphQL真香入门教程

    看完复联四,我整理了这份 GraphQL 入门教程,哈哈真香... 欢迎关注我的 个人主页 && 个人博客 && 个人知识库 && 微信公众号" ...

  3. 扫地机器人测评云鲸_“可以自己洗拖布”的云鲸扫地机器人,测评体验它是否“真香”?...

    "可以自己洗拖布"的云鲸扫地机器人,测评体验它是否"真香"? 2021-01-06 15:23:21 0点赞 0收藏 0评论 近年来,智能家居产品受到年轻人的强 ...

  4. 别在再满屏的 if、else 了,试试策略模式,真香!!

    你还在写满屏的 if/ else/ switch 之类的判断逻辑吗? 栈长在开发人员的代码中看过太多这样的低级代码了,真的太 low,极不好维护,本文栈长就教你如何用策略模式干掉 if/ else/ ...

  5. 封禁华为的美国,现在不得不在5G标准制定上“恢复合作”,网友:5G真香

    十三 发自 凹非寺 量子位 报道 | 公众号 QbitAI 华为被列"实体清单"还未满一年,外媒今日却曝出消息: 美国商务部拟允许美国公司与华为合作. 这波操作的目的是什么? 根据 ...

  6. 爬一爬 iPhone 11为何嘴上说真丑,销量却真香?

    9月11号早晨,在Steve Jobs剧院举行的2019苹果秋季新品发布会之后,蹲守在发布会前的果粉们开始了自乔布斯去世之后一年一度的对苹果的群嘲.从5S的土豪金,到6的大屏幕.粗线条,iPhone7 ...

  7. 百度“已死”,百度“真香”

    骂百度已然成为互联网的政治正确了. 10w+阅读量刷屏的一篇<搜索引擎百度已死>,和后续到达的作战大队<百度搜索引擎死了吗?><谁杀死了百度搜索?><百度双手 ...

  8. Ipad写代码真香,包邮送一个!

    牛年牛气祝福又来了~ 你的幸运值刷新了吗? 小礼物 iPad 一台 追剧学习两不误,真香! 赠送规则 本次联合抽奖活动,由几位大佬共同赞助.大家使用下面的二维码抽奖,中奖后,联系小编兑换.详细规则如下 ...

  9. c纳秒级计时器_C++11 计时器!真香

    C++11 计时器!真香 一.前言 在我们写程序过程中,有时候需要测试我们的程序语句执行时间的耗时,当前也是有很多的库提供我们去使用,一直没有良好的跨平台的库可以提供出来:而且一般这种代码也是由我们程 ...

最新文章

  1. 9.68最长公共子序列
  2. 也谈.Net中间语言——破解Delphi2CS行数和时间限制
  3. 【PAT乙级】1040 有几个PAT (25 分)
  4. linux 卸载自带java_卸载linux系统自带JDK,安装自己的jdk
  5. 常用的loss函数,以及在训练中的使用
  6. ASP.NET MVC Model绑定(五)
  7. 计算机丨浏览器访问出现DNS_PROBE_POSSIBLE解决方法
  8. 现在当兵有什么待遇复原以后_当兵多少年最好呢?这些关键点会影响在部队发展,很重要、很实用...
  9. 计算机固态硬盘安装,电脑安装了固态硬盘,需要如何重装系统?详细的方法教程在这里!...
  10. mysql数据库编程第六章试题_2016计算机二级MySQL数据库试题及答案
  11. 韩昊 20190919-6 四则运算试题生成,结对
  12. 深度迁移度量网络 Deep Transfer Metric Learning
  13. 使用dubbo遇到了Unsatisfied dependency expressed through field ‘userService‘
  14. python给女朋友_Python 给女朋友道歉的一天
  15. 【C语言】剖析函数递归(2)
  16. 小兔子在终端给大家拜年啦
  17. JavaScript中Set的使用
  18. 【云宏大讲坛】关键应用在超融合环境下的实践
  19. (附源码)计算机毕业设计ssm党史知识竞赛系统
  20. 宣传折页设计三折页宣传册(案例分享)(版权归redtrans所有,请勿私用)

热门文章

  1. app inventer与java不同,App Inventor内置块
  2. 【SpringBoot零基础案例04】【IEDA 2021.1】SpringBoot核心配置文件appilcation.yml或application.yaml
  3. v-on 事件监听器
  4. JavaScript中的setMonth()方法的小问题 解决:setMonth(month, 1)
  5. 深入理解javascript 中的 delete(转)
  6. 让JavaScript回归函数式编程的本质
  7. HDU 4332 Constructing Chimney [状态压缩+矩阵]
  8. 很多用户反映w7开机时候不是非常的理想 其实和它的内存量没有太大关系
  9. 关于C#的Main(String[] args)参数输入问题
  10. ASP.NET MVC 实现多文件上传