Spark加载外部配置文件

--files path启动加载配置文件

在spark-streaming程序中需要配置文件中的数据来完成某项统计时,需要把配置文件打到工程里,maven的配置如下:

    <build>  
         <plugins>  
             <plugin>  
                 <groupId>org.apache.maven.plugins</groupId>  
                 <artifactId>maven-surefire-plugin</artifactId>  
                 <configuration>  
                     <skip>true</skip>  
                 </configuration>  
             </plugin>  
         </plugins>  
         <resources>  
             <resource>  
                 <directory>src/main/resources</directory>  
                 <includes>  
                     <include>**/*.txt</include>  
                     <include>*.txt</include>  
                 </includes>  
                 <filtering>true</filtering>  
             </resource>  
         </resources>  
    </build>  

这样在local模式下运行时没问题的,但是要放在yarn集群上就会出问题,需要用如下方式来调用:

spark-submit --class com.kingsoft.server.KssNodeStreaming 
--master yarn-cluster 
--driver-memory 2G 
--executor-memory 5G 
--num-executors 10 
--jars /home/hadoop/spark-streaming-flume_2.10-1.0.1.jar,/home/hadoop/avro-ipc-1.7.5-cdh5.1.0.jar,/home/hadoop/flume-ng-sdk-1.5.0.1.jar,/home/hadoop/fastjson-1.1.41.jar 
--files /home/hadoop/idc_ip.txt,/home/hadoop/ipdata.txt 
/home/hadoop/SparkStreaming-0.0.1-SNAPSHOT.jar 
0.0.0.0 
58006

Spark中addFile加载配置文件

      我们在使用Spark的时候有时候需要将一些数据分发到计算节点中。一种方法是将这些文件上传到HDFS上,然后计算节点从HDFS上获取这些数据。当然我们也可以使用addFile函数来分发这些文件。注意,如果是spark程序通过yarn集群上加载配置文件,path必须是集群hdfs的绝对路径,如:viewfs://58-cluster//home/hdp_lbg_supin/resultdata/zhaopin/recommend/config/redis.properties。

addFile

  addFile方法可以接收本地文件(或者HDFS上的文件),甚至是文件夹(如果是文件夹,必须是HDFS路径),然后Spark的Driver和Exector可以通过SparkFiles.get()方法来获取文件的绝对路径(Get the absolute path of a file added through SparkContext.addFile()),addFile的函数原型如下:

def addFile(path: String): Unit
def addFile(path: String, recursive: Boolean): Unit

      addFile把添加的本地文件传送给所有的Worker,这样能够保证在每个Worker上正确访问到文件。另外,Worker会把文件放在临时目录下。因此,比较适合用于文件比较小,计算比较复杂的场景。如果文件比较大,网络传送的消耗时间也会增长。

      path:可以是local、hdfs(任何hadoop支持的文件系统)、HTTP、HTTPS、FTP等。local方式时,在windows下使用绝对路径时需要加个“/”,如“d:/iteblog.data”得写成“/d:/iteblog.data”或“file:///d:/iteblog.data”。

   recursive:如果path是一个目录,那么我们可以设置recursive为true,这样Spark会递归地分发这个路径下面的所有文件到计算节点的临时目录。

   通过SparkFiles.get(path:String)获取添加的文件路径。

var path = "/user/iteblog/ip.txt"
sc.addFile(path)
val rdd = sc.textFile(SparkFiles.get(path))

      上面的实例展示了如何在Driver中获取分发出去的文件,我们还可以在Exector获取到分发的文件:

var path = "/user/iteblog/ip.txt"
sc.addFile(path)
val rdd = sc.parallelize((0 to 10))
rdd.foreach{ index =>
    val path = SparkFiles.get(path)
    ......
}
      如果我们添加的是压缩文件,比如 .tar.gz.tgz或者 .tar,Spark会调用Linux的解压缩命令 tar去解压缩这些文件。

addJar

  addJar添加在这个SparkContext实例运行的作业所依赖的jar。,其函数原型如下:

def addJar(path: String)
      path:可以是本地文件(local file)、HDFS文件(其他所有的Hadoop支持的文件系统也可以)、HTTP、 HTTPS 或者是FTP URI文件等等。

   其实Spark内部通过spark.jars参数以及spark.yarn.dist.jars函数传进去的Jar都是通过这个函数分发到Task的。


将配置文件打到工程jar包里

      注意:IntelliJ IDEA创建Maven项目时,必须是Java项目,否则不能将配置文件打到工程jar包。

      redis.properties配置文件示例如下:

redis.host=xx.xx.xxx.x
redis.port=6380
redis.password=6f3d16c5119bb946
redis.maxActive=500
redis.maxWait=10000
redis.maxidle=500
redis.minidle=10
redis.maxtotal=500
      RedisClient.scala加载配置文件示例如下:

package com.bj58.adsp.dp.files.redis

import java.io.{InputStream, BufferedInputStream, FileInputStream}
import java.util.Properties

import org.apache.commons.pool2.impl.GenericObjectPoolConfig
import redis.clients.jedis.JedisPool
import scala.collection.JavaConversions._

/**
 * Created by Administrator on 2015/10/23.
 */
object RedisClient extends Serializable {
  
  val properties: Properties = new Properties
  val in: InputStream = getClass.getResourceAsStream("/redis.properties")
  properties.load(new BufferedInputStream(in))
  val redisHost = properties.getProperty("redis.host")
  val redisPort = properties.getProperty("redis.port")
  val redisPwd = properties.getProperty("redis.password")
  val redisTimeout = 30000
  val config = new GenericObjectPoolConfig()
  config.setTestOnBorrow(true)
  config.setMaxIdle(properties.getProperty("redis.maxidle").toInt)
  config.setMinIdle(properties.getProperty("redis.minidle").toInt)
  config.setMaxTotal(properties.getProperty("redis.maxtotal").toInt)
  
  lazy val pool = new JedisPool(config, redisHost, redisPort.toInt, redisTimeout, redisPwd)

  lazy val hook = new Thread {
    override def run = {
      println("Execute hook thread: " + this)
      pool.destroy()
    }
  }
  sys.addShutdownHook(hook.run)
}

      如果是读取配置文件内容,可以直接:

val properties: Properties = new Properties
val in: InputStream = getClass.getResourceAsStream("/redis.properties")
properties.load(new BufferedInputStream(in))
      如果是只加载配置文件,可以直接:

public static RedisClient init() {
   RedisClient client = null;
   try {
      // 根据配置文件初始化Redis客户端
      client = RedisClient.getInstance(getClass.getResource("/redis.properties"));
   } catch (Exception e) {
      e.printStackTrace();
   }
   return client;
}

直接将配置文件内容写到程序中

示例如下:

lines.foreachRDD(rdd => {
  //embedded function
  def func(records: Iterator[String]) {
	var conn: Connection = null
	var stmt: PreparedStatement = null
	try {
	  val url = "jdbc:mysql://xx.xxx.xx.xxx:3307/supindb"
	  val user = "root"
	  val password = "root"
	  conn = DriverManager.getConnection(url, user, password)
	  records.flatMap(_.split(" ")).foreach(word => {
		val sql = "insert into mytable(word) values(?)"
		stmt = conn.prepareStatement(sql)
		stmt.setString(1, word)
		stmt.executeUpdate()
	  })
	} catch {
	  case e: Exception => e.printStackTrace()
	} finally {
	  if (stmt != null) {
		stmt.close()
	  }
	  if (conn != null) {
		conn.close()
	  }
	}
  }

  val repartitionedRDD = rdd.repartition(4)
  repartitionedRDD.foreachPartition(func)
})

使用addFile("__app__.jar")方式

      如果程序中调用其他服务,而其他服务需要加载配置文件,则可以将程序打成jar包,并命名为__app__.jar,使用sc.addFile("__app__.jar")方式即可。


Refer:

http://blog.csdn.net/aaa1117a8w5s6d/article/details/43090017

http://www.iteblog.com/archives/1704

  • 7
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值