TT Bigdata TT Bigdata
首页
  • 部署专题

    • 常规安装
    • 一键部署
  • 组件安装

    • 常规&高可用
  • 版本专题

    • 更新说明
  • Ambari-Env

    • 环境准备
    • 开始使用
  • 组件编译

    • 专区—Ambari
    • 专区—Bigtop
  • 报错解决

    • 专区—Ambari
    • 专区—Bigtop
  • 其他技巧

    • Maven镜像加速
    • Gradle镜像加速
    • Bower镜像加速
    • 虚拟环境思路
    • R环境安装+一键安装脚本
    • Ivy配置私有镜像仓库
    • Node.js 多版本共存方案
    • Ambari Web本地启动
    • Npm镜像加速
    • PostgreSQL快速安装
    • Temurin JDK 23快速安装
  • 成神之路

    • 专区—Ambari
    • 专区—Bigtop
  • 集成案例

    • Redis集成教学
    • Dolphin集成教学
    • Doris集成教学
    • 持续整理...
  • 模板代码

    • 各类组件
    • 通用模板
  • 国产化&其他系统

    • Centos系列
    • Kylin系列
    • OpenEuler系列
    • Rocky系列
    • Ubuntu系列
  • 生产调优

    • 组件调优指南
    • 1v1指导调优
  • 定制开发

    • 组件版本定制
    • 样式风格定制
  • 蓝图愿景
  • 技术支持
  • 合作共建
GitHub (opens new window)

JaneTTR

数据酿造智慧,每一滴都是沉淀!
首页
  • 部署专题

    • 常规安装
    • 一键部署
  • 组件安装

    • 常规&高可用
  • 版本专题

    • 更新说明
  • Ambari-Env

    • 环境准备
    • 开始使用
  • 组件编译

    • 专区—Ambari
    • 专区—Bigtop
  • 报错解决

    • 专区—Ambari
    • 专区—Bigtop
  • 其他技巧

    • Maven镜像加速
    • Gradle镜像加速
    • Bower镜像加速
    • 虚拟环境思路
    • R环境安装+一键安装脚本
    • Ivy配置私有镜像仓库
    • Node.js 多版本共存方案
    • Ambari Web本地启动
    • Npm镜像加速
    • PostgreSQL快速安装
    • Temurin JDK 23快速安装
  • 成神之路

    • 专区—Ambari
    • 专区—Bigtop
  • 集成案例

    • Redis集成教学
    • Dolphin集成教学
    • Doris集成教学
    • 持续整理...
  • 模板代码

    • 各类组件
    • 通用模板
  • 国产化&其他系统

    • Centos系列
    • Kylin系列
    • OpenEuler系列
    • Rocky系列
    • Ubuntu系列
  • 生产调优

    • 组件调优指南
    • 1v1指导调优
  • 定制开发

    • 组件版本定制
    • 样式风格定制
  • 蓝图愿景
  • 技术支持
  • 合作共建
GitHub (opens new window)
  • 方法论

  • 代码生命周期-metainfo

    • 加载原理深度剖析[一]
    • 加载原理深度剖析[二]
    • 加载原理深度剖析[三]
    • 结构与层级深入解读
    • configFile详解[一]
    • configFile详解[二]
    • cardinality详解[一]
    • cardinality详解[二]
    • cardinality详解[三]
    • category详解[一]
    • category详解[二]
    • category详解[三]
      • 2.2.4 渲染推荐方案并显示结果
        • 2.2.4.1 recommendationsSuccessCallback 函数详解
        • 2.2.4.2 createComponentInstallationObjects 函数详解
        • 2.2.4.3 处理主机与 MASTER 组件的配对
        • 2.2.4.4 页面渲染结果
    • theme详解[一]
    • theme详解[二]
    • theme详解[三]
    • commandScript详解[二]
    • commandScript详解[一]
    • commandScript详解[三]
    • customCommand详解[一]
    • customCommand详解[二]
    • customCommand详解[三]
    • requiredServices详解[一]
    • requiredServices详解[二]
    • osSpecifics详解[一]
    • osSpecifics详解[二]
    • osSpecifics详解[三]
    • quicklinks详解[一]
    • quicklinks详解[二]
    • quicklinks详解[三]
    • quicklinks详解[四]
  • 架构剖析

  • UI样式

  • GOD-Ambari
  • 代码生命周期-metainfo
