GraphQL这个坑可以入了 (2)新协议的优势 - 所求即所得

分享 未结
1 1 0 4
小编 2019-06-13发布
收藏 点赞
来源: 编程还真是个事儿

GraphQL被开源出来其实只是这一两年的事,但是Facebook使用这个技术已经有四五年的历史了,所以说这是一个相对成熟的技术。另外,自从GraphQL被公开出来之后,这个社区异常活跃。就连Facebook里的GraphQL 的原始设计者们,他们自己都好惊奇,突然间就有了很多Facebook以外的人,开始使用GraphQL。那我们今天就来看看它有什么好。

那我们先来看看GraphQL的查询什么样,先来个直观的认识,下面就是一个GraphQL查询,去拿到id为9527的用户,但与与/user/:id这种Rest查询的区别是,我们限定了返回结果的字段,我们只要name和age两个字段。

{
 user(id: "9527") {
   name
   age
 }
}

这个简单的例子可以看出我们的GraphQL可以方便的支持参数(其实还能支持的更好看,我们后面会讲)。 那我们如果我们的客户端需要更多的数据怎么办,可以方便的扩展。

{
 user(id: "9527") {
   name
   age
   email
   friends{
     name
     age
   }
 }
}

这个查询就体现出GraphQL的威力了,我们多要了两个字段email和friends。email没啥好说的,就是一个单一的值,但friends可是实打实的对象集合。对于这种对象,或者说复杂类型,我们可以继续给它指定需要的字段,这里我们指定了 name和age。

你还可以在friends里再指定friends来拿到朋友的朋友。你可以各种嵌套来达成你的查询目的,数据也不在是单一的资源,而形成了一个图。我就是看中这个特性才跳坑的,这种图形化的查询对现代前端和数据工程师都非常有用。我在不少地方都提到过,GraphQL不止可以给前端调用,它给后端以及数据和算法工程师的代码调用也是很好的。

当然,如此强大的查询也让很多后端程序员为GraphQL的性能担心,可真的有问题吗? 这得结合GraphQL的后端实现来给各位解答,首先GraphQL是很轻功能薄的一层,也就是说它自己额外产生的延迟(Overhead)是很低的。其实绝大多数人担心的是,GraphQL会不会额外产生过多数据库的查询。我觉得这个担心是有道理的,如果你给每一个字段都上一个resolver函数,函数里直接执行数据库查询,那当然会产生非常多的查询。可目前已有的GraphQL后端实现(包括JavaScript, Go,Java和Scala)给你提供了非常灵活的自定义优化方式。比如说你可以结合使用Cache和Context对象来减少数据库查询次数,具体如何做我以后结合具体的框架再来讲。而且大家可以想象一下Facebook访问量和界面复杂程度,据说这东西是让他们更轻松了,为什么我们不行?问题都是可以优化和解决的。关于后端的工作量,本篇最后会谈。

那我们拿到的数据是什么样子的呢,这也是我最喜欢GraphQL的地方之一,调用方可以明确知道返回数据的结构,或者说里面都有什么,这是Rest API做不到的。我们来看上面那个GraphQL的返回。

{
  data:{
   user:{
      name:"beinan”,
      age:18,
      email:"aaa@a.com”,
      friends:[
        {
           name:"friend1”,
           age:17
        },
        …..
      ]
   }
 }
}

这个返回结果完全适合你的请求同构的。那么在前端,你有什么样的view, 需要什么样的数据,你就构建什么样的请求,得到的结果你就可以直接用来生成和填充你的view。再复杂的view你也可以一次查询请求搞定,这对前端的反应速度和开发效率是个巨大的提升。后面章节(估计要很多节以后了)我会写一个react的例子,来看看他们如何配合。

至于会不会增加后端工作量的问题,我看好多人问,我分几点来讨论,

1) 你一般不需要为GraphQL换语言,GraphQL各语言实现的进步非常快,基本都是易学易用,现在至少有十几种主流语言支持GraphQL,基本常用的语言都支持了,这个速度是非常惊人的,一般的技术需要好多年才能覆盖这么多语言。

2) 你不需要为GraphQL换框架,GraphQL和框架无关,各种主流web框架,不管你是Django, Rails还是Express,哪怕是Spring MVC,Play Framework,Finatra都不矛盾。当然,你并不真的需要框架。

3) 如果你的服务是一个单一的大型Rest, 你可以把GraphQL 直接连接到你已有的Rest项目上(好处是你可以重用你已经实现的业务逻辑代码,数据库和Cache访问代码),这都是很容易,加一两个endpoint(后面会讲这一两个是哪两个)就行了。所以你可以让GraphQL和你的Rest并行一段时间。

4) 如果你的服务已经很好的使用了微服务的构架,你也不需要重写你的服务,你可用GraphQL挡在所有后端服务前面来自由拼装你的微服务。

5) 关于优化,如果访问量大,的确需要优化GraphQL对数据库的访问,任何后端服务在大访问量面前都需要优化。不过我个人觉得GraphQL的优化相对容易做,毕竟是一个单一的访问,都共享一个单一的context对象,你可以从全局出发进行优化,你可以做的事情更多。而Rest会产生多次请求(多次请求本身就是一个不小的问题),这些请求很可能分发到不同的服务器,即便在同一个服务器你也很难控制它们到达的先后顺序。其实Rest的优化更难。

下回我们来讲GraphQL如何定义数据,我写的慢,请大家耐心等待。。。

回帖
  • 消灭零回复