关键词不能为空

当前您在: 主页 > 英语 >

GraphQL在微服务架构中的实践架构

作者:高考题库网
来源:https://www.bjmy2z.cn/gaokao
2021-02-10 10:52
tags:

-

2021年2月10日发(作者:至诚)




GraphQL


在微服务架构中的实践架构




目录





GraphQL


是什么?


..... .................................................. ...........................................


1



GraphQL


在微服务架构中的使用



.

< p>
............................................ .....................


2



GraphQL


在实践过程中遇到的棘手问题



....................................... ............


3



合理的



GraphQL


微服务架构的设计



.


.............................................. ...........


4














来源:


C DA


数据分析





1




一、


GraphQL


是什么?



简单对象访问协议



SOAP



从今天来 看已经是一门非常古老的



Web


服 务


技术了,


虽然很多服务仍然在使用遵循



SOAP


的接口,


但是到今天



REST


风格


的面向资源的



API


接口已经非常深入人心,也非常的成熟;但是这篇文章 要介


绍的主角其实是另一门更加复杂、完备的查询语言



GraphQL





作为



Facebook




2015


年推出的查询语言,


GraphQL


能够对



API


的数据提供一套易于理解的完整描述,


使得客户端能够更 加准确的获得它需要的


数据,目前包括



Facebook



Twitter



GitHub


在内的很多公司都已经在生产


环境使用



GraphQL


提供



API


;其实无论


我们是否决定生产环境中使用



GraphQL


,它确实是一门值得学习 的技术。



二、


GraphQL


在微服务架构中的使用



类型系统



GraphQL


的强大表达能力主要还是来自于它完备的类型系统,与



REST


不同,它将整个



Web


服务中的全部资源看成一个有连接的图,而不是一个个


资源孤岛,在访问任何资源时都可以通过资源之间的连接访问其它的资源。







来源:


CDA


数据分析





2



如上图所示,当我们访问



User


资源时,就可以通过



GraphQL


中的连接


访问当前



User




Repo




Issue


等资源,我们不再需要通过多个



REST



接口分别获取这些资源, 只需要通过如下所示的查询就能一次性拿到全部的结


果:



{


user {


id


email


username


repos(first: 10) {


id


url


name


issues(first: 20) {


id


author


来源:


CDA


数据分析





3



title }


}


}


}


GraphQL


这种方式能够将原有



RESTful


风格时的多次请求聚合成一次请


求,


不仅能够减少多次请求带来的延迟,


还能够降低 服务器压力,


加快前端的渲


染速度。它的类型系统也非常丰富, 除了标量、枚举、列表和对象等类型之外,


还支持接口和联合类型等高级特性。



为了能够更好的表示非空和空字段,


GraphQL


也引入了



Non-Null


等标


识代表非空的类型,例如



String!


表示非空的字符串。



schema {


query: Query


mutation: Mutation


}


来源:


CDA


数据分析





4



Schema


中绝大多数的类型都是普通的对象类型,


但是每一个



Schema



都有两个特殊类型:


query




mutation


,它们是



GraphQL


中所有查询的入


口, 在使用时所有查询接口都是



query

的子字段,所有改变服务器资源的请求


都应该属于



mutation


类型。



集中式



vs


分散式



GraphQL


以图的形式将整个



Web


服务中的资源展示出来,


其实我们可以


理解为它 将整个



Web


服务以




SQL




的方式展示给前端和客户端,服务端


的资源最终都被聚合到一张 完整的图上,这样客户端可以按照其需求自行调用,


类似添加字段的需求其实就不再需要 后端多次修改了。












RESTful


不同,


每一个的



GraphQL


服务其实对外只提供了一个用于调

< p>
用内部接口的端点,所有的请求都访问这个暴露出来的端点。





来源:


C DA


数据分析





5




GraphQL


实际上将多个



HTTP


请求聚合成了一个请求,它只是将多个



RESTful


请求的资源变成了一个从根资源



Post


访问其他资源的



Comment




Author


的图,多个请求变成了一个请求的不同字段,从 原有的分散式请求


变成了集中式的请求,这种方式非常适合单体服务直接对外提供



GraphQL



务,


能够在数据源和展示层建立一个非常清晰的分离,


同时也 能够通过一些强大


的工具,例如



GraphiQL


直接提供可视化的文档;但是在业务复杂性 指数提升


的今天,


微服务架构成为了解决某些问题时必不可少的 解决方案,


所以如何在微


服务架构中使用



GraphQL


提高前后端之间的沟通效率并降低开发成 本成为了


一个值得考虑的问题。



Relay