JaneTTR
2025-06-01
目录

category详解[三]

# 2.2.4 渲染推荐方案并显示结果 前端逻辑详解

Ambari 完成推荐方案计算后,需要将结果在前端以图形化方式渲染展示出来。这个过程涉及推荐数据的处理、主机与组件的分配映射、以及最终页面上的动态渲染。以下结合核心 JS 逻辑,图示与数据结构,完整还原每一步实现。

# 2.2.4.1 recommendationsSuccessCallback 函数详解

每当用户点击“下一步”触发服务部署推荐时,浏览器会发起 AJAX 请求,后端返回的推荐数据将交由 loadRecommendationsSuccessCallback 函数进行处理。该函数的核心作用是把后端返回的 host_group、component 分布信息转化为便于前端页面渲染的数据结构。

image-20241002114624714

/**
 * Success-callback for recommendations request
 * @param {object} data
 * @method loadRecommendationsSuccessCallback
 */
loadRecommendationsSuccessCallback: function loadRecommendationsSuccessCallback(data) {
    var recommendations = data.resources[0].recommendations;
    this.set('recommendations', recommendations);
    if (this.get('content.controllerName')) {
        this.set('content.recommendations', recommendations);
    }

    var recommendedHostsForComponent = {};
    var hostsForHostGroup = {};

    recommendations.blueprint_cluster_binding.host_groups.forEach(function (hostGroup) {
        hostsForHostGroup[hostGroup.name] = hostGroup.hosts.mapProperty('fqdn');
    });

    recommendations.blueprint.host_groups.forEach(function (hostGroup) {
        var components = hostGroup.components.mapProperty('name');
        components.forEach(function (componentName) {
            var hostList = recommendedHostsForComponent[componentName] || [];
            var hostNames = hostsForHostGroup[hostGroup.name] || [];
            hostList.pushObjects(hostNames);
            recommendedHostsForComponent[componentName] = hostList;
        });
    });

    this.set('recommendedHostsForComponents', recommendedHostsForComponent);
    if (this.get('content.controllerName')) {
        this.set('content.recommendedHostsForComponents', recommendedHostsForComponent);
    }
}
,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
  • hostsForHostGroup:用于将推荐的 host_group 与实际主机进行映射,方便后续查找和展示。

示例结构如下:

{
  "host-group-1": [
    "centos1"
  ],
  "host-group-2": [
    "centos2"
  ],
  "host-group-3": [
    "centos3"
  ]
}
1
2
3
4
5
6
7
8
9
10
11

随后,通过循环,将每个组件名称与具体分配的主机关联起来:

recommendations.blueprint.host_groups.forEach(function (hostGroup) {
    var components = hostGroup.components.mapProperty('name');
    components.forEach(function (componentName) {
        var hostList = recommendedHostsForComponent[componentName] || [];
        var hostNames = hostsForHostGroup[hostGroup.name] || [];
        hostList.pushObjects(hostNames);
        recommendedHostsForComponent[componentName] = hostList;
    });
});
1
2
3
4
5
6
7
8
9

最终,得到了组件到主机的完整映射关系 recommendedHostsForComponent,例如:

