spark-streaming任务提交遇到的坑
一、背景
基本所有公司互联网公司都会有离线和实时任务,达到实时的目的手段据个人了解有storm、spark-streaming、flink。今天来探讨一下spark-streaming任务的开发到上线过程中遇到的问题。
公司领导最近提了一个实时展示用户、产品各方面统计数据的需求,对于数据埋点需要有一套针对性的计划。因此需要我们大数据平台对数据进行实时接收、清洗、导入....的内容。详细内容不再介绍。下面介绍在开发中spark on yarn遇到的坑。
二、代码坑
1.maven项目中,resource目录是一个classpath目录,配置文件所在地
通过ConfigFactory.load("application.properties")来获取properties的配置信息,比如application.properties和log4j.propertoes
logger = LoggerFactory.getLogger(this.getClass)来获取logger
2.case class样例类
特点有:不用new;toString漂亮;实现了hashcode和equal;可用case匹配;默认可序列化等
所以如果只是用来保存一个具有多个属性的对象,那再好不过了
3.结果批量插入batch
conn.setAutoCommit(false)
一个循环ps.addBatch()
一个ps.executeBatch()
conn.commit()
注意,insert update delete操作不能用executeQuery(),只能是select是query
4.数据库连接池
虽然设置上都差不多,但是实现上还需要更加格式化的代码,每次调用,都是先获取连接池,再获取connection
还有一点关键就是分布式运行时,数据库连接池需要是一个class 而不是一个object否则将会在每一台worker上都会建立一个数据库连接池
5.StreamingContext中含有SparkContext函数来获取sc,所以不用再去创建sc
但是需要注意,在整个spark代码中无论是sc还是ssc还是sqlContext都不能调用.stop()方法,不然会中值进程
注意:别忘了调用ssc.start()
6.动态创建对象
Class.forName().newInstance().asInstanceOf[]通过这种方式可以有选择的创建对应的类的对象
7.rdd.collect()
返回的是一个数组Array,注意:rdd的lazy性质
8.@volatile
该注解表示该变量的修改代码不能被进行执行顺序优化,以及修改引用即时性,但是不保证同步安全性。同步的三个特性保证两个,安全性实际上并不需要,因为@volatile的目的是我修改你即时查看,并不是多线程多并发的共同修改
9.Option[Type]
功能太强大,Option的子类有Some()和None,表示尽可能返回给你你想要的,如果存在那么结果就在Some(....)中的....。...就是结果,如果不存在就返回None,所以很多时候的用法是匹配:
def show(x: Option[String]) = x match {
case Some(s) => s
case None => "?"
}
存在的话怎么样,不存在的话怎么样
11.正则方法
"""(\d+\.\d+\.\d+\.\d+).*?logger.php\?(.*?) HTTP.*""".r,用””.r表示正则对象
也可以用 new Regex(....)的方法
有方法如下findAllIn;findFirstIn;findPrefixOf;replaceFirstIn,replaceAllIn.
我想说的是另外一个关于分组的问题()
python中是.group(index)
scala中是直接val regexobject(变量1,变量2,...) = “字符串”
其中变量1 2就是正则中()所包含的分组
val logRegex(ip, query) = logStr这个例子就是吧logStr用logRegex匹配,把(\d+\.\d+\.\d+\.\d+)作为ip变量的值,把(.*?)作为query变量的值。,一口气定义并初始化两个变量
三、分布式任务的坑
1.签名问题
引入的各种包存在签名,当submit执行的时候会不信任!!!,所以需要删除jar包中的文件zip -d ***.jar 'META-INF/*DSA' 'META-INF/*.RSA' 'META-INF/*SF'
2.读取文件问题
在程序中除了配置文件还有一个文件用来把ip解析成城市信息,但是每次提交上去之后发现读取这个文件失败,根本找不到这个文件,但是jar包中确实是存在的!!!
这就是一个分布式运行的问题,如果在本地没问题,放在classpath中或者绝对路径都可以,此时说一下到底那些代码是是appmaster中执行,那些代码在worker中执行。
:main中开始到rdd操作之前
:从rdd操作开始到结束
可以看出,我们最好是把需要共享的信息在rdd操作之前读入然后传入rdd的应用函数参数中
3.数据共享、变量共享
当然这个问题的根本原因还是appmaster和worker的分布式运行原因。
问题一:object和class的问题,object是一个静态的东西,可以人为object在每台机器上都是一个对象,而且各不相同!一定要注意,但是如果我们在appmaster中创建一个class的对象,在worker中调用这个对象的属性,那么这个属性不是多个,而是唯一的一个!!!!!!!!!!!!!!!!!!!!!!!!!!!
所以我们不能通过在object中定义大家都需要的变量!
问题二:序列化问题。当我使用class来共享数据以及变量的时候,报错task can not seriablzable.........,问题在于serializable的class条件是类中的类变量都是可以序列化的!!!!请自行检查。
本文仅仅是列出了出现的问题以及解决办法,具体问题的详细解析后续文章中介绍。