开发者学堂课程【2020版大数据实战项目之DMP广告系统(第四阶段):框架搭建_配置文件工具类编写】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/679/detail/11801
框架搭建_配置文件工具类编写
内容介绍:
一、代码
二、为 spark session 添加一个方法
三、添加内容配置
四、判断配置来源
一、代码
Package cn.itcast.utils
Import org.apache.sql.sparksession
Class sparkconfighelper(builder:sparksession.builder){
Def loadconfig():sparksession.builder={
//builder.option(...).option(...)
}
}
Object sparkconfighelper{
//一:为 sparksession 添加一个方法
//使用隐式转换,将 sparksession -> sparkconfighelper
Implicit def sparktohelper():sparkconfighelper={
}
Def main(args:array[string]):unit={
Val spark = sparksession.bulider()
.appname(name=
”
...
”
)
.master(master=
”
...
”
)
.loadconfig()
.getorcreat()
二、为 spark session 添加一个方法
已经介绍过配置文件工具类编写的大致思路,接下来把它分为两步编写,首先第一步,要先去做一件事情,为 spark session 添加一个方法。第二步,加载配置文件。这两步都很重要,第一步是比较难的,第二步也不简单,还是克服一下。进入到 idea 当中,第一步,在 usual 当中创建新的 scarlet class ,命名为 spark conflict 接下来,类创建出来了。
伴生对象可以直接 object ,提供 spark configure help 这样的对象。要在后面写 main 方法。 main 方法要写在 object 里。整体的架子就已经写完了。
第一步为 spark session 添加方法。怎么去添加一个方法,要使用隐式转换,将 spark session 类转为 spark Conflict helper 的类。一步一步说,大家注意一下,现在理想的调用方式,就是要创建出来一个 spark 对象。这个 spark 对象要通过 spark session 去创建出来。spark session c创建先 import 一下,然后要去创建 builder 然后设置 APP name , APP name 就随便写,接下来,还要再设置 Master 也随便写。问大家一个问题,这个方法现在是没有的,能不能在 spark help 里编写一个方法,叫做 load config 直接去把这个方法写完。假如说把 master 返回的对象,转为 spark conflict helper 的对象,那么就可以调用 load config ,可以去编写一个implicit def ,创建一个方法,叫做 Spark to helper ,这个方法里接收什么对象不知道,应该返回 sparkconfighelper 的对象, sparkconfighelper 当中,应该要提供出来 spark session 对象,让他进行设置,隐式转换写到这一步。
接下来要把 master 返回对象转为sparkconfighelper 的对象,我们要知道 master 对象是什么,大家能发现它是 spark Builder 的对象类型,应该来一个 builder 让他接收,类型是 position builder ,后面就可以写get Load config ,还是不太对,大家发现 get or create 没有了,为什么没有呢?因为 load config 的对象,应该给它添加一个返回值,这个返回值应该是 builder ,现在报红线,没关系我们先给它放在这。
把 sparksession.builder 去掉, spark 现在是一个 spark session 对象,转换的时候还一个红线,没有返回任何内容出来,隐式转换函数,应该创建 sparkconfighelper 的对象。 spark config helper 当中, log config 方法是 Builder当中去添加一些内容。 builder 是往其中添加 option ,设置多个 option ,那么 option 怎么去调用, builder 对象才可以。所以,添加一个主构造,把 builder 对象给它整下来,那么 builder 对象,就命名为叫做 spark session builder , loud conflict 当中就可以工作了,我们第一步,也就是为 spark session 添加方法, Load conflict 的方法,就结束了。
Class sparkconfighelper(builder:sparksession.builder){
Val config=configfactory.load(resourcebasename =
“
spark
”
)
Def loadconfig():sparksession.builder={
//builder.option(...).option(...)
//二 :为 builder 添加配置
//问题:配置文件的修改,如果直接按照 key 读取配置文件,会出现配置文件修改,代码也要跟着修改的问题
//解决方案:自动的访问配置文件,加载其中所有内容
//1.获取所有的 config 中的键值对
//2.遍历键值对
//3.获取其中所有的 key ,和所有的 value
//4.设置给builder
}
三、添加内容配置
如何去添加配置。先把核心问题说一下, spark conf 文件有可能改。比如说添加新的配置,这是有可能的。那么再添加新的配置,很多地方都要去改,首先拿到 builder ,通过 builder 设置 confinger 的时候,第一步,应该在这创建一个新的东西,叫confinge 通过 config factory 创建出来,可以直接 load spark 加载 spark.conf ,拿到 config 以后,往 builder 当中设置第一个内容,拷贝一下 Spark worker timeout ,接下来再去通过 conflict ,把内容传进来,再进行 conflict 的设置。
那么是第二个参数,叫做 spark rpc time ask time out 通过 conflict get string ,传入 RPC time out ,为 builder 当中设置了两个config 。假设说现在文件当中只有两个 config ,某一天添加了第三个 config ,要复制一下配到这呢,再去添加一下,那么以后你每次添加一个配置的时候,或者删除一个配置的时候,都要来这个类当中去删掉,或者增加一个新的 config ,这种方式不好。
问题配置文件的修改,默认情况下如果直接读取配置,可以按照 key 读取配置文件,会出现配置文件修改,代码也要跟着修改的问题,这样会比较容易产生问题,比如说哪天删错了,或者加错了,都会造成一些混乱,为了避免这种问题,应该让它变为自动的。解决方案是,自动的访问配置文件,加载其中所有内容,那怎么去设置这个自动的这个方案呢?第一步,获取所有 conflict 中的键值对,配置文件当中写的是一个 Key 对应一个 value ,应该获取到所有的键值对,这是第一步。第二步我们获取到键值对然后遍历键值对。
//1.获取所有的 config 中的键值对
Import scala.collection.javaconverters._
Val entryset = config.entryset().asscala
//2.遍历键值对
For(entry <- entryset){
//3.获取其中所有的 key ,和所有的 value
Val key = entry.getkey
Val value = entry.getvalue
//4.设置给builder
Builder.config(key,value)
第三步获取其中所有的 Key 和所有的 value ,第四步设置 builder ,返回 builder,工作就完成了。我们先来看第一步,获取到 entryset 就是所有的键值对,通过 Config.entryset 去获取。但是这个方法点开以后,大家发现这是 Java 类,拿 Java 的操作肯定不是那么舒服的,把返回的 Java 转为 scala ,怎么转?要导入一个新的工具,工具叫做 scala ,这样就把 entryset 返回的 Java 给它转为 scala 。我们第二步是遍历键值对, for entry ,从 entryset 当中遍历键值对,这时就获取到了 entry 。应该获取其中的所有 Key 和所有 value , Key 怎么获取呢?通过 entry.getkey 就获取到了,再通过 entry.getvalue 就获取到 value了。 Entry 其实就是一个元组,就是一个键值对。 key value 设置过了以后呢,就可以把 key value 设置给 builder 了。这样就非常简单了,第四步设置给 builder 。那么可以通过 builder.config ,传入 Key ,传入 value 。
Val value = entry.getvalue.unwrapped().asinstanceof[string]
在最外层把 builder 返回出去,整个功能就搞定了。我们看一看报错。首先他说不是这个 value ,类型是不对的,那翻译我们看到,他是叫做 config value ,这样的类型, Key 是一个 string 类型,所以 key 没有问题,但 value有问题,先把 config value 删掉,有一个方法通过 unwrapped 方法,可以把 config value 那么我们知道在配置文件当中所写的所有东西都是字符串,所以在获取到 anyref 的时候,肯定是不服气了,如果明明是字符串,给 anyref 不知道在做什么。那么应该把它 asinstanceof 这个时候不报错了。在设置之前,要 print ln 一下,看一看 Key 和 value 对应的内容。
那么就运行一下,刚才修改了两个东西,第一个东西就是 new sparkconfighelper(bulider) ,大家要记得写 new 。然后还有一个 master(master=”local[6]”),把 APP name改成了 test 。就是刚才做的小修改,大家注意一下。代码运行是没有问题的。往上找大家会发现好多配置,但不是自己设置的配置。
首先 Java specification.name这不是我设的,这是 java平台名字,如果你看不懂的话没关系。 user.dir 这是环境信息,我们加载出来了什么,现在是把所有的 config 的内容全都给它加载出来了,但是 config entryset 当中包含了一大堆系统级别的配置,系统级别的环境变量,这些东西没有用,不要设置给 builder 。所以只能再去做一些判断。
四、判断配置来源
//判断:判断配置来源
Val origin:configorigin=entry.getvalue.origin().filename()
其实思路比较简单,这个判断是额外加的一点,要判断的是键值对配置来源,怎么判断这个来源呢?先命名一个 origin ,然后直接拿 Entry 看到其中的 origin 。其实里面包含了 origin ,也可以直接调用 origin ,就返回了一个来源,要 origin 对象似乎没有用,其实想要的是它来源于哪个文件,如果是系统的环境变量的话,它应该不来源于任何文件,所以.get filename()
//判断:判断配置来源
Val origin:configorigin=entry.getvalue.origin().filename()
If(stringutils.isnotblank(origin)){
//4.设置给builder
Builder.config(key,value)
拿到 filename 以后 origin 是 string ,就可以 If (stringutils. isnotblank(origin)){ 这个类,前面跟大家介绍过了,如果 origin 文件名是空的话,就说明这不是我们要的。如果你要想判断它不为空,可以在前面加一个感叹号,这是一种办法。还有一种办法呢,是你直接选为 isnotblank ,这个时候,就基本上搞定。接下来再去运行一下代码。
里面其实都是我们所写的配置,所以说明我们的配置文件加载是没有任何问题的,接下来,就可以把 print 给去掉,把 builder 打开,把 key value 设置进去,整个功能就完成了。接下来总结一下,首先第一步,为 spark builder 对象添加一个方法,叫做loadconfig ,其实是通过隐式转换做到的。
将 Action 对象转为 spark config helper ,写一个方法来接收 builder ,返回 sport config helper ,如果在运行环境当中有 object ,这个隐式转换就会自动被应用,调到 master 就可以直接调 load config 的方法,其实就是 spark config helper 的方法,第一步就是获取到所有的键值对,但是键值对有可能是包含 Java 环境的一些变量,这个时候要拿到对应 entry ,拿到 key value 判断其来源,设置给 builder 返回,我们整个功能就完成了。