{
  "REDIS_CLIENT": [
    "centos1",
    "centos2",
    "centos3"
  ],
  "REDIS_MASTER": [
    "centos1",
    "centos2",
    "centos3"
  ],
  "REDIS_SLAVE": [
    "centos1",
    "centos2",
    "centos3"
  ],
  "ZOOKEEPER_CLIENT": [
    "centos1",
    "centos2",
    "centos3"
  ],
  "ZOOKEEPER_SERVER": [
    "centos1",
    "centos2",
    "centos3"
  ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 2.2.4.2 createComponentInstallationObjects 函数详解

在页面渲染阶段,loadStep 会调用 createComponentInstallationObjects,进一步生成前端展示所需的组件-主机映射对象。

image-20241002152835722

self.loadStepCallback(self.createComponentInstallationObjects(), self);
1

核心实现如下:

/**
 * 为 UI 分配对话框创建用于显示组件-主机组合框的对象
 * content.recommendations 期望已填充推荐的 API 调用结果
 * @return {Object[]}
 */
createComponentInstallationObjects: function createComponentInstallationObjects() {
    var stackMasterComponentsMap = {},  // 用于存储主组件映射
        masterHosts = this.get('content.masterComponentHosts') || this.get('masterComponentHosts'),  // 获取主组件及其主机信息
        servicesToAdd = (this.get('content.services') || []).filterProperty('isSelected').filterProperty('isInstalled', false).mapProperty('serviceName'),  // 筛选出尚未安装的已选服务
        recommendations = this.get('recommendations'),  // 获取推荐的主机和组件映射
        resultComponents = [],  // 最终生成的组件安装对象数组
        multipleComponentHasBeenAdded = {},  // 用于跟踪哪些允许多次出现的组件已经被添加
        hostGroupsMap = {};  // 主机组名称与主机组对象的映射

    // 遍历所有服务组件,挑选出需要显示的主组件并存储到 stackMasterComponentsMap 中
    App.StackServiceComponent.find().forEach(function (component) {
        var isMasterCreateOnConfig = this.get('mastersToCreate').contains(component.get('componentName'));  // 判断是否需要根据配置创建主组件
        // 如果是在安装向导中,并且组件需要显示在主组件分配页面或通过配置需要创建,则将其加入映射
        if (this.get('isInstallerWizard') && (component.get('isShownOnInstallerAssignMasterPage') || isMasterCreateOnConfig)) {
            stackMasterComponentsMap[component.get('componentName')] = component;
            // 如果是在添加服务时需要显示或通过配置需要创建的主组件,也将其加入映射
        } else if (component.get('isShownOnAddServiceAssignMasterPage') || this.get('mastersToShow').contains(component.get('componentName')) || isMasterCreateOnConfig) {
            stackMasterComponentsMap[component.get('componentName')] = component;
        }
    }, this);

    // 遍历推荐的主机组,构建主机组与主机的映射关系
    recommendations.blueprint_cluster_binding.host_groups.forEach(function (group) {
        hostGroupsMap[group.name] = group;
    });

    // 遍历推荐的主机组中的组件,并决定哪些组件需要显示
    recommendations.blueprint.host_groups.forEach(function (host_group) {
        var hosts = hostGroupsMap[host_group.name] ? hostGroupsMap[host_group.name].hosts : [];  // 获取当前主机组中的主机

        // 遍历主机组中的每个主机
        hosts.forEach(function (host) {
            host_group.components.forEach(function (component) {
                var willBeDisplayed = true;  // 变量表示是否需要显示该组件

                // 获取当前组件对应的主组件
                var stackMasterComponent = stackMasterComponentsMap[component.name];

                // 如果该组件是主组件,则进行进一步判断
                if (stackMasterComponent) {
                    var isMasterCreateOnConfig = this.get('mastersToCreate').contains(component.name);  // 判断是否需要根据配置创建该主组件
                    // 如果服务已经安装并且不打算添加新服务,则仅渲染那些已经安装的主组件
                    if (!servicesToAdd.contains(stackMasterComponent.get('serviceName')) && !isMasterCreateOnConfig) {
                        willBeDisplayed = masterHosts.someProperty('component', component.name);  // 检查当前组件是否已安装
                    }

                    // 如果组件需要显示,则生成组件安装对象
                    if (willBeDisplayed) {
                        var savedComponents = masterHosts.filterProperty('component', component.name);  // 获取已保存的组件信息

                        // 处理可以多次出现的组件,如果组件已经存在多个实例,确保每个实例只被添加一次
                        if (this.get('multipleComponents').contains(component.name) && savedComponents.length > 0) {
                            if (!multipleComponentHasBeenAdded[component.name]) {
                                multipleComponentHasBeenAdded[component.name] = true;

                                savedComponents.forEach(function (saved) {
                                    resultComponents.push(this.createComponentInstallationObject(stackMasterComponent, host.fqdn.toLowerCase(), saved));  // 创建组件安装对象并加入结果集
                                }, this);
                            }
                        } else {
                            var savedComponent = masterHosts.findProperty('component', component.name);  // 获取已保存的组件信息
                            resultComponents.push(this.createComponentInstallationObject(stackMasterComponent, host.fqdn.toLowerCase(), savedComponent));  // 创建组件安装对象
                        }
                    }
                }
            }, this);
        }, this);
    }, this);

    return resultComponents;  // 返回生成的组件安装对象数组
}
,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
  • stackMasterComponentsMap:记录所有 MASTER 类型组件。 image-20241002153108710

    这里面主要包括 REDIS_MASTER 和 ZOOKEEPER_SERVER。

# 2.2.4.3 处理主机与 MASTER 组件的配对

结合 stackMasterComponentsMap,最终生成的 resultComponents 只会包含属于 MASTER 的组件和分配主机的配对关系。

例如,结果结构如下:

image-20241002155554795

[
  {
    "component_name": "REDIS_MASTER",
    "display_name": "Redis Master",
    "serviceId": "REDIS",
    "isServiceCoHost": false,
    "selectedHost": "centos1",
    "isInstalled": true
  },
  {
    "component_name": "REDIS_MASTER",
    "display_name": "Redis Master",
    "serviceId": "REDIS",
    "isServiceCoHost": false,
    "selectedHost": "centos2",
    "isInstalled": true
  },
  {
    "component_name": "REDIS_MASTER",
    "display_name": "Redis Master",
    "serviceId": "REDIS",
    "isServiceCoHost": false,
    "selectedHost": "centos3",
    "isInstalled": true
  },
  {
    "component_name": "ZOOKEEPER_SERVER",
    "display_name": "ZooKeeper Server",
    "serviceId": "ZOOKEEPER",
    "isServiceCoHost": false,
    "selectedHost": "centos3",
    "isInstalled": false
  },
  {
    "component_name": "ZOOKEEPER_SERVER",
    "display_name": "ZooKeeper Server",
    "serviceId": "ZOOKEEPER",
    "isServiceCoHost": false,
    "selectedHost": "centos2",
    "isInstalled": false
  },
  {
    "component_name": "ZOOKEEPER_SERVER",
    "display_name": "ZooKeeper Server",
    "serviceId": "ZOOKEEPER",
    "isServiceCoHost": false,
    "selectedHost": "centos1",
    "isInstalled": false
  }
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

image-20241002151212330 image-20241002151356603

# 2.2.4.4 页面渲染结果

最终,所有分配到 MASTER 类别的组件(如 Redis Master、ZooKeeper Server)都会以可视化形式展现在主机分配页面,每个组件都标明分配在哪台服务器。

image-20241002155703093

笔记

本节详细解析了从后端推荐方案到前端 JS 处理再到 UI 渲染的完整链路,全流程可追溯,且所有关键数据结构、图片与代码均已完整呈现,便于快速定位与扩展页面功能。

#Ambari#metainfo#推荐部署#StackAdvisor#自动化运维#组件编排
category详解[二]
theme详解[一]

← category详解[二] theme详解[一]→

最近更新
01
Pandoc 缺失导致 SparkR 构建失败
06-08
02
Cyrus SASL/GSASL 缺失解决
06-07
03
Hadoop_3.3.4 编译实战 1.0.0+
06-06
更多文章>
Theme by Vdoing | Copyright © 2017-2025 JaneTTR | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式