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

  • 架构剖析

    • server与agent协作详解[一]
    • server与agent协作详解[二]
    • ambari install逻辑详解[一]
    • ambari install逻辑详解[二]
    • ambari install逻辑详解[三]
    • stack-hooks逻辑详解[一]
    • stack-hooks逻辑详解[二]
    • distro-select逻辑详解
    • java 请求过程解读[一]
    • java 请求过程解读[二]
    • java 请求过程解读[三]
      • 4. 最佳实践与技巧 💡
        • 4.1 通过 Resource.Type.<Xxx> 快速定位
      • 5. 总结与延伸学习 🚀
        • 5.1 内容回顾
    • java 请求过程泛化及补充[一]
    • java 请求过程泛化及补充[二]
  • UI样式

  • GOD-Ambari
  • 架构剖析
JaneTTR
2025-06-03
目录

java 请求过程解读[三]

# 3.6 Provider 解读

在 3.5 ClusterController 解读 中,我们已经了解到 ClusterController 如何通过查找和调用资源提供者(ResourceProvider )来驱动整个查询链路。本节我们聚焦于资源提供者(Provider)体系的实现细节与工作流,包括它们的分层结构、实例化机制、查询分发和实际数据的获取。你将看到 Ambari 如何用统一的 Provider 体系高效适配不同的资源类型,并通过工厂和缓存模式实现极强的扩展性和灵活性。

Provider管理与分发架构

提示

如上图所示,Provider 层通过 ProviderModule 管理,DefaultProviderModule 是核心工厂,针对不同资源类型返回对应 ResourceProvider 实例(如 StackServiceResourceProvider、JobResourceProvider 等),支撑了整个资源查询能力。

# 3.6.1 Provider 之间的分层与协作

Ambari 所有资源提供者(ResourceProvider)都继承自 AbstractProviderModule,统一了资源管理接口与缓存逻辑。 而 DefaultProviderModule 是它的标准实现,负责实际的 Provider 实例化与注册。两者关系如下:

  • AbstractProviderModule

    • 抽象类,定义了 Provider 的通用接口与注册、查找、缓存机制(如 getResourceProvider、registerResourceProvider、createResourceProvider 等)。
  • DefaultProviderModule

    • 继承自 AbstractProviderModule,实现了 createResourceProvider,根据资源类型工厂化创建并返回对应 Provider。

核心代码与逻辑:

@Override
public ResourceProvider getResourceProvider(Resource.Type type) {
    if (!resourceProviders.containsKey(type)) {
        registerResourceProvider(type); // 未注册则自动注册
    }
    return resourceProviders.get(type); // 缓存命中直接返回
}
1
2
3
4
5
6
7

笔记

通过 Provider 层的缓存机制,Ambari 避免了重复构建 Provider,极大提升了查询性能与资源复用。

# 3.6.2 Provider 注册与工厂分发

  • createResourceProvider:由子类实现,针对不同资源类型返回具体 Provider 实例。
  • registerResourceProvider:自动注册新 Provider 到缓存,并为支持监听的 Provider 自动绑定观察者模式。
protected abstract ResourceProvider createResourceProvider(Resource.Type type);

protected void registerResourceProvider(Resource.Type type) {
    ResourceProvider resourceProvider = createResourceProvider(type);

    if (resourceProvider instanceof ObservableResourceProvider) {
        ((ObservableResourceProvider) resourceProvider).addObserver(this); // 自动监听变更
    }
    putResourceProvider(type, resourceProvider);
}
1
2
3
4
5
6
7
8
9
10

每种资源类型(如 StackService、Job、Workflow 等)都有专属 Provider 实现,DefaultProviderModule 能按需分发和注册。

# 3.6.3 Provider 的按需获取与复用

getResourceProvider 方法负责查找指定资源类型的 Provider。没有则注册新 Provider,有则复用缓存。

public ResourceProvider getResourceProvider(Resource.Type type) {
    if (!resourceProviders.containsKey(type)) {
        registerResourceProvider(type);
    }
    return resourceProviders.get(type);
}
1
2
3
4
5
6
  • 逻辑要点:

    • 支持多资源类型(每种类型单独缓存,避免并发创建冲突)
    • 注册时自动实现 Provider 的解耦和生命周期管理

# 3.6.4 DefaultProviderModule 的分发实现

在 DefaultProviderModule 中,不同资源类型会分发到不同的 Provider 实例:

@Override
protected ResourceProvider createResourceProvider(Resource.Type type) {
    LOGGER.debug("Creating resource provider for the type: {}", type);

    switch (type.getInternalType()) {
        case Workflow:
            return new WorkflowResourceProvider();
        case Job:
            return new JobResourceProvider();
        case TaskAttempt:
            return new TaskAttemptResourceProvider();
        // 其他资源类型...
        default:
            LOGGER.debug("Delegating creation of resource provider for: {} to the AbstractControllerResourceProvider", type.getInternalType());
            return AbstractControllerResourceProvider.getResourceProvider(type, managementController);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  • 逻辑要点:

    • 大部分常见类型(如 Workflow、Job 等)专门 Provider 直连
    • 默认走通用的 ControllerResourceProvider,适配未知或扩展类型

这种实现允许自定义资源类型 Provider解耦与扩展性,满足未来扩展和第三方插件对接需求。

# 3.6.5 Provider 查询主流程:getResources

每个 Provider 必须实现自己的 getResources 方法,负责根据请求条件返回实际的数据集合。以 StackServiceResourceProvider 为例:

StackServiceResourceProvider 查询链路

@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<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;
}
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
  • 构建查询:先将请求/条件转化为标准化的 requests。
  • 实际执行:调用 managementController 的 getStackServices(或同类方法)真正去查询业务数据。
  • 封装返回:用 createResource 封装结果,统一数据格式后返回。

# 4. 最佳实践与技巧 💡

在 Ambari 项目中,规范的命名和工厂分发机制极大提升了源码的可读性和可维护性。以下技巧和习惯可以帮你更快定位和理解 Provider 的实现:

# 4.1 通过 Resource.Type.<Xxx> 快速定位

  • 每种资源类型(如 StackService、Cluster、Host 等)都有固定的命名规范:

    • 资源定义:如 StackServiceResourceDefinition
    • 资源提供者:如 StackServiceResourceProvider
  • 只要知道 Resource.Type,就可以一键全局搜索到对应的 ResourceDefinition/ResourceProvider 源码。

提示

配合 IDE 的类跳转、正则搜索与类型全局定位,可以显著提高定位和理解复杂 Provider 的效率。

# 5. 总结与延伸学习 🚀

# 5.1 内容回顾

本文详细讲解了 Provider 层在 Ambari 服务查询流程中的关键作用,包含:

  1. Provider 层次结构:分层抽象与 DefaultProviderModule 工厂实现,带来良好的扩展性与解耦。
  2. Provider 创建与分发机制:缓存与注册、自动类型分发、可插拔扩展。
  3. getResources 查询链路:统一规范的数据查询和结果封装。
  4. 命名规则和快速定位技巧:助你高效扩展、维护和定制 Ambari 查询能力。

通过本节内容,你可以轻松理解 Ambari 查询处理的对象流转链条,快速定位 Provider 实现,掌握二次开发和问题定位的核心工具。

#Ambari#Provider#ResourceProvider#查询链路#资源工厂模式
java 请求过程解读[二]
java 请求过程泛化及补充[一]

← java 请求过程解读[二] java 请求过程泛化及补充[一]→

最近更新
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
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式