标准



如果说



RESTful


其实是客户端与服务端在



HTTP


协议通信时定义的固定


标准,那么



Relay


其实也是我们在使用



GraphQL


可以遵循的一套规范。






这种标准的出现能够让不同的工程 师开发出较为相似的通信接口,


在一些场


景下,


例如标识对象和分页这种常见的需求,


引入设计良好的标准能够降低开发


人员之间的沟通成本。



Relay


标准其实为三个与



API


有关的最常见的问题制定了一些规范:



来源:


CDA


数据分析





6



提供能够重新获取对象的机制;



提供对如何对连接进行分页的描述;



标准化



mutation


请求,使它们变得更加可预测;



通过 将上述的三个问题规范化,


能够极大地增加前后端对于接口制定和对接

< br>时的工作效率。



对象标识符



Node




Relay


标准中定义的一个接口,所有遵循



Node


接口的类型都


应该包含一个



id


字段:



interface Node {


id: ID!


}


type Faction : Node {


id: ID!


name: String


ships: ShipConnection


}


来源:


CDA


数据分析





7



type Ship : Node {


id: ID!


name: String


}


Faction




Ship


两个类型都拥有标识符



id


字段,


我们可以通过该标识符< /p>


重新从服务端取回对应的对象,


Node


接口和字段在默认情况下会假定整个服


务中的所有资源的



id


都是不同的,


但是很多时候我们 都会将类型和



id


绑定到


一起,


组合后才能一个类型特定的


< p>
ID



为了保证



id


的不透明性,


返回的



id



往都是



Base64


编码的字符串,


GraphQL


服务器接收到对应



id


时进行解码就


可以得到相关的信息。



连接与分页



在一个常见的数据库中,一对多关系是非常常见的,一个



User


可以同时


拥有多个



Post


以及多个



Comment


,这些资源的数量在理论上不是有穷的,


没有办法在同一个请求全部返回,所以要对这部分资源进行分页。




query {


viewer {


name


email


来源:


CDA


数据分析





8



posts(first: 1) {


edge {


cursor


node {


title }


}


}


}


}


Relay


通过抽象出的


『连接模型』


为一对多的关系提供了分片 和分页的支持,




Relay


看来,当我们获取某一个



User


对应的多个



Post


时,其实是得到了


一个



PostConnection


,也就是一个连接:



{









来源:


CDA


数据分析

< p>




9




}


]


}


}


}


在一个



PostConnection


中会存在多个



PostEdge


对象,其中的



cursor


就是我们用来做分页的字段,


所有的



cursor


其实都是



Base64


编码的字符串,


这能够提醒调用方



cursor


是一个不透明的指针,


拿到当前



cursor


后就可以将


它作为



after


参数传到下一个查询中:



query {


viewer {


name


email


posts(first: 1, after:


edge {


cursor


来源:


CDA


数据分析





10



node {


title }


}


}


}


}


当我们想要知道当前页是否是 最后一页时,其实只需要使用每一个连接中的



PageInfo


对象,其中包含了很多与分页相关的信息, 一个连接对象中一般都有


以下的结构和字段,例如:


Edge< /p>



PageInfo


以及游标和节点等。



PostConnection


├──



PostEdge




├──



cursor




└──



Post


└──



PageInfo


├──



hasNextPage


├──



hasPreviousPage


来源:

CDA


数据分析





11



├──



startCursor


└──



endCursor


Relay


使用了非常多的功能在连接周围构建抽象,


让我们能够更加方便地管


理客户端中的游标,


整个连接相关的规范其实特别复杂,


可以阅读



Relay Cursor


Connections Specification


了解更多与连接和游标有关的设计。



可变请求



每一个



Web

服务都可以看做一个大型的复杂状态机,这个状态机对外提


供两种不同的接口,


一种接口是查询接口,


它能够查询状态机的当前状态,


而另


一种接口是可以改变服务器状态的可变操作,例如



POST



DELETE


等请求。









按照约定,所有的可变请求都应该以动词开头并且它们的输入都以



Input


结尾,与之相对应的,所有的输出都以



Payload


结尾:



input IntroduceShipInput {


factionId: ID!


shipName: String!


来源:


CDA


数据分 析





12



clientMutationId: String!


}


type IntroduceShipPayload {


faction: Faction


ship: Ship


clientMutationId: String!


}


除此之外,可变请求还可以通过传入



clientMutationId


保证请求的幂等


性。



小结



Facebook




Relay


标准其实是一个在



GraphQL


上对于常见领域问题


的约定,


通过这种 约定我们能够减少工程师的沟通成本和项目的维护成本并在多


