requiredServices详解[二]
# 3.2 前端部分代码详解
# 3.2.1 validate
方法
提示
位置:app/controllers/wizard/step4_controller.js
该方法拉起整个依赖校验链,是前端服务依赖检测的入口。
在 step4_controller.js
中,validate
方法负责启动整个依赖校验过程。它依次调用了多个方法,确保所有服务的依赖关系得到正确验证。
- 文件:
app/controllers/wizard/step4_controller.js
- 主要职责:触发服务依赖校验、服务校验、错误聚合与反馈,阻止依赖不满足情况下的继续安装。
# 3.2.2 serviceDependencyValidation
方法
笔记
核心作用:收集和校验所有服务依赖,并将缺失项加入错误堆栈。
位于同一文件中,核心代码如下:
serviceDependencyValidation: function (callback) {
var selectedServices = this.filterProperty('isSelected', true);
var availableServices = this.get('content');
var missingDependencies = [];
// 遍历已选择的服务,收集缺失的依赖
selectedServices.forEach(function (service) {
service.collectMissingDependencies(selectedServices, availableServices, missingDependencies);
});
// 清理已有的服务检查错误
this.cleanExistingServiceCheckErrors();
this.addServiceCheckErrors(missingDependencies, callback);
}
,
cleanExistingServiceCheckErrors()
{
var existingServiceCheckErrors = this.get('errorStack').filter(function (error) {
return error.id.startsWith('serviceCheck_');
});
// 添加缺失依赖的错误
this.get('errorStack').removeObjects(existingServiceCheckErrors);
}
,
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
- 文件路径:
app/controllers/wizard/step4_controller.js
- 说明:先收集所有服务依赖缺失,再清理旧的校验错误,最后聚合到统一错误反馈。
# 3.2.3 collectMissingDependencies
方法
提示
依赖收集核心,直接调用 _missingDependencies,聚合缺失依赖。
位于 app/models/stack_service.js
:
collectMissingDependencies: function (selectedServices, availableServices, missingDependencies) {
this._missingDependencies(selectedServices, availableServices).forEach(function (dependency) {
this._addMissingDependency(dependency, availableServices, missingDependencies);
}.bind(this));
}
,
2
3
4
5
6
- 文件路径:
app/models/stack_service.js
- 说明:遍历所有选中服务,通过
_missingDependencies
判断缺失项,逐条 push 进缺失依赖数组。
# 3.2.4 _missingDependencies
和 isMissing
方法
笔记
_missingDependencies
根据 isMissing 结果过滤出缺失依赖,是判断逻辑的核心环节。
位于 app/models/stack_service.js
:
_missingDependencies: function (selectedServices, availableServices) {
return this.dependencies(availableServices).filter(function (dependency) {
return dependency.isMissing(selectedServices);
});
}
2
3
4
5
- 文件路径:
app/models/stack_service.js
- 说明:依赖数组只返回 isMissing 判定为 true 的服务,直观输出缺失项列表。
# 3.2.5 _addMissingDependency
方法
注意
此方法确保不会重复添加同一个缺失依赖,并会记录依赖名称、显示名称和兼容性信息。
位于 app/models/stack_service.js
:
_addMissingDependency: function (dependency, availableServices, missingDependencies) {
if (!missingDependencies.someProperty('serviceName', dependency.get('name'))) {
missingDependencies.push(MissingDependency.create({
serviceName: dependency.get('name'),
displayName: dependency.get('displayName'),
compatibleServices: dependency.compatibleServices(availableServices)
}));
}
}
2
3
4
5
6
7
8
9
- 文件路径:
app/models/stack_service.js
- 作用:避免重复,将新缺失依赖 push 进缺失依赖数组,包含服务名称、显示名称及兼容服务列表。
# 3.2.6 总结:Ambari 如何校验安装依赖
提示
Ambari 依赖校验流程小结
- 收集缺失的依赖项:
serviceDependencyValidation
+collectMissingDependencies
- 判断依赖项是否缺失:
_missingDependencies
+isMissing
- 记录缺失的依赖:
_addMissingDependency
追加到缺失依赖数组 - 错误反馈与处理:最终 push 到错误堆栈,阻断后续流程
# 4. 最佳实践与技巧 💡
# 4.1 快速定位相关代码
提示
高效定位和调试源码,是提升开发效率的关键
# 4.1.1 通过请求路径定位到服务类
每个 API 请求都能通过 路径参数(@Path
注解)定位到对应 Java 处理类。
比如:
curl 'http://centos1:8080/api/v1/stacks/BIGTOP/versions/3.1.0/services?...'
笔记
根据路径,查找 stacks
和 versions
关键词,可定位到 StacksService.java
:
src/main/java/org/apache/ambari/server/api/services/StacksService.java
# 4.1.2 通过资源类型定位到资源定义
定位到服务类后,根据 资源类型 查找定义。
case StackService:
resourceDefinition = new StackServiceResourceDefinition();
break;
2
3
- 位置:
ResourceInstanceFactoryImpl.java
- 路径:
src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
# 4.1.3 快速推断对应的资源提供器(Provider)
资源类型与定义确定后,对应 Provider 也就明了。
case StackService:
return new StackServiceResourceProvider();
2
- 路径:
src/main/java/org/apache/ambari/server/controller/internal/StackServiceResourceProvider.java
# 4.1.4 定位到数据获取方法:getResources
大部分 Provider 都有 getResources
,这是数据聚合与返回的核心。
@Override
public Set<Resource> getResources(Request request, Predicate predicate)
throws SystemException, UnsupportedPropertyException,
NoSuchResourceException, NoSuchParentResourceException {
final Set<StackServiceRequest> requests = new HashSet<>();
if (predicate == null) {
requests.add(getRequest(Collections.emptyMap()));
} else {
for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) {
requests.add(getRequest(propertyMap));
}
}
Set<String> requestedIds = getRequestPropertyIds(request, predicate);
Set<StackServiceResponse> responses = getResources(new Command<Set<StackServiceResponse>>() {
@Override
public Set<StackServiceResponse> invoke() throws AmbariException {
return getManagementController().getStackServices(requests);
}
});
Set<Resource> resources = new HashSet<>();
for (StackServiceResponse response : responses) {
Resource resource = createResource(response, requestedIds);
resources.add(resource);
}
return resources;
}
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
提示
跟踪 getResources,即可定位后端数据的流转路径。
# 5. 总结与延伸学习 🚀
# 5.1 内容回顾
提示
本节通过完整代码、注释、所有原图和逐层讲解,详细梳理了 Ambari 前端依赖校验机制和 Java 后端接口的定位方法。 配合实际开发场景,帮助你更高效掌控 Ambari 二次开发与排错全链路。