【数据中台商业化】数据中台微前端实践

news2024/10/6 23:40:46

一,需求背景

1 业务背景

在以往的业务场景中,用户进入五花八门的菜单体系中,往往会产生迷茫情绪,难以理解平台名称及具体作用,导致数据开发与管理学习成本较高,降低工作效率。为此我们整合从数据接入,数据开发,数据管理的全链路流程,期望让用户体验一站式数据开发与管理的便捷性;并提供不同业务场景,方便根据业务场景进行进一步数据开发与管理工作,为数据应用平台打下夯实规范的数据基础,方便用户在数据平台里,对于数据开发和数据应用进行便捷性的切换,因此我们设计目前的门户基座,可以快速浏览各个平台,同时串联数据开发与管理的工作,减少用户的试错成本,提升工作效率。

2 标品需求

基座子-项目交互简图如图1;

1,基座的业务页面比较简单,主要包含:顶部边栏、左侧边栏、公共子菜单、顶级平台菜单;

2,点击左上角图标,显示顶级平台菜单,点击平台,在基座左侧边栏动态显示平台一级菜单;

3,点击基座左侧边栏,在公共子菜单,动态显示一级菜单下边的二级、三级菜单;

4,点击基座左侧边栏或者公共子菜单,需要基座调度,在子项目区域正确加载子项目及子项目页面;

图 1

数据中台新门户基座要接入老数据平台一、老数据平台二等 多平台的前端项目,并且原有前端子项目在门户基座呈现任意子项目、任意子项目页面 任意混搭的需求;新门户要接入的项目关系详情如图2;

图 2

3 数据中台融合;

数据中台融合指的是京东体系内,其他对外独立交付的数据中台,比如京东工业、京东城市等项目;数据中台商业化的子项目不仅在新门户容器内,也可以按需打包进其他数据中台容器;下面简称 数据中台融合;

二,微前端技术调研

原有数据中台接入子应用的方式有多种:iframe 嵌套、@weus 微应用、链接跳转等;

1 iframe 存在问题:

• url 不同步。浏览器刷新 iframe url 状态丢失、后退前进按钮无法使用。

• UI 不同步,DOM 结构不共享。想象一下屏幕右下角 1/4 的 iframe 里来一个带遮罩层的弹框,同时我们要求这个弹框要浏览器居中显示,还要浏览器 resize 时自动居中..

• 全局上下文完全隔离,内存变量不共享。iframe 内外系统的通信、数据同步等需求,主应用的 cookie 要透传到根域名都不同的子应用中实现免登效果。

• 慢。每次子应用进入都是一次浏览器上下文重建、资源重新加载的过程。

2 weus 存在问题:

•weus 是京东内部研发已经不再维护了,如果有新的问题需要自己解决,对微前端有新需求也需要自己去实现;

•weus 没有严格的 css 沙箱、js 沙箱,而在我们的需求中,沙箱机制是刚需,我们要接入的子项目在 window 上挂在哪些变量,无法通过规范做到强有力的制约(因为要接入的项目是已经写完了)

•weus 在微前端功能实现,没有qiankun 丰富健全,比如全局状态管理、虽然 weus 实现了子应用的预加载,但是比较机械,是把所有注册的子应用都缓存,实际可能不需要,qiankun 就比较灵活可以根据需要手动缓存等;

3 链接跳转

链接跳转,指的是点击一个菜单,跳转到另一个页面。这种方式不符合 “一站式 ”大数据平台产品定位;

4 最终结论

通过几种实现方式的对比,最终决定以 qiankun 微前端为基础,结合我们的实际业务场景,通过权限菜单树 和 子项目关联来实现基座对子项目的调度,具体方案请参照 三,基座技术方案详细描述;

三,技术方案详细描述;

1 名词解释

跨子项目跳转

指的是子项目没通过基座自行跳转,基座此时需要根据 url 匹配正确的基座显示;

触发节点

点击菜单,菜单对应的节点即为触发节点,跨子项目跳转(刷新页面)没有触发节点,以跳转后url 对应的页面节点为触发节点;

页面节点

权限菜单树中,挂载了子项目页面的节点

门户节点

狭义指的是,当前页面节点对应的公共子菜单父级节点;广义指的是通过页面节点向父系节点查询,最终确认公共子菜单、基座边栏的显示,并通过页面节点确定菜单高亮等行为;

第一子系节点

指的是在由触发节点查页面节点时,只关注子节点中的第一个,如果当前节点的第一个节点不是页面节点,继续在孙子节点的第一个,直到节点类型为页面节点为止;

调度引擎

指的是在基座中,对权限树数据处理,接收基座业务层调度,通过对权限树遍历、查询操作对业务层输出运算结果的一个抽象分层;

2 整体流程图

如图3 为基座技术方案的整体流程图,下面详细介绍

图 3

3 技术方案-分步描述

第 1 步,配置权限菜单树,关联子项目页面

•如图 3 所示,首先会在权限中心配置权限菜单树,权限菜单树有很多级,比如一级平台,二级平台,二级平台一级菜单,二级菜单等,三级菜单等;

•然后需要在菜单树上,挂在子项目的页面,子项目页面的一些权限按钮等;

•最后权限中心对不同的用户赋予权限菜单树的子集;

第 2 步,基座菜单树数据处理;

•基座从接口拿到权限菜单树关联页面数据后,触发调度引擎初始化、并把基座的业务更新函数传给调度引擎;

•基座获取到菜单树以后,广度优先算法(如图4)遍历整个树结构,并建立节点间父子关联关系。根据节点是否挂载了子项目页面定义前端节点类型 ;最终形成图 5 的数据;

•在树遍历过程中,会统一在基座左侧边栏这一层级的节点,做一个门户节点的标记;

图4

•如图 5 所示,前端调度关系中,把权限菜单树分成 两种节点类型,挂载了子项目页面的节点,定义为页面节点。另一种没挂载子项目页面的节点,定义为分组节点;在基座调度中,不关心权限按钮节点,在数据处理中,页面节点就是整个权限菜单树的叶子节点;

图 5

第 3 步,点击基座边栏或公共子菜单

•点击基座边栏,触发点击菜单流程,点击的节点即为 “触发节点”;

•由触发节点,向第一子系节点查页面节点,查页面节点同时,会同时匹配门户节点;

•没有匹配到门户节点,由触发节点向父系节点匹配门户节点;

第 4 步,刷新页面或跨子项目跳转

•这时没有直接的触发节点,只能通过 url 上的标识和菜单树上的页面节点进行匹配

•匹配到页面节点以后,由页面节点向父系节点查门户节点;

第 5 步,通过门户节点输出 “运算结果”

•这里的运算结果主要包含:基座左侧边栏、公共子菜单菜单树列表、菜单高亮、产品平台名称等一系列基座需要正确显示所需要的数据;

•基座调度引擎,根据触发调度的类型;如果是点击菜单触发会执行 切换页面操作,刷新和跨子项目跳转则不需要触发;

第 6 步,基座业务层执行运算结果;

•基座调度引擎,在接收基座业务层调度指令后,通过对图 5 权限树的遍历、查询操作,最终获取运算结果;

• 调用基座业务层的更新函数,执行运算结果,到此基座调度流程结束;

四,基座-子项目结构通信图

1 基座分为业务层、调度引擎两部分;

•基座业务层主要包含:左侧边栏、顶部边栏、顶级平台菜单等 UI显示;

•基座调度层,以 qiankun 微前端为基础,丰富扩展了权限树数据处理、调度运算、双向通信、子项目分组分步预加载策略等;

2 基座子项目通信和路由调度

•基座在执行主题切换时候,通过 qiankun 的 setGlobalState 通知子项目;子项目在绑定项目空间等特定需求时,通过调度引擎封装的 eventCenter 和基座反向通信;

•跨子项目跳转,子项目会自行触发 pushState,点击基座菜单跳转流程,由调度引擎触发 pushState 触达

• qiankun 的 pushSate 劫持策略,触发 popstate 子项目页面因此触发更新;

图 6

3 路由劫持策略原理

基座调度引擎通过监听 popstate 来获取刷新、跨子项目跳转的指令,从而触发调度流程;以下为原理解析:

•以 Vue 为例,Vue 通过 主动触发 pushState、replaceState 或者监听 popstate 变化触发页面发生变化;

•但是跨子项目跳转,执行 pushState 并没有触发 popState 基座调度引擎又怎么能监听到呢?

