基于 GraphQL 平台化 BFF 构建及微服务治理

基于 GraphQL 平台化 BFF 构建及微服务治理
文章图片
01什么是BFF
BackendForFrontend , 即服务于前端的后端 。
面对越来越复杂的多端应用的需求 , 后端提供的RESTful接口形式难以应对多变的页面需求 , 这时候需要一层专门的BFF层来弥合这部分差异 。
例如同样一个商品详情页 , 在App端上和PC端上 , 两者的展示样式就有很多的不同 。 以往前后端分离的方式可能有几种做法 。
后端提供完全独立的RESTfulAPI , 然后由前端来进行聚合 。 前端需要负责处理多个数据源的聚合和前后数据依赖关系 , 并且由于经过了多次的外网请求对页面性能、原生App的兼容性上都很不友好 。
由网关层来进行聚合处理 。 这种方式不太容易灵活的定制一些聚合或者页面逻辑的处理 。
后端把数据聚合处理后 , 提供一个API给到前端 。 这样后端的微服务之间会存在横向的调用 , 而这是后端微服务架构里一般需要极力避免的做法 。
基于 GraphQL 平台化 BFF 构建及微服务治理
文章图片
针对这样的场景 , 现在一般会引入BFF这一中间层 , 让前端应用直接和BFF通信 , BFF再和后端API进行通信 , 获取数据并且处理完以后返回给前端 。 这样就能比较好的满足前后端各自的需求 。 其实从本质上来说是前端面向页面场景和后端面向业务领域之间的矛盾 , 由BFF这层来解决 。
基于 GraphQL 平台化 BFF 构建及微服务治理
文章图片
但是BFF也只是为了解耦前端和后端间的依赖而增加的一层 , BFF内部还是存在的非常多的问题 。
02BFF的主要职责和问题
BFF最主要是为了针对前端页面进行定制化的处理 , 虽然可以针对每个页面都开发一个单独的接口 , 但是实际上为了开发效率 , 我们还是会在很多代码上做一些复用 。 而这些页面可能有部分共有的逻辑 , 又会有部分差异 。 对BFF进行深入的分析我们发现 , BFF面临最主要的问题有三个:
第一个问题是按需取数
例如同样一个商品详情页 , 在App端上 , 完整的获取数据可能需要100个字段 , 对应10个接口 。 而在MobileWeb上 , 这个页面可能只需要50个字段 , 对应6个接口 。 但是实际开发的时候 , 工程师为了方便很容易写出来一个大而全的方法 , 包含了这100个字段并且调用10个接口 , 这样后期维护反而会很困难 , 而且拖累的部分页面的性能 。
面对这样的场景 , 如果希望代码能够优雅的复用 , 对工程师的能力的要求会特别高 , 需要设计一套非常精巧的代码框架来实现 。 实际情况却是很容易演变成上面例子中描述的样子 。
而GraphQL正是这样一套精巧的框架 , 可以很方便的按我们需求 , 选择性的对字段和数据进行获取 。 并且对于不需要获取的数据 , GraphQL也不会调用对应的数据接口 , 从而提升访问性能 。
第二个问题是页面差异化兼容
同一个业务针对不同的端 , 前端可能也是不同的团队来负责的 , 使用的技术栈也不相同 , 因此需要的数据结构、字段名称可能都不同 。 比如Web端需要完全平铺的字段结构 , 而App上可以接受结构化对象结构 , 或者前端使用了低代码平台来实现 , 字段结构是跟着UI组件来走的 。
对于字段的映射 , 本质上其实一种JSON结构转换成另外一种JSON结构 , 我们参考了很多Node.js生态里的解决方案 , 发现通过JSON模板渲染的方式来实现JSON结构的转换是比较可行的方案 。
第三个问题是不同版本的差异化兼容
在原生的APP上 , BFF层需要针对不同的版本做不同的处理 。 甚至原生的iOS/Android两端 , 有时候也要做一些不同的兼容逻辑处理 。 例如老版本展示A样式 , 新版本展示B样式 。 或者iOS的原生代码在某个版本有bug , 只能BFF来兼容 。 时间久了以后代码会越来越难以维护 , 代码里充斥着各种if-else的判断逻辑 。