前端websocket获取数据后需要存本地吗_是什么让我放弃了Restful API?了解清楚后我全面拥抱GraphQL!...

4be9c3cf25f5ccc154dfef19ec1864a3.png

背景

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

e391d50af27604af2d2fc3ff312ba899.png

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

7d78c1f1d048c7c785789c6af1b1731b.png

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

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

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

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

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

做加法:

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

做减法:

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

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

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

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

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

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

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

同时做加减法:

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

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

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

524ec8fc143b8fa63381960f66cb6af8.png

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

8bb340bd46dad46eadacdbca474790e8.png

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

所以GraphQL隆重出世了!

GraphQL简介

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

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

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

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

简单的来说,它:

5da1833db3e0f6cbd71b6ef0625fccf7.png

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

71b3fb215d06b54551791ee3854a32f8.png

GraphQL 对比 REST API 有什么好处?

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

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

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

举个经典的例子:前端向后端请求一个book对象的数据及其作者信息。

我用动图来分别演示下REST和GraphQL是怎么样的一个过程。

先看REST API的做法:

602d543cce5297086b9eda8b5ce836e7.gif

再来看GraphQL是怎么做的:

08715af89393835ad758a8702699441e.gif

可以看出其中的区别:

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

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

93002857a185d281ac62025a87b1468e.png

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

GraphQL 思考模式

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

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

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

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

GraphQL的这种思考模式是不是完美解决了之前遇到的问题呢?!

总结它的好处:

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

创建GraphQL服务器的最终目标是:

允许查询通过图和节点的形式去获取数据。

8594af55fde6f110b745c83de63e00b3.png

GraphQL执行逻辑

有人会问:

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

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

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

答案是:NO!不需要!

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

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

4deabf9ee4300ac0732ed37bd7054b2c.png

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

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

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

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

GraphQL应用的基本架构

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

8510e3076acee0753e46817089287f29.png

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

GraphQL特点总结

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

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

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

GraphQL支持的数据操作

GraphQL对数据支持的操作有:

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

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

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

dea85d378aeb019a1cc34e56862b8668.gif

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

ffa997dc8c621a2b879aa18fe8d8cdda.gif

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

对象类型(Object Type)

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

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

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

0b99d8cad26a3182250d6b499b0d0f4c.png

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

类型修饰符(Type Modifier)

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

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

比如:

  • 列表:[Type]

  • 非空:Type!

  • 列表非空:[Type]!

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

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

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

8e72ff6c057e7696825cd703365e9dcb.png

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

d758b2ab639877c4039baaf5d6e6eaba.png

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

2345f4994feb6360fb4be7289558acb2.png

其他类型

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

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

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

8433b7bc0472a29eb2ed35408aa52243.png

那么就可以实现该接口:

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

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

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

ff4f9191c65e0929d6b1c704894eba9c.png

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

a62014e4a132283f7b4da436e2ce87b9.png

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

Graphql 技术接入架构

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

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

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

a304bed7de5ecaeaa27501471f9bc407.png
集成现有服务的GraphQL层
  • 直连数据库和集成服务的混合模式:前两种方式的混合。

a4b8202ccfb521cee897d97fb6e11ae8.png
混合接入方式

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

服务端实现

在服务端, 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

覆盖了众多客户端设计语言,而其他语言的支持也在推进中。

Graphql的一些服务

整理了下目前比较流行的服务框架:

  • Apollo Engine:一个用于监视 GraphQL 后端的性能和使用的服务。
    Graphcool (github): 一个 BaaS(后端即服务),它为你的应用程序提供了一个 GraphQL 后端,且具有用于管理数据库和存储数据的强大的 web ui。

  • Tipe (github): 一个 SaaS(软件即服务)内容管理系统,允许你使用强大的编辑工具创建你 的内容,并通过 GraphQL 或 REST API 从任何地方访问它。

  • AWS AppSync:完全托管的 GraphQL 服务,包含实时订阅、离线编程和同步、企业级安全特性以及细粒度的授权控制。

  • Hasura:一个 BaaS(后端即服务),允许你在 Postgres 上创建数据表、定义权限并使用 GraphQL 接口查询和操作。

