简单BFF架构设计

又到周五了有了一个小时的闲暇时间简单写点东西,介绍一个简单的BFF的架构**。BFF**:Backends For Frontends,其实现在是个比较常见的前端架构设计的方案,其最大的优势便在于前端可以高度自由的在Node层做一些server端才可以做的东西,比如SSR、登录态校验、对接服务端各微服务应用等。今天介绍一种简单的设计方案。

技术背景

新建的系统需要对接集团的用户系统、权限系统以及多方业务的RPC服务端,业务属性原因Client端更新频率远高于Server端,且本地环境不可用(依赖服务的数据链路不通),只能依赖预发环境,预发环境与本地环境是隔离的(本地环境无法直接调用预发环境的RPC接口)。

架构图

技术设计

Demo代码

首先由于需要主动调用多方RPC服务,便采用Node层作为聚合,对Client端提供http接口;因为Node端与Client端更新频率不同,为了提高部署效率,采用了两端分离的设计,分成了两个Project,Client端发布生成CDN资源,然后由Node端提供Controller层代码生成主文档模板,同时引入Client端CDN资源。类似代码如下:

javascript 复制代码
import { Context } from 'egg';
import { Controller, Get, Provide, Priority, Inject } from '@midwayjs/decorator';

@Provide()
@Priority(-1) // 降低匹配路由优先级,相当于router放在最后
@Controller('/')
export class HomeController {
  @Inject()
  ctx: Context;

  @Get('/*')
  async home() {

    const env =
      this.ctx.cookies?.get('x-env', { signed: false }) || this.ctx.aliEnv;
    this.ctx.logger.info(`env: ${env}`);

    // 远端持久化配置服务获取版本
    const {version} = await this.mockService.getConfig();

    const publicPath = {
      mockLocal: 'https://127.0.0.1:8000/',
      local: 'http://127.0.0.1:8000/',
      dev: `https://dev.g.alicdn.com/xxx/${version}/dist/`,
      pre: `https://dev.g.alicdn.com/xxx/${version}/dist/`,
      prod: `https://g.alicdn.com/xxx/${version}/dist/`,
    };
   return `<!DOCTYPE html>
   <html lang="en">
   <head>
       <meta charset="UTF-8">
       <meta name="viewport" content="width=device-width, initial-scale=1.0">
       <title>Document</title>
       <link rel="stylesheet" href="${publicPath[env]}umi.css" />
       <script>
           window.routerBase = "/";
         </script>
         <script>
           window.publicPath = window.resourceBaseUrl || "${publicPath[env]}";
           try {
             window.__CONFIG__ = {
               user: ${JSON.stringify(this.ctx.user)},
               env: '${this.ctx.aliEnv}',
               clientEnv: '${env}',
             };
           } catch (e) {
             console.error('=== 初始化数据失败(window.__CONFIG__) ===', e);
           }
         </script>
   </head>
   <body>
       <div id="root"></div>
       <script src="${publicPath[env]}umi.js"></script>
   </body>
   </html>
   `
  }
}

Client版本控制

不同环境CDN路径不同,通过环境来区分配置,因为CDN资源不存在回归能力,所以将CDN资源发布时打上版本号路径,同时引入了第三方持久化配置服务,来配置不同环境的CDN版本号来实现Client资源的版本化控制部署。

本地开发代理&线上问题复现

由于本地环境数据链路不通,因此日常开发调试都需要使用预发环境,为了方便开发,支持通过手动种植指定标识的cookie来mock对应环境来实现本地Client资源的引用,同时也可以用于排查线上Client问题。说到这里可能有很多人没注意,这里有一个隐藏技巧,那就是我们的系统往往预发或者生产访问地址协议时https的,而本地资源是http的,很多人第一反应就是 ,https的页面不能访问http的资源,但是其实是localhost和127.0.0.1除外 ,chrome认为localhost或者127.0.0.1是本机,是可以被信赖的

当然也可以通过本地配置类似代理的方式,将本地的http请求代理到预发环境,但是设计代理工具的配置、登录态token域名及跨域问题等,相对会繁琐一些也可以支持。

相关推荐
我即将远走丶或许也能高飞36 分钟前
vuex 和 pinia 的学习使用
开发语言·前端·javascript
钟离墨笺1 小时前
Go语言--2go基础-->基本数据类型
开发语言·前端·后端·golang
爱吃泡芙的小白白1 小时前
Vue 3 核心原理与实战:从响应式到企业级应用
前端·javascript·vue.js
卓怡学长2 小时前
m115乐购游戏商城系统
java·前端·数据库·spring boot·spring·游戏
老陈聊架构2 小时前
『AI辅助Skill』掌握三大AI设计Skill:前端独立完成产品设计全流程
前端·人工智能·claude·skill
Ulyanov3 小时前
从桌面到云端:构建Web三维战场指挥系统
开发语言·前端·python·tkinter·pyvista·gui开发
cypking3 小时前
二、前端Java后端对比指南
java·开发语言·前端
糠帅傅蓝烧牛肉面3 小时前
单实例多MCP聚合服务:两种实现方案深度对比
前端·docker·ai
JosieBook3 小时前
【Vue】12 Vue技术—— Vue 事件修饰符详解:掌握事件处理的高级技巧
前端·javascript·vue.js
艾斯特_4 小时前
Echarts常用配置项及解释
前端·javascript·echarts