最近参与了一个大型项目,大型项目随着系统业务量的增大,不同的应用和系统共同使用着许多的服务接口API,而随着业务的变化和发展,不同的应用对相同资源的不同使用方法最终会导致需要维护的服务API数量呈现爆炸式的增长。而另一方面,创建一个大而全的通用性接口又非常不利于移动端使用(流量损耗),而且后端数据的无意义聚合也对整个系统带来了很大的资源浪费。

       1、 GrapQL背景 

经查资料显示GraphQL是Facebook 在2012年开发的,2015年开源,2016年下半年Facebook宣布可以在生产环境使用,而其内部早就已经广泛应用了,用于替代 REST API。Facebook的解决方案:用一个“聪明”的节点来进行复杂的查询,将数据按照客户端的要求传回去,后端根据GraphQL机制提供一个具有强大功能的接口,用以满足前端数据的个性化需求,既保证了多样性,又控制了接口数量。

        2、 使用介绍

GraphQL并不是一门程序语言或者框架,它是描述请求数据的一种规范,是协议而非存储,GraphQL本身并不直接提供后端存储的能力,它不绑定任何的数据库或者存储引擎,它可以利用已有的代码和技术来进行数据源管理。

一个GraphQL查询是一个被发往服务端的字符串,该查询在服务端被解释和执行后返回JSON数据给客户端。作为服务端除了了解具体的生态之外还需要了解缓存、上传文件等,如果是系统迁移还需要了解特定的框架,作为系统开发推荐使用Prisma的框架。偏向客户端方向的话,需要进一步了解关于graphql-client的相关知识,推荐使用apollo。

       3、 优缺点

        GraphQL虽然能够代替广泛使用的REST API,但也是各有千秋。

        3.1优点: 

        RESTful服务端决定有哪些数据获取方式,客户端只能挑选使用,如果数据过于冗余也只能默默接收再对数据进行处理;而数据不能满足需求则需要请求更多的接口。 
        GraphQL给客户端自主选择数据内容的能力,客户端完全自主决定获取信息的内容,服务端负责精确的返回目标数据。提供一种更严格、可扩展、可维护的数据查询方式。

        3.2缺点:

重构:使用GraphQL对数据源进行管理,相当于要对整个服务端进行一次换血,考虑的不仅仅是需要针对现有数据源建立一套GraphQL的类型系统,同时需要改造服务端暴露数据的方式,这对业务久远的产品无疑是一场灾难。

查询性能:GraphQL查询的每个字段如果都有自己的resolve方法,可能导致一次查询操作对数据库跑了大量的query。

       4、 Type类型

在GraphQL中,我们通过预先定义一张Schema和声明一些Type来达到预期的效果,

首先我们需要知道:

  • 对于数据模型的抽象是通过Type来描述的
  • 对于接口获取数据的逻辑是通过Schema来描述的

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

注意:标量是GraphQL类型系统的最小颗粒。

       4.1标量类型

GraphQL中的内建的标量包含String、Int、Float、Boolean、Enum。也可以通过Scalar声明一个新的标量:

a、
Prisma中,还有DateTime和ID这两个标量分别代表日期格式和主键。(prisma一个使用GraphQL来抽象数据库操作的库)

b、
Upload标量来代表要上传的文件

4.2高级数据类型

复杂的数据模型:Object、Interface、Union、Enum、Input Object、List、Non-Null(Object、Interface 和 Union 三种类型是不能作为输入对象类型的)。

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

       4.3类型修饰符

当前的类型修饰符有两种,分别是List和Required ,它们的语法分别为[Type]和Type!, 同时这两者可以互相组合,比如[Type]!或者[Type!]或者[Type!]!(请仔细看这里!的位置),它们的含义分别为:

  • 列表本身为必填项,但其内部元素可以为空
  • 列表本身可以为空,但是其内部元素为必填
  • 列表本身和内部元素均为必填

        5、 Schema逻辑

我们其实不妨把它当做REST架构中每个独立资源的URL来理解它,只不过在GraphQL中,我们用Query来描述资源的获取方式。因此,我们可以将Schema理解为多个Query组成的一张表。

       5.1 定义Query类型

GraphQL中使用Query来抽象数据的查询逻辑,当前标准下,有三种查询类型,分别是query(查询)、mutation(更改)和subscription(订阅),这三种查询类型必须是Root Query(根查询)存在的。

注:Query特指GraphQL中的逻辑查询(包含三种类型),query指GraphQL中的查询类型(仅指查询类型)对于传统的CRUD项目使用query(查询)、mutation(更改)就够了,subscription(订阅)是针对real-time应用提出。

       5.2 Resolver解析函数

Schema中声明了若干Query,那么我们只进行了一半的工作,因为我们并没有提供相关Query所返回数据的逻辑。在GraphQL中,我们会有这样一个约定,Query和与之对应的Resolver是同名的,这样在GraphQL才能把它们对应起来。大体的解析流程就是遇到一个Query之后,尝试使用它的Resolver取值,之后再对返回值进行解析,这个过程是递归的,直到所解析Field的类型是Scalar Type(标量类型)为止。

Resolver本身的声明在各个语言中是不一样的,因为它代表数据获取的具体逻辑。它的函数签名(以js为例子)如下:function(parent, args, ctx, info) {}

其中的参数的意义如下:

parent: 当前上一个Resolver的返回值

args: 传入某个Query中的函数(比如上面例子中article(id: Int)中的id)

ctx: 在Resolver解析链中不断传递的中间变量(类似中间件架构中的context)

info: 当前Query的AST对象

