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条件是类中的类变量都是可以序列化的!!!!请自行检查。

 

本文仅仅是列出了出现的问题以及解决办法,具体问题的详细解析后续文章中介绍。