这几天遇到了需要从hdfs加载json字符串,然后转化成json对象的场景。刚开始的实现方式见如下代码:
- val loginLogRDD = sc.objectFile[String](loginFile, loadLoginFilePartitionNum)
- .filter(jsonString => {
-
-
- val json = JSON.parseFull(jsonString)
- val resultJson = json match {
- case Some(map: Map[String, Any]) => if (map.get("ip").getOrElse("").equals("")) false else true
- case None => false
- }
- resultJson
- }).
从以上代码可知,每条Json记录,都会创建Json解析器来进行解析。
这种方式加载速度特别慢,1s大概才1M左右,并且CPU也特别忙。因此推测是Spark程序有问题导致的。
为了提高记载速度,决定采用mapPartitions方式加载Json串,也就是每个分区只创建一个Json解析器,代码如下:
- val loginLogRDD = sc.objectFile[String](loginFile, loadLoginFilePartitionNum)
- .mapPartitions(jsonStringIter=>{
- val mapper = new ObjectMapper()
- mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
- mapper.registerModule(DefaultScalaModule)
- jsonStringIter.map(record => {
- try {
- Some(mapper.readValue(record, classOf[JsonLoginRecord]))
- } catch {
- case e: Exception => None
- }
-
- })
- })
修改之后,每秒加载速度达到了100多兆,速度提高了100多倍,效果截图如下:
