微服务框架乾坤沙箱机制实现的原理

一、什么是沙箱

Qiankun微服务框架的沙箱机制是其核心功能之一,主要用于隔离不同子应用之间的运行环境,防止全局污染,保证各个子应用能够独立、安全地运行,沙箱的实现主要有两类:proxy沙箱及快照沙箱

二、proxy沙箱

原理概述

       Proxy对象的使用:Qiankun使用JavaScript的Proxy对象来创建一个全局对象的代理。通过这个代理,可以拦截并控制子应用对全局对象的访问和修改。

       拦截与重定向:当子应用尝试读取或修改全局对象(如window对象)的属性时,Proxy会拦截这些操作,并根据需要进行重定向。读取操作时,如果属性存在于代理对象中,则直接返回该值;否则,从全局对象中读取并返回。修改操作时,将修改应用到代理对象上,而不是全局对象上。

具体实现

  1. 创建一个包含所有全局变量和函数的“fakeWindow”对象。
  2. 使用Proxy对象将“fakeWindow”对象包装成一个代理,该代理将拦截对全局对象的所有访问。
  3. 在子应用执行时,将代理对象作为全局对象传入,这样子应用对全局对象的访问和修改都将被拦截和重定向到“fakeWindow”对象上。
// 代理沙箱
class LegacySandbox {
    // 持续记录新增和修改的全局变量
    currentUpdatePropsValueMap = new Map()
    // 沙箱期间更新的全局变量
    modifiedPropsOriginalValueMapInSandbox = new Map()
    // 沙箱期间新增的全局变量
    addedPropsMapInSandbox = new Map()
    propsWindow = {}
​
    // 核心逻辑
    constructor() {
        const fakeWindow = Object.create(null)
        // 设置值或者获取值
        this.propsWindow = new Proxy(fakeWindow, {
            set: (target, prop, value, receiver) => {
                const originValue = window[prop]
                if (!window.hasOwnProperty(prop)) {
                    this.addedPropsMapInSandbox.set(prop, value)
                } else if(!this.modifiedPropsOriginalValueMapInSandbox.has(prop)){
                    this.modifiedPropsOriginalValueMapInSandbox.set(prop, originValue)
                }
                this.currentUpdatePropsValueMap.set(prop,value)
                window[prop]= value
            },
            get: (target, prop, receiver) => {
                return window[prop]
            }
        })
​
    }
    setWindowProp(prop, value, isToDelete) {
        if (value === undefined && isToDelete) {
            delete window[prop]
        } else {
            window[prop] = value
        }
​
    }
​
    active() {
        // 恢复上一次该微应用处于运行状态时,对window 上做的所有应用的修改
        this.currentUpdatePropsValueMap.forEach((value, prop) => {
            this.setWindowProp(prop, value)
        })
    }
    // 失活 
    inactive() {
        // 还原window上的属性
        this.modifiedPropsOriginalValueMapInSandbox.forEach((value, prop) => {
            this.setWindowProp(prop, value)
        })
        // 删除在微应用运行期间 window 新增的属性
        this.addedPropsMapInSandbox.forEach((_, prop) => {
            this.setWindowProp(prop, undefined, true)
        })
    }
}
window.city="beijing"
let LegacySandbox01  = new LegacySandbox()
console.log('11',window.city)
LegacySandbox01.active()
LegacySandbox01.propsWindow.city ="shanghai"
console.log('22',window.city)
LegacySandbox01.inactive()
console.log('33',window.city)

三、快照沙箱

原理概述

      全局对象快照:在子应用加载时,对全局对象进行快照,保存其当前状态。

      状态恢复:在子应用卸载时,将全局对象恢复到加载时的状态,以消除子应用对全局对象所做的修改。

具体实现

  1. 在子应用加载前,遍历全局对象并保存其属性和值到一个快照对象中。
  2. 子应用加载并执行过程中,所有对全局对象的修改都只在当前子应用的执行环境中生效。
  3. 子应用卸载时,遍历全局对象并将其属性和值恢复到快照对象中的状态。
// example
class Sanapshotbox {
    // 激活
    windowSnapshot = {}
    modifyPropsMap = {}
​
    
    active() {
        // 保存window 对象上所有属性的状态
        for (const prop in window) {
            this.windowSnapshot[prop] = window[prop]
        }
        // 恢复上一次在运行微应用的时候改过的window 上的属性
        Object.keys(this.modifyPropsMap).forEach(prop => {
            window[prop] = this.modifyPropsMap[prop]
        })
    }
    // 失活 
    inactive() {
        // 记录修改window 上的哪些属性
        for (const prop in window) {
            if (window[prop] !== this.windowSnapshot[prop]) {
                this.modifyPropsMap[prop] = window[prop]
                // 将window 上的属性状态 还原至微应用之前的状态 
                window[prop] = this.windowSnapshot[prop]
            }
        }
    }
}
window.city="beijing"  // 初始值
let sanapshotbox  = new Sanapshotbox()
console.log("11",window.city)
sanapshotbox.active()  // 微应用运行
window.city="上海"
console.log("22",window.city)
sanapshotbox.inactive()  // 微应用卸载了
console.log('33',window.city)

四、选择沙箱机制

Qiankun会根据当前的环境和配置选择使用Proxy沙箱还是快照沙箱,如果浏览器不支持Proxy对象或配置了特定的选项(如singleton: false),则可能会选择使用快照沙箱。

CSS隔离:使用Shadow DOM来实现CSS的隔离。Shadow DOM允许将子应用的DOM和样式封装在一个独立的、隔离的环境中,从而避免子应用之间的样式冲突。

JavaScript隔离:通过沙箱机制,Qiankun能够确保子应用之间的JavaScript执行环境也是隔离的。每个子应用都有自己的“fakeWindow”对象或快照状态,因此它们之间的全局变量和函数不会相互干扰。

相关推荐

  1. 服务框架乾坤沙箱机制实现原理

    2024-07-16 12:40:01       26 阅读
  2. 乾坤前端js沙箱机制

    2024-07-16 12:40:01       31 阅读
  3. qiankun(乾坤前端框架简介

    2024-07-16 12:40:01       44 阅读
  4. 服务原理实践

    2024-07-16 12:40:01       38 阅读
  5. 服务治理:服务治理中服务回退机制

    2024-07-16 12:40:01       44 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-16 12:40:01       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-16 12:40:01       72 阅读
  3. 在Django里面运行非项目文件

    2024-07-16 12:40:01       58 阅读
  4. Python语言-面向对象

    2024-07-16 12:40:01       69 阅读

热门阅读

  1. 力扣题解(交错字符串)

    2024-07-16 12:40:01       26 阅读
  2. 排序-归并排序

    2024-07-16 12:40:01       30 阅读
  3. C#中Dapper的使用教程

    2024-07-16 12:40:01       24 阅读
  4. 运行时动态调整 Pod 的 CPU 及 Memory 资源

    2024-07-16 12:40:01       27 阅读
  5. Python面经

    2024-07-16 12:40:01       24 阅读
  6. Etcd-v3.4.27集群部署

    2024-07-16 12:40:01       22 阅读
  7. 大语言模型的原理

    2024-07-16 12:40:01       24 阅读
  8. Android 底部导航栏实现

    2024-07-16 12:40:01       18 阅读
  9. Spark核心技术架构

    2024-07-16 12:40:01       21 阅读
  10. actual combat 33 —— Vue实战遇到的问题

    2024-07-16 12:40:01       22 阅读
  11. MATLAB切片

    2024-07-16 12:40:01       19 阅读