Spark加载hadoop配置原理
0x0 背景
最近为了将hadoop&hive的五大配置文件,即:
core-site.xml
hdfs-site.xml
yarn-site.xml
mapred-site.xml
hive-site.xml
从项目中(classpath)移到项目外(任意位置),研究了spark启动过程的源码,在此记录一下。
0x1 Hadoop及Hive获取默认配置过程
Hadoop有一个类
Configuration implementsIterable<Map.Entry<String,String>>,Writable
这个类就是用于处理hadoop的配置,其内部有静态代码块:
static{
//print deprecation warning if hadoop-site.xml is found in classpath
ClassLoader cL = Thread.currentThread().getContextClassLoader();
if (cL == null) {
cL = Configuration.class.getClassLoader();
}
if(cL.getResource("hadoop-site.xml")!=null) {
LOG.warn("DEPRECATED: hadoop-site.xml found in the classpath. " +
"Usage of hadoop-site.xml is deprecated. Instead use core-site.xml, "
+ "mapred-site.xml and hdfs-site.xml to override properties of " +
"core-default.xml, mapred-default.xml and hdfs-default.xml " +
"respectively");
}
addDefaultResource("core-default.xml");
addDefaultResource("core-site.xml");
}
可见,当Configuration加载后,就会从classpath读取
hadoop-site.xml
core-default.xml
core-site.xml
这三个配置文件。
同时,Configuration类有四个子类:
分别是:
HdfsConfiguration
HiveConf
JobConf
YarnConfiguration
进入这四个类内部同样可以见到类似的静态代码,
HdfsConfiguration中:
static {
addDeprecatedKeys();
// adds the default resources
Configuration.addDefaultResource("hdfs-default.xml");
Configuration.addDefaultResource("hdfs-site.xml");
}
YarnConfiguration中:
static {
addDeprecatedKeys();
Configuration.addDefaultResource("yarn-default.xml");
Configuration.addDefaultResource("yarn-site.xml");
...
}
JobConf中:
public static void loadResources() {
addDeprecatedKeys();
Configuration.addDefaultResource("mapred-default.xml");
Configuration.addDefaultResource("mapred-site.xml");
Configuration.addDefaultResource("yarn-default.xml");
Configuration.addDefaultResource("yarn-site.xml");
}
但是HiveConf并未在静态代码块中读取配置文件,然而在CarbonData的启动过程中,会读取hive-site.xml:
val hadoopConf = new Configuration()
val configFile = Utils.getContextOrSparkClassLoader.getResource("hive-site.xml")
if (configFile != null) {
hadoopConf.addResource(configFile)
}
可见,Hadoop在启动过程中,各组件会首先在classpath下读取相应的配置文件。
我们也可以通过Configuration的set(String name, String value)或者addResource(Path file)方法来添加配置,addResource内部执行流程如下:
//将资源添加到resources列表(存储配置文件资源的列表)
resources.add(resource); // add to resources
//将已有的属性清空
properties = null; // trigger reload
finalParameters.clear(); // clear site-limits
//重新加载所有配置
loadResources(Properties properties,
ArrayList<Resource> resources,
boolean quiet)
0x2 Spark启动过程中设置Hadoop配置
Spark Application启动过程中首先要实启动一个SparkContext,其实SparkContext本质上可以理解为Spark运行的配置集合。
val sc = SparkContext.getOrCreate(sparkConf)
而在SparkContext创建过程中会启动一个调度任务,用于连接远程集群:
val backend = cm.createSchedulerBackend(sc, masterUrl, scheduler)
如果是Spark on Yarn,会调用YarnClusterManager的createSchedulerBackend方法:
override def createSchedulerBackend(sc: SparkContext,
masterURL: String,
scheduler: TaskScheduler): SchedulerBackend = {
sc.deployMode match {
case "cluster" =>
new YarnClusterSchedulerBackend(scheduler.asInstanceOf[TaskSchedulerImpl], sc)
case "client" =>
new YarnClientSchedulerBackend(scheduler.asInstanceOf[TaskSchedulerImpl], sc)
case _ =>
throw new SparkException(s"Unknown deploy mode '${sc.deployMode}' for Yarn")
}
}
然后在YarnClientSchedulerBackend中创建了YarnClient,可见看Client中的构造函数:
private[spark] class Client(
val args: ClientArguments,
val hadoopConf: Configuration,
val sparkConf: SparkConf)
extends Logging {
import Client._
import YarnSparkHadoopUtil._
def this(clientArgs: ClientArguments, spConf: SparkConf) =
this(clientArgs, SparkHadoopUtil.get.newConfiguration(spConf), spConf)
private val yarnClient = YarnClient.createYarnClient
private val yarnConf = new YarnConfiguration(hadoopConf)
可见,Spark将利用SparkConf中的配置,调用SparkHadoopUtil.get.newConfiguration(spConf)方法生成相应的Hadoop配置。
其实,在SparkContext中,有2个成员变量(本质上是一个):
private var _hadoopConfiguration: Configuration = _
def hadoopConfiguration: Configuration = _hadoopConfiguration
....
_hadoopConfiguration = SparkHadoopUtil.get.newConfiguration(_conf)
这个_hadoopConfiguration 也是通过SparkHadoopUtil.get.newConfiguration(_conf)方法获取到hadoop的配置。
进入SparkHadoopUtil.get.newConfiguration(_conf)方法,可见到:
conf.getAll.foreach { case (key, value) =>
if (key.startsWith("spark.hadoop.")) {
hadoopConf.set(key.substring("spark.hadoop.".length), value)
}
}
1
2
3
4
5
也就是说,在SparkConf中所有以spark.hadoop.开头的属性,都会被转换为hadoop的配置。
那么我们通过解析hadoop的xml配置文件,转换为相应的键值对,传给spark就可以了。代码如下:
/**
* 读取hadoopConfPath下所有hadoop相关配置文件,并转换为SparkConf
*
* @param hadoopConfPath hadoop配置文件所在的文件夹
* @return
*/
public SparkConf getHadoopConf(String hadoopConfPath) {
SparkConf hadoopConf = new SparkConf();
try {
Map<String, String> hiveConfMap = parseXMLToMap(hadoopConfPath + "/hive-site.xml");
Map<String, String> hadoopConfMap = parseXMLToMap(hadoopConfPath + "/core-site.xml");
hadoopConfMap.putAll(parseXMLToMap(hadoopConfPath + "/hdfs-site.xml"));
hadoopConfMap.putAll(parseXMLToMap(hadoopConfPath + "/yarn-site.xml"));
hadoopConfMap.putAll(parseXMLToMap(hadoopConfPath + "/mapred-site.xml"));
for (Map.Entry<String, String> entry : hiveConfMap.entrySet()) {
hadoopConf.set(entry.getKey(), entry.getValue());
}
for (Map.Entry<String, String> entry : hadoopConfMap.entrySet()) {
hadoopConf.set("spark.hadoop." + entry.getKey(), entry.getValue());
}
return hadoopConf;
} catch (DocumentException e) {
logger.error("读取xml文件失败!");
throw new RuntimeException(e);
}
}
//将xml解析为HashMap
private Map<String, String> parseXMLToMap(String xmlFilePath) throws DocumentException {
Map<String, String> confMap = new HashMap<>();
SAXReader reader = new SAXReader();
Document document = reader.read(new File(xmlFilePath));
Element configuration = document.getRootElement();
Iterator iterator = configuration.elementIterator();
while (iterator.hasNext()) {
Element property = (Element) iterator.next();
String name = property.element("name").getText();
String value = property.element("value").getText();
confMap.put(name, value);
}
return confMap;
}
注意:
经测试,如果集群有kerberos加密,该方法无效!
原因可能是:
class SparkHadoopUtil extends Logging {
private val sparkConf = new SparkConf(false).loadFromSystemProperties(true)
val conf: Configuration = newConfiguration(sparkConf)
UserGroupInformation.setConfiguration(conf)
在该类中设置了一个new的SparkConf,这个SparkConf只从System.getProperty读取spark开头的属性,因此不是正确的属性,导致kerberos登录异常。
Spark加载hadoop配置原理相关推荐
- Springboot默认加载application.yml原理
Springboot默认加载application.yml原理以及扩展 SpringApplication.run(-)默认会加载classpath下的application.yml或applicat ...
- atitit.动态加载数据库配置in orm hibernate mybatis
atitit.动态加载数据库配置in orm 1. 动态加载数据库配置的优点::: 1 1.1. 组合多个配置文件... 1 1.2. 连接多个数据库 1 2. 基本的流程:::getCfg内存对象, ...
- 模块化加载_webpack模块化原理-异步加载模块
在上篇文章中,我们介绍了 webpack 同步加载模块的原理.这篇文章,我们来介绍一下 webpack 异步加载模块. 异步加载模块 还是先做一些准备工作. 首先定义一个依赖模块:math.js,ma ...
- Selenium基础 — 拓展:使用浏览器加载项配置实现用户免登陆
1.什么是加载项配置 在很多情况下,我们在登录网站的时候,浏览器都会弹出一个是否保存登录账号的信息.如果我们选择保存,那么我们在下次登录时就不用再次输入账号,直接免登录了. 在我们实际的测试过程中,测 ...
- 前端性能优化之资源传输优化、渲染优化、Web 加载和渲染原理
一.资源传输优化 使用压缩 Gzip,如下所示: 对传输资源进行体积压缩,可高达 90% 配置 Nginx 启用 Gzip 启用 Keep Alive,如下所示: 一个持久的 TCP 连接,节省了连接 ...
- Apollo配置中心热加载mysql_Apollo配置中心介绍
1.What is Apollo 1.1 背景 随着程序功能的日益复杂,程序的配置日益增多:各种功能的开关.参数的配置.服务器的地址-- 对程序配置的期望值也越来越高:配置修改后实时生效,灰度发布,分 ...
- 海思涵科技WIFI认证服务器不在线,在海思平台外加一个usb wifi模块,mt7601 加载ok,配置网络ok,但不能ping通?...
请教下:我用mt7601 usb wifi模块 加载驱动 配置网络后经常打印 PeerBeaconAtJoinAction(): Set CentralChannel=1 PeerBeaconAtJo ...
- Flutter 实现根据环境加载不同配置
之前做后端开发的时候,不管是什么语言或者框架,都习惯根据不同环境加载不同的开发配置,比如本地开发的时候,加载local.env配置,部署开发环境的时候加载develop.env配置,通常通过一个环境变 ...
- springboot 启动分析【难点】——如何自动扫描 @SpringBootApplication||如何加载自动配置类 @EnableAutoConfiguration||如何加载前端控制器
springboot 启动分析[难点] 自动扫描的特点 默认扫描与 启动类 同级的所有包及其子包都可以自动扫描 如果不可要使用@ComponentScan(basePackage={"&qu ...
最新文章
- Windows系统下制作一个记事本以语音方式读出你输入的文字 以及放到开机启动项,开机自启动读出语音!
- CI框架json无法Unicode转中文解决方案
- 解决方案 | python安装wordfreq库
- 需求调研报告模板_2020年工业软管行业深度市场调研及投资策略建议报告-液体化学品增加对其需求...
- Java二叉搜索树转循环链表,关于java:二叉搜索树转换为单向链表interview1712
- logstash filter 处理json数据按原始数据字段数据存储
- 剑指offer面试题[21]包含min函数的栈
- 【正点原子MP157连载】第四十四章Linux SPI总线框架-摘自【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7
- Altium Designer使用-----智能pdf输出装配图
- 尾矿库监测 GNSS北斗高精度定位终端机应用
- <论文阅读> M2BEV Multi-Camera Joint 3D Detection and Segmentation with Unified Bird’s-Eye View Represen
- 移动APP测试中的功能与非功能测试
- 显卡天梯图2020年10月完整版
- 分享篇:第十届“泰迪杯”数据挖掘挑战赛-农田害虫图像识别(特等奖)一
- tecplot选择变量
- SVN解决冲突的几种情况
- 电磁场与电磁波:法拉第电磁感应定律,高斯定律的高斯定律
- Arrays.copyOf方法
- FFN -> GLU -> GAU
- 信托资金将分辨用于向邢台依林山庄食物有限公司、唐山国泰纸业有限公司、唐山蓝猫饮品团体有限公司发放流动资金贷款1亿、1.5亿、1亿
热门文章
- c语言链表萌新,萌新一枚,关于链表问题求大佬解答
- 会不会导致内存泄漏_可能会导致.NET内存泄露的8种行为
- Win7 路由上网DNS服务器ping不通的解决方法
- 给Win7光盘添加PE3.0
- 2个红外传感器循迹原理_红外线光学气体浓度传感器作用原理
- 在php中页面布局 3列左右侧固定中间自适应居中,css三列布局--两边固定中间自适应和中间固定两边自适应...
- octave安装 缺java_Octave信号包安装
- html表单提交前验证,jquery表单提交前实现同步验证(附代码)
- linux 音频文件播放文件管理,linux dsp 播放音频文件
- python 画图设置横纵坐标_Python输出高质量论文图片