BFF 实践(通过网关的服务编排功能) - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
vocalman
V2EX    分享发现

BFF 实践(通过网关的服务编排功能)

  •  
  •   vocalman 2019-11-14 11:50:59 +08:00 2649 次点击
    这是一个创建于 2165 天前的主题,其中的信息可能已经有所发展或是发生改变。

    这次分享一个 BFF 实践(通过网关的服务编排功能),详情如下:

    什么是服编排 /数据聚合?

    服务编排 /数据聚合 指的是可以通过一个请求来依次调用多个微服务,并对每个服务的返回结果做数据处理,最终整合成一个大的结果返回给前端。

    例如一个服务是“查询用户预定的酒店”,前端仅需要传一个订单 ID,后端会返回整个订单的信息,包括用户信息、酒店信息和房间信息等。

    这个服务背后可能对应着以下几个操作:

    • 请求订单详情,返回订单对应的用户 ID、酒店 ID、房间 ID ;
    • 根据各类 ID 查询对应的信息;
    • 将数据做过滤、移动等操作,最后整合起来;
    • 将整合好的数据返回给前端;

    下面的图可以帮你更好理解:

    在这里插入图片描述

    编排的优势

    微服务架构上对功能做了解耦,使用服务编排可以快速从各类服务上获取需要的数据,对业务实现快速响应。总的来说,编排有以下几点优势:

    • 功能解耦,服务能够被复用;
    • 对前端友好,无需多次请求;
    • 业务响应速度快,服务能够被快速生成;
    • 返回数据有改动的话,请求接口无影响;
    • 老系统改动的情况下,不需要改动前端,可以通过网关对数据做兼容。

    使用编排工具:Goku API Gateway

    先简单介绍一下,Goku API Gateway (中文名:悟空 API 网关)是一个基于 Golang 开发的微服务网关,能够实现高性能 HTTP API 转发、服务编排、多租户管理、API 访问权限控制等目的,拥有强大的自定义插件系统可以自行扩展,并且提供友好的图形化配置界面,能够快速帮助企业进行 API 服务治理、提高 API 服务的稳定性和安全性。

    Goku API Gateway 支持一个编排 API 对应多个后端服务,每个后端服务的请求参数可以使用前端传入的参数,也可以在编排里自定义(写静态参数或从返回数据里获得)。每个后端服务的返回数据支持过滤、删除、移动、重命名、拆包和封包等操作;编排 API 能够设定编排失败时的异常返回。

    Goku API Gateway 的社区版本( CE )同时拥有完善的使用指南和二次开发指南,内置的插件系统也能够让企业针对自身业务进行定制开发。

    项目地址:https://github.com/eolinker/goku-api-gateway

    官网地址:https://www.eolinker.com

    如何在 Goku 上做服务编排?

    我们将编排的整个操作放到网关进行,由网关对数据做处理与转换,这样无需对后端服务做改动。一个请求到达网关,网关调用多个后端服务,并且在网关上对各个服务的返回数据做处理(操作有过滤、移动、重命名、封包、拆包,后面会对各操作做详细解释),最后由网关将数据整合好返回给前端。

    在这里插入图片描述

    操作步骤

    1.在网关上,新建 API 的类型选择服务编排:

    在这里插入图片描述

    2.配置 查询预定酒店 API 的请求信息:

    在这里插入图片描述

    3.添加并配置 Step:

    网关将编排过程中对 API 的转发处理过程(转发->获取返回数据->数据处理)称为一个 Step

    添加一个转发服务,该服务为 查询订单详情 API,配置相应的转发地址、传入的参数、对返回数据做何种处理等。

    在这里插入图片描述

    由于篇幅原因,后续的 Step (查询用户详情、查询酒店详情、查询房间详情)就不一一展示了。

    编排的传递参数方式和数据处理

    (一)编排的两种传递参数方式

    网关将编排过程中对 API 的转发处理过程(转发->获取返回数据->数据处理)称为一个 Step

    我们将处理查询订单详情 API 称为 Step1,其中 Step1 的返回数据有:用户 ID、酒店 ID、房间 ID。同理,将查询用户信息这步称为 Step2,将查询酒店信息称为 Step3,将查询房间信息称为 Step4

    传参规则:

    • 使用前端传入的参数可以写成:body.参数名header.参数名
    • 使用 Step1 里的返回数据作为参数可以写成:body1.参数名header1.参数名
    • 以此类推

    1.在转发路径传参

    以下为转发路径的传参写法:

    • 例如 Step1 要接收前端传入的 orderID 参数,还有 Authorization 参数。 Step1 的转发路径可以写成:/getOrderInfo/{{body.orderID}}/{{header.Authorization}}
    • 例如 Step2 接收 Step1 里的返回用户 ID 参数( userID ),同时接收前端传入的 Authorization 参数。 Step2 的转发路径可以写成:/getUserInfo/{{body1.userID}}/{{header.Authorization}}

    2.在 Step 里配置请求参数

    Step2 中需要接收 Step1 里返回的 userID 作为参数,同时需要接收前端传入的 Authorization 参数

    在网关里 Step2 的请求参数配置如下所示,请求参数存在多个的话用换行表示:

    在这里插入图片描述

    (二)返回数据处理

    1.查询订单详情的 API,返回数据称为 json1,内容如下:

    { "status":"000000", "data":{ "id":"201910180009x" ,"user_account":"[email protected]" ,"hotal":"0001" ,"room":"biger1" ,"time_start":"20191019" ,"time_end":"20191020" } } 

    2.查询用户详情的 API,返回数据称为 json2,内容如下:

    { "status":"000000", "data":{ "account":"[email protected]", "full_name":"", "phone":"" } } 

    3.查询酒店详情的返回数据,称为 json3,内容如下:

    { "status":"000000", "data":{ "id":"001", "type":"星级酒店", "name":"", "address":"", "location":{}, } } 

    4.查询房间详情的返回数据,称为 json4,内容如下:

    { "status":"000000", "data":{ "name":"豪华大床房" ,"window":1 ,"floor":"10-12" ,"nosmoke":1 } } 

    5.可以在每一个 Step 里对返回 Json 做处理,网关会将处理过的数据最后整合起来,再返回前端,例如这是通过网关返回的 最终数据

    { "id":"201910180009x" ,"userInfo":{ "account":"[email protected]", "full_name":"", "phone":"" } ,"hotelinfo":{ "type":"星级酒店", "name":"", "address":"", "location":{}, } , "roominfo":{ "name":"豪华大床房" ,"window":1 ,"floor":"10-12" ,"nosmoke":1 } } 

    这里以查询酒店详情 API 的返回数据 json3 为例,讲解网关如何在编排过程中对返回数据做处理。

    查询酒店详情 API 返回的原始数据如下:

    { "status":"000000", "data":{ "id":"001", "type":"星级酒店", "name":"", "address":"", "location":{}, } } 

    从网关返回给前端的数据中截取酒店信息的数据如下:

    "hotelinfo":{ "type":"星级酒店", "name":"", "address":"", "location":{}, } 

    那么从原始数据到处理后的数据需要经过以下操作:

    1.字段黑名单

    字段黑名单的作用是排除某些字段,支持数组形式。

    在网关的 Step3 里配置如下: 在这里插入图片描述

    经过网关处理后,实际的返回数据如下,可以看到 data 对象里的 id 字段已经被过滤掉:

    { "status":"000000", "data":{ "type":"星级酒店", "name":"", "address":"", "location":{}, } } 

    2.字段拆包

    拆包是指将指定对象的内容提取出来作为该步骤( step )的返回结果。其中匹配目标只能为 object,匹配目标为空时,结果为 {},可用于清除数据。

    在网关的 Step 里配置如下: 在这里插入图片描述

    经过网关处理后,实际的返回数据如下,可以看到 data 对象被拆开,最终数据仅保留了 data 对象里面的字段:

    { "type":"星级酒店", "name":"", "address":"", "location":{}, } 

    3.封包

    字段封包会将当前的数据整体打包为最终返回数据中的一个对象,不支持*,不支持数组。

    在网关的 Step 里配置如下:

    在这里插入图片描述

    经过网关处理后,实际的返回数据如下,数据被整体打包为 hotelinfo 对象:

    { "hotelinfo":{ "type":"星级酒店", "name":"", "address":"", "location":{}, } } 

    经过三个步骤,就可以将原始数据变成最终的数据。

    本文仅列举了编排过程中部分数据处理的操作,如需了解更多编排细则,可通过文末给出的教程链接。

    相关链接

    项目地址:https://github.com/eolinker/goku-api-gateway

    官网地址:https://www.eolinker.com

    相关教程: 服务编排

    本文转自 EOLINKER 博客,原文链接为: https://blog.csdn.net/qq_40579834/article/details/102661837

    目前尚无回复
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2628 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 34ms UTC 12:54 PVG 20:54 LAX 05:54 JFK 08:54
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86