Graphql的一些工具:

  • graphiql (npm): 一个交互式的运行于浏览器中的 GraphQL IDE。

  • Graphql Language Service: 一个用于构建 IDE 的 GraphQL 语言服务(诊断、自动完成等) 的接口。

  • quicktype (github): 在 TypeScript、Swift、golang、C#、C++ 等语言中为 GraphQL 查 询生成类型。

想要获取更多关于Graphql的一些框架、工具,可以去awesome-graphql:一个神奇的社区,维护一系列库、资源等,地址是

https://github.com/chentsulin/awesome-graphql。

想要学习更多Graphql的知识,可以去GraphQL.cn。

end

—— 推 荐 阅 读 ——假如,人工智能也去摆地摊作为一个乘风破浪的程序员,我每天除了疯就是浪程序员最卑微的瞬间

【人工智能社群】已经成立,旨在打造真正有价值,能交流,一起学习成长的社群,并且每月送书不断!现备注城市+昵称+研究方向,扫码添加好友后立即进群。

a96cfcf31d70cdd06a96bfb864c8efa8.png

▲长按扫码

你在看吗?b3ffb89c5416e96dcda596b8c2c8d7d9.gif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/507359.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

子集和问题 算法_LeetCode刷题实战90:子集 II

算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !今天和大家…

隐私计算 2.5 Blakley秘密共享方案

1 简介 作者:Blakley;时间:1979年;理念:基于高斯消元法。 2 具体实现 I 秘密分割算法 II 秘密重构算法 3 实例 设秘密S(3,10,5)S (3, 10, 5)S(3,10,5),n5n 5n5, t3t 3t3。 I 秘密分割 &#xff0…

conda如何升级pytorch_Google Cloud TPUs 支持 Pytorch 框架啦!

在2019年PyTorch开发者大会上,Facebook,Google和Salesforce Research联合宣布启动PyTorch-TPU项目。项目的目标是在保持PyTorch的灵活性的同时让社区尽可能容易地利用云TPU提供的高性能计算。团队创建了PyTorch/XLA这个repo,它可以让使PyTorc…

隐私计算 2.6 秘密共享的同态特性

1 秘密共享的同态性 秘密共享的同态性:秘密份额的组合等价于组合的秘密共享份额。 假设A、B两方分别有秘密SAS^ASA和SBS^BSB;他们的值被随机拆分为S1A,…,SnAS_1^A, \dots, S_n^AS1A​,…,SnA​和S1B,…,SnBS_1^B, \dots, S_n^BS1B​,…,SnB​&#xff…

二阶龙格库塔公式推导_带你走进最美数学公式

同学们,我们先来跟老师欣赏一下数学中最优美的式子吧?是什么魔力让以上几个似乎毫不相干的数学中最特殊的数字能如此优美的写在同一个式子呢?是欧拉,是数学。0和1——老师就不用介绍啦,e是自然常数(natural constant)&…

隐私计算 2.9 秘密共享应用于横向联邦学习

1 简介 1.1 横向联邦学习 横向联邦学习也称为按样本划分的联邦学习,主要应用于各个参与方的数据集有相同的特征空间和不同的样本空间的场景,例如两个地区的城市商业银行可能在各自的地区拥有非常不同的客户群体,所以他们的客户交集非常小&a…

python缩进说法_【多选题】关于Python程序中与“缩进”有关的说法中,以下选项中错误的是()。...

问题:【多选题】关于Python程序中与“缩进”有关的说法中,以下选项中错误的是()。更多相关问题 因方某将赵某打伤,方某住所地的市劳动教养委员会对方某作出劳动教养2年的决定,并将方某送交劳动 根据行政诉讼…

智能测井解释

1 智能测井解释的需求分析 1、岩性识别 2、储层划分 3、参数计算 4、流体判别 5、井数据批量处理 岩性识别:分类任务 曲线预测、曲线补齐:回归任务 2 岩性识别 2.1 岩性识别主要方法简介 目前岩性识别的方法主要有重磁、测井、地震、遥感、电 磁、地…

基于移动设备的OCR识别工作进展(1)