•通过阅读 qiankun 中依赖的库 single-spa 的源码,navigation 模块劫持了 pushstate 方法,只要触发 pushstate,就会触发 popstate 事件,关键代码如下所示:

function patchedUpdateState(updateState, methodName) {
  return function () {
    const urlBefore = window.location.href;
    const result = updateState.apply(this, arguments);
    const urlAfter = window.location.href;


    if (!urlRerouteOnly || urlBefore !== urlAfter) {
      if (isStarted()) {
        window.dispatchEvent(
          createPopStateEvent(window.history.state, methodName)
        );
      } else {
        reroute([]);
      }
    }
    return result;
  };
}
window.history.pushState = patchedUpdateState(
   window.history.pushState,
   "pushState"
);

五,基于 qiankun 功能扩展:

1 沙箱隔离

js 沙箱利用 qiankun 沙箱机制;

css 沙箱,qiankun 的 css 沙箱不健全;我们接入的又是老项目,目前的策略是 :

•基座通过特殊命名空间 .susceptor、element-ui 通过 .spr 跟子项目隔离;

•子项目通过特殊命名空间,例如 .datacenter-xxx 跟基座隔离

•子项目对 .el- 不执行隔离,目的是为了统一控制布局、主题,同时做性能优化;

2 通信机制

基座和子项目,属于典型的主从结构,采用单向数据流通信;为了满足特殊场景子项目跟基座通信需求,在 qiankun 的通信基础上,封装了 eventCenter 仅用于 子项目 跟基座通信;

•基座 -> 子项目,通过qiankun 的 onGlobalStateChange 通信

•子项目 -> 基座,通过 subActions 封装的 eventCenter 通信

3 分组、分步、动态预加载机制

目前标品基座已经加载了 30多个前端子项目,这么多前端子项目在首个子项目挂载后执行预加载,有可能会阻塞正常页面访问;

分组指的是,通过产品划定的平台,只有切换到当前平台才会加载到当前平台的子项目;

分步指的是,当前平台子项目过多时,一次预加载少量子项目,分多次预加载;

动态指的是,基座在首个子项目挂载后,会检测网速,只有网速良好时才会执行预加载;

4 跨子项目跳转

跨子项目跳转的背景在于 BDP 一站式开发与管理平台,是一个大产品,数据规划、数据集成 等是其中的模块;模块之间存在一些跳转,对于前端就是跨子项目跳转;

我们目前的跨子项目跳转,由 subActions 封装,抹平了标品基座 和 数据中台融合容器的区别;

基座跳转逻辑如下:

crossAppJump: ({ subApp='', path= '', paramsStr='', target= ''})=> {
      let jumpUrl = `/susceptor/${subApp}${path}`
      if(paramsStr){
        jumpUrl = `${jumpUrl}${paramsStr}`
      }
      if(target === '_blank'){
        window.open(`${location.origin}${jumpUrl}`)
      } else {
        window.history.pushState({ portalPushState: true }, null, jumpUrl);
      }
  },

数据中台融合跳转逻辑如下:

 crossAppJump: ({ subApp='', path= '', paramsStr='', target= ''})=> {
      let jumpUrl = `/${subApp}${path}`
      window.__datafuse_jssdk__.crossAppJumpFnGetter({
        path: jumpUrl,
        paramsStr,
        target
      })();
}

5,接口访问及登录鉴权;

由于微前端的技术形态,子项目在基座中加载实质是基座容器的 一段 html,所有接口均是以基座的 域名进行接口转发;由因为数据中台融合,所以子项目请求后端接口均是以 /api/datacenter/项目名 开头;

通过以下 nginx 示例,我们把基座、子项目 的页面访问、接口访问链路 说明白;

# proxy.conf 示例(已做脱敏处理,均不是项目升级名称)
server {
    listen                80;
    server_name           unify.external.dadacenter;
    charset utf-8;
   location /sub-app{
        alias  /export/web/sub-app-web;
        try_files $uri $uri/ /index.html =404;
   }
   location /api/datacenter/subapp {
        proxy_pass   http://server-sup-app/;
   }
   location /susceptor{
      alias  /export/web/susceptor;     on;
      try_files $uri $uri/ /index.html =404;
   }
   location /api{
        proxy_pass  http://sever-api/;
  }
}


# server.conf 示例(已做脱敏处理,均不是实际项目)
upstream server-sup-app{
    server 111.112.113.114:10001;
}
upstream sever-api{
    server 111.112.113.114:1000;
}

