大厂50万节点监控系统架构设计&Prometheus底层源码级剖析

144 阅读4分钟

download:大厂50万节点监控系统架构设计&Prometheus底层源码级剖析

函数剖析

从 Demo 我们看到,整个项目先经过 createRoot 这个函数创立一个 root 对象,再经过 rootrender 办法将 App 这个组件渲染到网页上

createRoot

我们先看 createRoot 这个办法详细做了什么事情。这个办法来自 react-dom 这个包。我们能够在源码中 packages / react-dom / src / client / ReactDOMRoot.js 中找到 createRoot 的详细完成(前面在 ReactDOM.js 做了一些关于环境的条件判别,可先疏忽)

createRoot 函数有两个参数 containeroptions,其中 options 是可选参数,本章为了简单起见先不讨论;

该函数大约完成的功用就是:

  1. 创立容器对象 FiberRootNode

  2. 事情拜托处置

  3. 依据 FiberRootNode 对象返回 ReactDOMRoot 对象

    // 删除了一些干扰逻辑之后,createRoot 函数大致如下所示 function createRoot( container: Element | DocumentFragment, options?: CreateRootOptions, ): RootType { let isStrictMode = false; let concurrentUpdatesByDefaultOverride = false; let identifierPrefix = ''; let onRecoverableError = defaultOnRecoverableError; let transitionCallbacks = null;

    // 创立容器对象 FiberRootNode const root = createContainer( container, ConcurrentRoot, null, isStrictMode, concurrentUpdatesByDefaultOverride, identifierPrefix, onRecoverableError, transitionCallbacks, ); markContainerAsRoot(root.current, container);

    // 事情监听处置 const rootContainerElement: Document | Element | DocumentFragment = container.nodeType === COMMENT_NODE ? (container.parentNode: any) : container; listenToAllSupportedEvents(rootContainerElement);

    // 依据容器对象 root 返回 ReactDOMRoot 对象 return new ReactDOMRoot(root); }

createContainer 函数完成了 创立容器对象 FiberRootNode 的工作。

这个办法来自 react-reconciler 这个包,能够在 packages / react-reconciler / src / ReactFiberReconciler.old.js 中找到,而这个办法内容也很简单,直接调用了同层级 ReactFiberRoot.old.js 文件的 createFiberRoot 办法来创立并返回一个 FiberRootNode 对象,也称之为 Fiber 根结点

留意: 这里的 Fiber 根结点Fiber 节点 是有区别的,细致可看下面的各自的定义函数

这里引入一个概念叫做 Fiber,目前我们只需求对他有个初步的印象:Fiber 节点用于存储 React 组件节点信息(包括 DOM节点,组件的属性 / state / effect 等)。这里能够简单了解为一个存储信息的 JS 对象,后续章节会细致引见

function createFiberRoot(containerInfo, tag, hydrate, initialChildren, hydrationCallbacks, isStrictMode, concurrentUpdatesByDefaultOverride,
identifierPrefix, onRecoverableError, transitionCallbacks) {
  // 创立 FiberRootNode 对象
  // tag 值为 ConcurrentRoot,定义在 packages/react-reconciler/src/ReactRootTags.js 文件中;
  // tag === ConcurrentRoot === 1 ,表示 “根节点”
  var root = new FiberRootNode(containerInfo, tag, hydrate, identifierPrefix, onRecoverableError);
  // 倡议看到这里先别焦急看后面的代码,先看看下面 FiberRootNode 的定义和结构函数
  
  // 分割线 ************** 分割线 ************** 分割线 ************** 分割线 **************
  
  // 看完 FiberRootNode 的定义之后,接下来马上要创立 Fiber 对象
  // createHostRootFiber 会调用 packages/react-reconciler/src/ReactFiber.old.js 文件中的 createFiber 办法创立一个 `Fiber HostRoot节点`
  // `Fiber HostRoot节点` 就是一个 Fiber 对象,只是他的 Tag 等于 3,代表 `HostRoot`
  var uninitializedFiber = createHostRootFiber(tag, isStrictMode);
  
  // 把 `Fiber 根结点` 的 current 属性指向刚创立的 `Fiber HostRoot节点`
  root.current = uninitializedFiber;
  // `Fiber HostRoot节点` 的 stateNode 属性指向 `Fiber 根结点`
  uninitializedFiber.stateNode = root;
  // cache 相关的可先疏忽
  var initialCache = createCache();
  retainCache(initialCache);
  root.pooledCache = initialCache;
  retainCache(initialCache);
  
  // 初始化一个 state 对象
  var initialState = {
      element: initialChildren,
      isDehydrated: hydrate,
      cache: initialCache,
      transitions: null
  };
  uninitializedFiber.memoizedState = initialState;
  
  // 初始化 `Fiber HostRoot节点` 的更新队列
  // 给 Fiber 的 updateQueue 属性赋值
  /**
  var queue = {
    baseState: fiber.memoizedState,
    firstBaseUpdate: null,
    lastBaseUpdate: null,
    shared: {
      pending: null,
      interleaved: null,
      lanes: NoLanes
    },
    effects: null
  };
  fiber.updateQueue = queue;
  **/
  initializeUpdateQueue(uninitializedFiber);
  
  // 返回 `Fiber 根结点`
  return root;
}