人协作时保证服务对外提供 接口的统一。



三、


GraphQL< /p>


在实践过程中遇到的棘手问题



N + 1


问题



在传统的后端服务中,


N + 1


查 询的问题就非常明显,由于数据库中一对


多的关系非常常见,再加上目前大多服务都使用



ORM


取代了数据层,所以在


来源:


CDA


数据分析




13



很多时候相关问题都不会暴露出来,


只有真正出现性能问题或者慢查询时才会发


现。



SELECT * FROM users LIMIT 3;


SELECT * FROM posts WHERE user_id = 1;


SELECT * FROM posts WHERE user_id = 2;


SELECT * FROM posts WHERE user_id = 3;


SELECT * FROM users LIMIT 3;


SELECT * FROM posts WHERE user_id IN (1, 2, 3);


GraphQL


作为一种更灵活的



API


服务提供方式,相比于传统的



Web



务更容易出现上述问题,


类似的问题 在出现时也可能更加严重,


所以我们更需要


避免



N + 1


问题的发生。



数据库层面的



N + 1


查询我们可以通过减少



SQL


查询的次数来解决,一


般我们会将多个



=


查询转换成



IN


查询;


但是



GraphQL


中的



N + 1


问题就


有些复杂了,


尤其是当资源需要通过



RPC


请求从其他微服务中获取时,


更不能


通过简单的 改变



SQL


查询来解决。



来源:


CDA


数据分析





14






在处理



N + 1


问题之前,我们要真正了解如何解决这一类问题的 核心逻


辑,


也就是将多次查询变成一次查询,

< br>将多次操作变成一次操作,


这样能够减少


由于多次请求增 加的额外开销



——



网络延迟、


请求解析等;


GraphQL


使用了



DataLoader


从业务层面解决了



N + 1


问题,其核心逻辑就是整个多个请求,


通过批量请求的方式解决问题 。



微服务架构


微服务架构在当下已经成为了遇到业务异常复杂、


团队人数增加以及高并发


等需求或者问题时会使用的常见解决方案,当微服务架构遇到



GraphQL


时就


会出现很多理论 上的碰撞,会出现非常多的使用方法和解决方案。




来源:


CDA


数据分析





15



在这一节中,我们将介绍在微服务架构中使用



GraphQL


会遇到哪些常见


的问 题,对于这些问题有哪些解决方案需要权衡,同时也会分析



GraphQL



设计理念在融入微 服务架构中应该注意什么。



当我们在微服务架构中融入



GraphQL


的标准时,会遇到三个核心问题,

< p>
这些问题其实主要是从单体服务迁移到微服务架构这种分布式系统时引入的一


系列技术难点,


这些技术难点以及选择之间的折衷是在微服务中实践

< br>


GraphQL


的关键。



Schema


设计



GraphQL


独特的



Schema


设计其实为整个服务的架构带来了非常多的变< /p>


数,


如何设计以及暴露对外的接口决定了我们内部应该如何实现用 户的认证与鉴


权以及路由层的设计。



从总体来看,微服务架构暴露的



GraphQL


接口应该只有两种;一种接口


是分散式的,每一个微服务对外暴露不同的端点,分别对外界提供服务。







在这种情况下,


流量的路由是根据用户请求的不同服务进行分发的,


也就是我们


会有以下的一些



GraphQL API


服务:


< /p>


来源:


CDA


数据分析

< br>




16



/posts/api/graphql


/comments/api/graphql


/subscriptions/api/graphql


我 们可以看到当前博客服务总共由内容、


评论以及订阅三个不同的服务来提


供,在这时其实并没有充分利用



GraphQL < /p>


服务的好处,当客户端或前端同时


需要多个服务的资源时,需要分 别请求不同服务上的资源,并不能通过一次



HTTP


请求满足全部的需求。



另一种方式其 实提供了一种集中式的接口,


所有的微服务对外共同暴露一个


端 点,


在这时流量的路由就不是根据请求的



URL


了,


而是根据请求中不同的字


段进行路由。




这种路由的方式并不能够通过传统的



nginx


来做,因为在



nginx


看来整


个请求其实只有一个



URL


以及一些参数,


我们只有解析 请求参数中的查询才能


知道客户端到底访问了哪些资源。



来源:


CDA


数据分析




17



/api/graphql


请求的 解析其实是对一颗树的解析,


这部分解析其实是包含业务逻辑的,



这里我们需要知道的是,这种



Schema


设计下的请求是按照



field


进行路由


的,


GraphQL


其实帮助我们完成了解析查询树的过程,我们只需要对相应字段


实现特 定的



Resolver


处理返回的逻辑就可以了。




然而在多个微服务提供



Schema


时,


我们需要通过一种机制将多个服务的



Schema


整合起来,


这种整合



Schema


的思路最重要的就是需要解决服务之间


的重复资源和冲突字段问题,如果多个服务需要同时提供同一个类型的基础资

源,例如:


User


可以从多种资源间接访问到。



{


post(id: 1) {


user {


id


email }


id


title


content }


作 为微服务的开发者或者提供方来讲,不同的微服务之间的关系是平等的,


我们需要一个更 高级别或者更面向业务的服务对提供整合



Schema


的功能,



保服务之间的字段与资源类型不 会发生冲突。




< br>来源:


CDA


数据分析





18




















前缀



如何 解决冲突资源从目前来看有两种不同的方式,


一种是为多个服务提供的

< br>资源添加命名空间,一般来说就是前缀,在合并



Schema


时,通过添加前缀能


够 避免不同服务出现重复字段造成冲突的可能。




SourceGraph


在实践



GraphQL


时其实就使用了这种增加前缀的方式,



种方式的实现成本比较低,能够快速解决微服务中

< br>


Schema


冲突的问题,读者


可以阅读



GraphQL at massive scale: GraphQL as the glue in a


microservice architecture


一文了解这种做法的实现细节;这种增加前缀解决


冲突的方式优 点就是开发成本非常低,


但是它将多个服务的资源看做孤岛,


没 有


办法将多个不同服务中的资源关系串联起来,这对于中心化设计的


GraphQL


来说其实会造成一定体验上的丢失。



来源:


CDA


数据分析





19



粘合



除了增加前缀这种在工程上开发 成本非常低的方法之外,


GraphQL


官方提


供了一种名为



Schema Stitching


的方案,能够将不同服务的



GraphQL


Schema


粘合 起来并对外暴露统一的接口,这种方式能够将多个服务中的不同


资源粘合起来,能够充分 利用



GraphQL


的优势。




为了打通不同服务之间资源的壁垒、建立合理并且完善的



GraphQL API



我们其实需 要付出一些额外的工作,


也就是在上层完成对公共资源的处理;


当对


整个



Schema


进行合并时,如果遇到公共资源,就会选用特定的



Resolver



行解析,这些解析器的逻辑是在



Schema Stitching


时指定的。



const linkTypeDefs = `


extend type User {


chirps: [Chirp]



}


`;


来源:


CDA

< br>数据分析





20

-


-


-


-


-


-


-


-



本文更新与2021-02-10 10:52,由作者提供,不代表本网站立场,转载请注明出处:https://www.bjmy2z.cn/gaokao/628629.html

GraphQL在微服务架构中的实践架构的相关文章

  • 爱心与尊严的高中作文题库

    1.关于爱心和尊严的作文八百字 我们不必怀疑富翁的捐助,毕竟普施爱心,善莫大焉,它是一 种美;我们也不必指责苛求受捐者的冷漠的拒绝,因为人总是有尊 严的,这也是一种美。

    小学作文
  • 爱心与尊严高中作文题库

    1.关于爱心和尊严的作文八百字 我们不必怀疑富翁的捐助,毕竟普施爱心,善莫大焉,它是一 种美;我们也不必指责苛求受捐者的冷漠的拒绝,因为人总是有尊 严的,这也是一种美。

    小学作文
  • 爱心与尊重的作文题库

    1.作文关爱与尊重议论文 如果说没有爱就没有教育的话,那么离开了尊重同样也谈不上教育。 因为每一位孩子都渴望得到他人的尊重,尤其是教师的尊重。可是在现实生活中,不时会有

    小学作文
  • 爱心责任100字作文题库

    1.有关爱心,坚持,责任的作文题库各三个 一则150字左右 (要事例) “胜不骄,败不馁”这句话我常听外婆说起。 这句名言的意思是说胜利了抄不骄傲,失败了不气馁。我真正体会到它

    小学作文
  • 爱心责任心的作文题库

    1.有关爱心,坚持,责任的作文题库各三个 一则150字左右 (要事例) “胜不骄,败不馁”这句话我常听外婆说起。 这句名言的意思是说胜利了抄不骄傲,失败了不气馁。我真正体会到它

    小学作文
  • 爱心责任作文题库

    1.有关爱心,坚持,责任的作文题库各三个 一则150字左右 (要事例) “胜不骄,败不馁”这句话我常听外婆说起。 这句名言的意思是说胜利了抄不骄傲,失败了不气馁。我真正体会到它

    小学作文