鉴权,前端不需要开发,但是需要知道,后端是通过顶级域名种 cookie 鉴权的;例如:unify.external.bigdata 测试环境是在 .external.bigdatao 域名下,这也是为什么本地开发需要配置 host:127.0.01 loca.external.dadacenter ; 

六,写在最后,不忘初心

本节提供两个图, 对上文介绍的微前端实践,有进一步的能力提升,有感兴趣的同学欢迎一起讨论;

1,整体流程图;

如图 6 所示,配置流程:配置权限菜单树,然后配置子项目-子项目页面两级;最后把权限菜单树 和 子项目-子项目页面关联起来,形成如图 7 的权限树-子项目关联数据模型;

基座两个调度流程,跟上文类似,但是多了子项目维度,基座在加载子项目的时候,就可以把子项目 在权限树的 权限按钮信息全部给到子项目;

图 6

2 权限菜单树模型;

上文介绍的基座调度流程是简化后的版本,项目节点只有 分组节点、页面节点;但是从能力层缺失了 子项目维度;在设计之初,如图 7 所示:项目节点包含了 分组节点、子项目节点、子项目页面节点、页面节点 4种节点类型;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/870817.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

不知道打仗之害,就不知道打仗之利

不知道打仗之害,就不知道打仗之利 【安志强趣讲《孙子兵法》第7讲】 【原文】 夫钝兵挫锐,屈力殚货,则诸侯乘其弊而起,虽有智者,不能善其后矣。 【注释】 屈力殚货:屈力,指力量消耗,…

掌握Python的X篇_32_使用python编辑pdf文件_pdfrw

本篇介绍利用python操作pdf文件,我们平时也会有合并和拆分pdf的需求,此时我们就可以使用本节内容。 文章目录 1. pdfrw的安装2. 切分pdf文件3. pdfrw官网及实现一版四面的实例 1. pdfrw的安装 pip install pdfrw官网地址:https://github.co…

设计模式之责任链模式【Java实现】

责任链(Chain of Resposibility) 模式 概念 责任链(chain of Resposibility) 模式:为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者 通过前一对象记住其下一个对象的引用而连成一条…

Mysql中插入数据,并返回自增主键的值