注意:Resolver内部实现对于GraphQL完全是黑盒状态。这意味着Resolver如何返回数据、返回什么样的数据、从哪返回数据,完全取决于Resolver本身,基于这一点,在实际中,很多人往往把GraphQL作为一个中间层来使用,数据的获取通过Resolver来封装,内部数据获取的实现可能基于RPC、REST、WS、SQL等多种不同的方式。

好了,GraphOL基础今天我就总结在这里,关于其实战应用且等下回分晓。

GraphQL基础篇的更多相关文章

  1. GraphQL实战篇(一)

    看过基础篇的都知道,GraphQL创建Schema有两种方式,Schema First和Graph Type,前者使用GraphQL Schema Language类似于EF的DB First:后者和 ...

  2. C#多线程之基础篇3

    在上一篇C#多线程之基础篇2中,我们主要讲述了确定线程的状态.线程优先级.前台线程和后台线程以及向线程传递参数的知识,在这一篇中我们将讲述如何使用C#的lock关键字锁定线程.使用Monitor锁定线 ...

  3. 一步步学习javascript基础篇(0):开篇索引

    索引: 一步步学习javascript基础篇(1):基本概念 一步步学习javascript基础篇(2):作用域和作用域链 一步步学习javascript基础篇(3):Object.Function等 ...

  4. 2000条你应知的WPF小姿势 基础篇<15-21>

    在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师,对C#和WPF有着极深的热情.最为出色的是他维护了两个博客:2,000Things You Should Know ...

  5. ABP框架实践基础篇之开发UI层

    返回总目录<一步一步使用ABP框架搭建正式项目系列教程> 说明 其实最开始写的,就是这个ABP框架实践基础篇.在写这篇博客之前,又回头复习了一下ABP框架的理论,如果你还没学习,请查看AB ...

  6. C#多线程之基础篇2

    在上一篇C#多线程之基础篇1中,我们主要讲述了如何创建线程.中止线程.线程等待以及终止线程的相关知识,在本篇中我们继续讲述有关线程的一些知识. 五.确定线程的状态 在这一节中,我们将讲述如何查看一个线 ...

  7. C#多线程之基础篇1

    在多线程这一系列文章中,我们将讲述C#语言中多线程的相关知识,在多线程(基础篇)中我们将学习以下知识点: 创建线程 中止线程 线程等待 终止线程 确定线程的状态 线程优先级 前台线程和后台线程 向线程 ...

  8. iOS系列 基础篇 03 探究应用生命周期

    iOS系列 基础篇 03 探究应用生命周期 目录: 1. 非运行状态 - 应用启动场景 2. 点击Home键 - 应用退出场景 3. 挂起重新运行场景 4. 内存清除 - 应用终止场景 5. 结尾 本 ...

  9. iOS系列 基础篇 04 探究视图生命周期

    iOS系列 基础篇 04 探究视图生命周期 视图是应用的一个重要的组成部份,功能的实现与其息息相关,而视图控制器控制着视图,其重要性在整个应用中不言而喻. 以视图的四种状态为基础,我们来系统了解一下视 ...

随机推荐

  1. 『性能』List 和 HashSet 查找性能比较 (任何数据量的检索 从此只用 HashSet )

    结论: 总数 50000 (5万): List 检索 5W次 耗时 23秒, HashSet 检索 5W次 耗时 0.01秒. 总数 5000   (5千): List 检索 5K次 耗时 0.16秒 ...

  2. Java日志正确使用姿势

    前言 关于日志,在大家的印象中都是比较简单的,只须引入了相关依赖包,剩下的事情就是在项目中“尽情”的打印我们需要的信息了.但是往往越简单的东西越容易让我们忽视,从而导致一些不该有的bug发生,作为一名 ...

  3. 企业级镜像仓库harbor搭建

    企业级镜像仓库harbor搭建 一.    Harbor概述 VMware公司最近开源了企业级Registry项目Harbor,其的目标是帮助用户迅速搭建一个企业级的Docker registry 服 ...

  4. Java多线程与并发之面试常问题

    JAVA多线程与并发 进程与线程的区别 进程是资源分配的最小单位,线程是CPU调度的最小单位 所有与进程相关的资源,都被记录在PCB(进程控制块)中 进程是抢占处理机的调度单位:线程属于某个进程,共享 ...

  5. vue学习记录⑤(组件通信-父与子)

    今天我们看一下组件通信. 经过前面几篇文章,我们已经可以构建出完整的单个组件,并利用路由使其串联起来访问了. 但这明显还是不够的.一个页面不可能就是个单组件,一般是由多个组件合成的.正因为如此,组件之 ...

  6. 小程序后端项目【Springboot框架】部署到阿里云服务器【支持https访问】

    前言: 我的后端项目是Java写的,用的Springboot框架.在部署服务器并配置https访问过程中,因为做了一些令人窒息的操作(事后发现),所以老是不能成功. 不成功具体点说就是:域名地址可以正 ...

  7. c/c++ 网络编程 陈硕老师视频理解之ttcp

    ttcp 是干啥的:测试2台机器间的网络传输性能 wiki 功能如下图: 对应的视频是: 4.回顾基础的Sockets API.mkv 5.TTCP代码概览.mkv 6.使用TTCP进行网络传输性能测 ...

  8. bootstap初识之css

    老师的博客:https://www.cnblogs.com/liwenzhou/p/8214637.html bootstrap中文网:http://www.bootcss.com/ 官网:https ...

  9. C 实现自己构建的数组

    #include<stdio.h>#include<malloc.h>#include<stdlib.h>#include<stdbool.h>stru ...

  10. 【机器学习笔记五】聚类 - k均值聚类

    参考资料: [1]Spark Mlib 机器学习实践 [2]机器学习 [3]深入浅出K-means算法  http://www.csdn.net/article/2012-07-03/2807073- ...