FiberRootNode 的定义:

一个结构函数,对象内保管Fiber 根节点的信息,可先关注以下几个

  • tag:标识节点类型,此处为 ConcurrentRoot

  • containerInfo:Fiber 根节点的 DOM 信息,表示在这个 DOM 节点内部渲染当前 React 应用

  • current:保管当前 Fiber 树(后续章节会讲到)

  • 其他属性能够先大致扫一遍,重要是的后续会逐一引见

    // 在`packages/react-reconciler/src/ReactFiberRoot.old.js`文件中
    // FiberRootNode 结构函数
    function FiberRootNode(containerInfo, tag, hydrate, identifierPrefix, onRecoverableError) {
    this.tag = tag;
    this.containerInfo = containerInfo;
    this.pendingChildren = null;
    this.current = null;
    ....
    // 省略其他属性初始化
    ....
    

Fiber 节点的定义

function FiberNode(
  tag: WorkTag,
  pendingProps: mixed,
  key: null | string,
  mode: TypeOfMode,
) {
  // tag 表示 Fiber 类型
  // packages/react-reconciler/src/ReactWorkTags.js 中定义
  this.tag = tag;
  // 写在 jsx 组件上的 key 属性
  this.key = key;
  // createElement的第一个参数,ReactElement 上的 type
  this.elementType = null;
  // 暂时可以为与 elementType 根本分歧
  this.type = null;
  // fiber 节点对应的 DOM 节点
  this.stateNode = null;
  // Fiber 构造
  // 指向父节点
  this.return = null;
  // 指向第一个子节点
  this.child = null;
  // 指向兄弟节点
  this.sibling = null;
  // 普通假如没有兄弟节点的话是 0 当某个父节点下的子节点是数组类型的时分会给每个子节点一个 index
  this.index = 0;
  // 保管 ref 属性对象
  this.ref = null;
  
  // 新的 props 对象
  this.pendingProps = pendingProps;
  // 现有的 props 对象
  this.memoizedProps = null;
  // 保管更新对象的队列
  this.updateQueue = null;
  // 现有的 state 对象
  this.memoizedState = null;
  // 依赖对象
  this.dependencies = null;
    
  // 渲染方式
  // React 18 默许是 `ConcurrentMode`: 0b000001
  // packages/react-reconciler/src/ReactTypeOfMode.js 文件中定义
  this.mode = mode;
  // Effects
  // effect 的 Flag,标明当前的 effect 是`交换`/ `更新` / `删除` 等操作
  // packages/react-reconciler/src/ReactFiberFlags.js
  this.flags = NoFlags;
  // 子树的 Flag 合集
  this.subtreeFlags = NoFlags;
  // 需求删除的 fiber 节点
  this.deletions = null;
  
  // 更新渲染调度优先级相关
  // packages/react-reconciler/src/ReactFiberLane.old.js 文件中定义
  this.lanes = NoLanes;
  this.childLanes = NoLanes;
  
  // current 树和 workInprogress 树之间的互相援用
  // current 树就是当前的 Fiber 树
  // workInprogress 树 就是正在更新的 Fiber 树
  // 后续讲到组件更新会细致讲到
  this.alternate = null;
  if (enableProfilerTimer) {
    // 。。。 省略
  }
 }

总结一下: createContainer 办法经过 createFiberRoot 创立并返回 Fiber 根节点FiberRootNode 对象。同时该对象的 current 属性指向一个 Fiber HostRoot节点