1 问题由来
关于我们 Node 服务产生了什么问题,为什么会出现这些问题,以及为何需要采用 GraphQL 去解决这些问题,是一个值得探究的过程。下面,我将从服务架构入手,简单介绍一下项目背景,而后通过几个案例,让大家更形象的理解我们现在的问题是如何产生的。
1.1 服务架构简介
左边方框内属于我们前端团队的服务,右边属于后端服务。这里只是比较粗糙的架构,省略了一些负载均衡等细节,对于我司国内酒店服务来说,这里的图示就足以解释说明我们的问题。
而我们 Node 组,是处于承接上下游的一个位置,是属于直接服务于前端的后端,也就是所谓的 BFF 层,关于这个架构的形成过程,我后面会展开解释。
就目前而言,我们的主要职责是多端适配,UI 适配,版本控制,下发一些AB实验,日志收集等。
虽然我上面说了许多职能,但是我认为我们最核心的职能,其实就是负责给客户端同学输送数据,那么我们输送数据的过程中会产生什么问题?为什么会产生这些问题,下面让我来举例说明一下。
1.2 案例一:数据定制困难
我们都知道,我们的服务最早都是基于PC端而设计的,而随着时代的发展,移动端的各个终端变得越来越丰富,包括现在的 app、小程序、touch 等。所以如果不是拆分服务,我们注定要面临多端适配的一个演进过程。这其中一个典型例子,就是对于同一接口,不同端的需求可能是不同的。拿我们酒店系统举例:
对于酒店列表页展示:
在 PC 端和 APP 端我可以把一家酒店的很多信息都放到列表中展示,每一家酒店就会包含比较完整的酒店模型的字段,然而在一些情况下,比如小程序的这种场景下,可能我需要每家酒店只展示图片,报价,名称三个字段,客户端这种多变的需求是非常常见的,但是我们的接口都是同一个。
那么,我们 APP 端的代码大概会是这样的形式:
hotelInfo: {
name: "酒店",
price:232,
imgUrl:"img.jpg",
tags:[{
name:"亲子家庭"
}],
score:4.2,
rank:"XX酒店排名第X名"
}
它将会把酒店模型下的所有字段直接返回给客户端。
而对于小程序端,我们就需要增加一个参数,判断请求来源是小程序,再去将模型中不显示的字段单独删除,才能达到这种字段级的控制。伪代码如下图:
if ( source === "XIAOCHENGXU" ) {
hotelInfo.tags = undefined;
hotelInfo.score = undefined;
hotelInfo.rank = undefined;
}
假设现在我的小程序改版了,我新版本可能又想展示四个字段,老版本还是只展示三个,这时候我们就面临了版控问题。
作为服务端,我们有两个选择,不去管是新老版本的差异,冗余的返回四个字段,这样带来的好处就是开发简单,只增不减,没有风险。而另一种选择就是加一段这样的代码:
if ( source === "XIAOCHENGXU" ) {
hotelInfo.tags = undefined;
if( version <