创建数据库和表使用 insert into 进行插入数据使用 RETURN_GENERATED_KEYS 进行返回插入的这条数据 具体方法如下: Testvoid addGetPk(){try{Statement stmt conn.createStatement();String sql String.format("insert into t_students values(null,%s,%s,%d…

Git:在本地电脑上如何使用git?

git 版本: 2.40.1.windows.1 文章目录 一. 使用git之前你必须要理解的几个概念1.1 理解工作区、版本库、暂存区的概念1.2 提交Git版本库的步骤【分两步执行】 二. Git本地库实战2.1 初始化版本库2.2 新建 & 提交 & 状态2.3 查看日志2.4 回退 & 穿梭 &am…

Linux驱动-基于Buildroot构建系统镜像后实现基于QT项目开发之环境配置

Linux驱动-基于Buildroot构建系统镜像后实现基于QT项目开发之环境配置 需求BuildRootUboot的仓库地址和commit idKernel 的仓库地址和commit id BuildRoot已编译库在Windows上的Create上创建项目编译QT项目 需求 基于Build root编译整个镜像后,如何开发自己的基于Q…

D* 算法完全解析(应该是全网最详细的吧)

花了几天时间学习了下 D* 算法,只能说熟悉了一下流程,远不能说掌握,算法实在是非常巧妙 参考 《制造车间无人搬运系统调度方法研究》 《基于D*Lite算法的移动机器人路径规划研究》 人工智能: 自动寻路算法实现(四、D、D*算法) D* 算法 D*路径…

Pycharm社区版连接WSL2中的Mysql8.*

当前时间2023.08.13,Windows11中默认的WSL版本已经是2了,在WSL2中默认的Ubuntu版本已经是22.04,而Ubuntu22.04中默认的Mysql版本已经是8.*。 Wsl 2 中安装mysql WSL2中安装Mysql的方法参考自微软官方文档【开始使用适用于 Linux 的 Windows …

网络请求中,token和cookie有什么区别

HTTP无状态,每次请求都要携带cookie,以帮助识别用户身份; 服务端也可以向客户端set-cookie,cookie大小限制为4kb; cookie默认有跨域限制,不跨域共享和传递,例如: 现代浏览器开始禁…

使用Python和pyodbc库将文件信息插入Access数据库

将文件信息插入 Access 数据库的博客文章示例: 简介: 在日常编程工作中,我们经常需要处理文件和文件夹。有时,我们需要遍历文件夹中的所有文件,并将文件的路径、类型、文件名以及修改日期和创建日期等信息保存到数据库…

基于MIV的神经网络变量筛选

1.案例背景 一般神经网络中所包含的网络输人数据是研究者根据专业知识和经验预先选择好的,然而在许多实际应用中,由于没有清晰的理论依据,神经网络所包含的自变量即网络输入特征难以预先确定,如果将一些不重要的自变量也引入神经网络,会降低模型的精度,因此选择有意义的自变量特…

Flask 上下文是什么 ?

哈喽大家好,我是咸鱼。今天我们来聊聊什么是 Flask 上下文 咸鱼在刚接触到这个概念的时候脑子里蹦出的第一个词是 CPU 上下文 今天咸鱼希望通过这篇文章,让大家能够对 Flask 上下文设计的初衷以及应用有一个基本的了解 Flask 上下文 我们在使用 Flask 开…

【算法基础19-模拟队列】

模拟队列 算法示意图 算法的伪代码 例题 实现一个队列,队列初始为空,支持四种操作: push x – 向队尾插入一个数 x;pop – 从队头弹出一个数;empty – 判断队列是否为空;query – 查询队头元素。 现在要…

不做Linux就没前途吗?

答案当然是——并不会 我晚上回来的时候跟一个今年的毕业生聊天,他入职了一家公司,但是从事的不是Linux相关的工作。 我这里想说的是,做Linux可以赚钱,Linux现在是全世界最牛逼的开源项目一点都不为过,但是Linux也不是…

环境与能源创新专题:地级市绿色创新、碳排放与环境规制数据

数据简介:推动绿色发展,促进人与自然和谐共生是重大战略举措。绿色发展强调“绿水青山就是金山银山”,人与自然和谐共生重在正确处理生态环境保护与经济发展的关系。在着力于实现绿色发展的过程中,绿色创新是绿色发展的重要驱动因…

时序预测 | Matlab实现基于RF随机森林的电力负荷预测模型

文章目录 效果一览基本介绍模型描述源码设计学习小结参考资料效果一览 基本介绍 时序预测 | Matlab实现基于RF随机森林的电力负荷预测模型 电力负荷预测是指通过对历史电力负荷数据分析,来预测未来某个时间段内的电力负荷需求。这项预测对于电力系统的运行和调度至关重要,可以…

CSS实现左侧固定,右侧自适应(5种方法)

<div class"father"><!-- 左右div不能调换顺序来写 --><div class"left">固定宽度区</div><div class"right">自适应区</div> </div> 一、利用左侧浮动float右侧margin-left /* 利用浮动floatmargin…

【Linux操作系统】深入理解系统调用中的read和write函数

在操作系统中&#xff0c;系统调用是用户程序与操作系统之间进行交互的重要方式。其中&#xff0c;read和write函数是常用的系统调用函数&#xff0c;用于在用户程序和操作系统之间进行数据的读取和写入。本文将深入介绍read和write函数的工作原理、用法以及示例代码&#xff0…

chatGPT小白快速入门-002:一文看懂什么是chatGPT

一、前言 本文是《chatGPT小白快速入门培训课程》的第002篇文章&#xff1a;一文看懂什么是chatGPT&#xff0c;全部内容采用chatGPT和chatGPT开源平替软件生成。完整内容大纲详见&#xff1a;《chatGPT小白快速入门课程大纲》。 本系列文章&#xff0c;参与&#xff1a; AIGC…

对doccano自动标注使用的默认UIE模型进行微调以提高特定领域的实体识别能力,提高标注速度

预处理doccano标注的数据 该章节详细说明如何通过doccano.py脚本对doccano平台导出的标注数据进行转换&#xff0c;一键生成训练/验证/测试集。 在本地部署UIE模型 下载模型压缩包&#xff1a; 本来是要通过一定的方法&#xff08;GitZip&#xff09;才能在整体的大项目仓库…