1 模型调研 模型1:Tesseract-OCR 模型2:PaddleOCR Android上面有体验版的demo:https://ai.baidu.com/easyedge/app/openSource?frompaddlelitePP-OCR模型:https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.5/README_…

2020.2idea创建web_IntelliJ IDEA 2017.3 完整的配置Tomcat运行web项目教程(多图)

小白一枚,借鉴了好多人的博客,然后自己总结了一些图,尽量的详细。在配置的过程中,有许多疑问。如果读者看到后能给我解答的,请留言。Idea请各位自己安装好,还需要安装Maven和Tomcat,各自配置好环…

OCR基本原理

学习内容为《动手学OCR.pdf》 1 OCR基础 1.1 OCR是什么 OCR(Optical Character Recognition,光学字符识别); 传统意义上的OCR:面向扫描文档类对象; 一般意义上的OCR:场景文字识别&#xff08…

实用供暖通风空调设计手册 第三版_实用供热空调设计手册第三版即将出版随想...

看到西北院组织豪华的暖通空调大师阵容编写的《实用供热空调设计手册》第三版即将出版的信息,暖通空调人都期盼着2020年底见到具有更多新理念、新技术、新方法、新设备、新材料内容的新版《实用供热空调设计手册》。看到《实用供热空调设计手册》第二版,…

android 北斗定位代码_iPhone 11 确认支持北斗导航,真相来了!

点击 哎咆科技 关注我们最近“北斗”火了。因为7月31日,北斗三号全球卫星导航系统正式开通。截止8月7日,微博话题“北斗三号全球卫星导航系统正式开通”已有5.3亿次阅读、8万次讨论。北斗三号全球卫星导航系统的开通,意味着中国自主研发的北斗…

linux shell rman删除归档_我们一起学一学渗透测试——黑客应该掌握的Linux基础

点击上方「蓝字」关注我们各位新老朋友们:大家好,我是菜鸟小白。欢迎大家关注“菜鸟小白的学习分享”公众号,菜鸟小白作为一名软件测试工程师,会定期给大家分享一些测试基础知识、测试环境的搭建和python学习分享,另外…

PAN++学习笔记

1 主要创新点 文本检测和识别两个任务结合起来,作为互补,提高检测和识别精度;处理不规则形状的文本;提供一个高效的端到端框架PAN,对实时的应用场景友好。 2 已有工作的痛点 将文本检测和识别任务分开,不…

postgresql 遍历字符串数组_每日一道编程题(348):1005.K次取反后最大化的数组和...

1005.K次取反后最大化的数组和每日编程中遇到任何疑问、意见、建议请公众号留言或直接撩Q474356284(备注每日编程)给定一个整数数组 A,我们只能用以下方法修改该数组:我们选择某个个索引 i 并将 A[i] 替换为 -A[i],然后总共重复这个过程 K 次…

python读取mysql数据_Selenium(Python) ddt读取MySQL数据驱动

import unittest from time import sleep from ddt import ddt, data from pymysql import connect from selenium import webdriver def getMySQLTestData(): # 查询数据库的方法 db connect(host"localhost", user"root", password"123456", …

签字后被开除_员工虚假报销公司可以开除吗?

大家好,我是法小明。今天继续和大家聊聊劳动法那些事,很多企业都会有报销制度,但制度难免会有漏洞,如果劳动者钻空子的话公司可以解除劳动合同吗?我们一起看看下面这个例子:小案例陈某系某公司员工&#xf…

python创建sqlite3数据库_树莓派使用 Python + SQLite 建立温度数据库

相比 MySQL 而言,SQLite 更为轻便、易于维护和部署。本文使用Python向SQLite数据库中插入树莓派温度数据,SQLite数据库中包含一张只包含三个字段的记录表——参数名称,时间和温度值。本文重点解释Python操作SQlite的具体方法,由于…

论文笔记:推荐系统去偏(Debiased Recommendation)研究综述

1 推荐系统的偏差 出现偏差的原因:用户行为数据是观察所得(Observational)而不是实验所得(Experimental),因此会存在各种偏差,如用户对物品的选择偏差、系统对物品的曝光偏差等;偏差带来的问题:不考虑偏差&#xff0c…