九、job触发流程

1. val lines = sc.textFile()

可以从HDFS、本地文件系统、或者任何Hadoop支持的文件系统中读取文件。返回的是一个字符串的RDD。

  /**
   * Read a text file from HDFS, a local file system (available on all nodes), or any
   * Hadoop-supported file system URI, and return it as an RDD of Strings.
   * @param path path to the text file on a supported file system
   * @param minPartitions suggested minimum number of partitions for the resulting RDD
   * @return RDD of lines of the text file
   */
  def textFile(
      path: String,
      minPartitions: Int = defaultMinPartitions): RDD[String] = withScope {
    assertNotStopped()
    hadoopFile(path, classOf[TextInputFormat], classOf[LongWritable], classOf[Text],
      minPartitions).map(pair => pair._2.toString).setName(path)
  }

minPartitions是一个有默认值的参数。

haddoopFile返回的是一个HadoopRDD,其中的元素,其实是(key, value) pair,key是hdfs或文本文件的每一行的offset,value是文本行。然后对Hadoop调用map方法,会剔除掉key,只保留value,然后会获取到一个MapPartitionsRDD。MapPartitionsRDD内部的元素,就是一行一行的文本行。

class HadoopRDD[K, V](
    sc: SparkContext,
    broadcastedConf: Broadcast[SerializableConfiguration],
    initLocalJobConfFuncOpt: Option[JobConf => Unit],
    inputFormatClass: Class[_ <: InputFormat[K, V]],
    keyClass: Class[K],
    valueClass: Class[V],
    minPartitions: Int)
  extends RDD[(K, V)](sc, Nil) with Logging {
  // RDD.scala
  /**
   * Return a new RDD by applying a function to all elements of this RDD.
   */
  def map[U: ClassTag](f: T => U): RDD[U] = withScope {
    val cleanF = sc.clean(f)
    // MapPartitionsRDD
    new MapPartitionsRDD[U, T](this, (context, pid, iter) => iter.map(cleanF))
  }

2. val words = lines.flatMap(line => line.split(" "))

  // RDD.scala
  /**
   *  Return a new RDD by first applying a function to all elements of this
   *  RDD, and then flattening the results.
   */
  def flatMap[U: ClassTag](f: T => TraversableOnce[U]): RDD[U] = withScope {
    val cleanF = sc.clean(f)
    // 返回MapPartitionsRDD
    new MapPartitionsRDD[U, T](this, (context, pid, iter) => iter.flatMap(cleanF))
  }

3. val pairs = words.map(word => (word, 1))

    RDD map,同上。

4. val counts = pairs.reduceByKey(_ + _)

其实RDD里是没有reduceByKey的,因此对RDD调用reduceByKey()方法的时候,会触发scala的隐式转换;此时就会在作用域内,寻找隐式转换,会在RDD中找到rddToPairRDDFunctions()隐式转换,然后将RDD转换为PairRDDFunctions。

  // The following implicit functions were in SparkContext before 1.3 and users had to
  // `import SparkContext._` to enable them. Now we move them here to make the compiler find
  // them automatically. However, we still keep the old functions in SparkContext for backward
  // compatibility and forward to the following functions directly.

  implicit def rddToPairRDDFunctions[K, V](rdd: RDD[(K, V)])
    (implicit kt: ClassTag[K], vt: ClassTag[V], ord: Ordering[K] = null): PairRDDFunctions[K, V] = {
    new PairRDDFunctions(rdd) //转换为了PairRDDFunctions
  }
  // PairRDDFunctions.scala
  /**
   * Merge the values for each key using an associative and commutative reduce function. This will
   * also perform the merging locally on each mapper before sending results to a reducer, similarly
   * to a "combiner" in MapReduce.
   */
  def reduceByKey(partitioner: Partitioner, func: (V, V) => V): RDD[(K, V)] = self.withScope {
    combineByKeyWithClassTag[V]((v: V) => v, func, func, partitioner)
  }

reduceByKey会在发送结果前在本地预先合并,这会减少网络上数据的传送量,提高性能。

5. counts.foreach(count => println(count._1 + ": " + count._2))

  /**
   * Applies a function f to all elements of this RDD.
   */
  def foreach(f: T => Unit): Unit = withScope {
    val cleanF = sc.clean(f)
    sc.runJob(this, (iter: Iterator[T]) => iter.foreach(cleanF))
  }

action RDD,开始调用runJob,启动job。

经过多次嵌套调用,最终调用dagScheduler的runJob方法,由dagScheduler启动job。

  /**
   * Run a function on a given set of partitions in an RDD and pass the results to the given
   * handler function. This is the main entry point for all actions in Spark.
   *
   * @param rdd target RDD to run tasks on
   * @param func a function to run on each partition of the RDD
   * @param partitions set of partitions to run on; some jobs may not want to compute on all
   * partitions of the target RDD, e.g. for operations like `first()`
   * @param resultHandler callback to pass each result to
   */
  def runJob[T, U: ClassTag](
      rdd: RDD[T],
      func: (TaskContext, Iterator[T]) => U,
      partitions: Seq[Int],
      resultHandler: (Int, U) => Unit): Unit = {
    if (stopped.get()) {
      throw new IllegalStateException("SparkContext has been shutdown")
    }
    val callSite = getCallSite
    val cleanedFunc = clean(func)
    logInfo("Starting job: " + callSite.shortForm)
    if (conf.getBoolean("spark.logLineage", false)) {
      logInfo("RDD's recursive dependencies:\n" + rdd.toDebugString)
    }
    // 由dagScheduler启动job
    dagScheduler.runJob(rdd, cleanedFunc, partitions, callSite, resultHandler, localProperties.get)
    progressBar.foreach(_.finishAll())
    rdd.doCheckpoint()
  }

 

<think>嗯,用户想配置Jenkins使用钉钉作为触发器来启动Job。首先,我需要回忆一下Jenkins的触发机制。通常,Jenkins可以通过Webhook、定时任务、或者其他事件触发构建。钉钉作为通讯工具,本身可能没有直接的触发器,但可以通过钉钉机器人或者API结合Jenkins的插件来实现。 根据用户提供的引用内容,特别是引用[3]和[4],他们提到了使用钉钉插件和通过代码调用钉钉机器人的接口。可能的步骤包括安装钉钉插件,配置机器人,设置Webhook,以及可能的后置脚本。过用户的需求是触发器,也就是钉钉的事件触发Jenkins Job,而是构建后的通知。 可能需要考虑使用钉钉的Outgoing机器人,当钉钉收到消息时,发送请求到Jenkins的API触发构建。或者,使用Jenkins的Generic Webhook Trigger插件,让钉钉机器人发送请求到Jenkins的指定URL来触发Job。 另外,引用[5]提到配置Git凭据,这可能和拉取代码有关,但用户的问题是关于触发器,所以可能需要这部分。需要确保Jenkins能够接收来自钉钉的HTTP请求,可能需要设置安全措施,比如Token验证。 总结步骤可能包括:在钉钉创建自定义机器人获取Webhook URL,在Jenkins安装插件如Generic Webhook Trigger,配置Job接收Webhook请求,处理参数和安全性。然后测试通过钉钉发送消息触发构建。</think>### 配置Jenkins使用钉钉作为触发启动Job的步骤 #### 1. **安装钉钉插件** - 进入Jenkins管理界面,选择「系统管理 -> 插件管理 -> 可选插件」,搜索并安装「DingTalk」插件[^3]。 - 安装完成后,重启Jenkins服务。 #### 2. **配置钉钉机器人** - 在钉钉群中创建自定义机器人,获取机器人的`Webhook URL`和`Access Token`[^3][^4]。 - 在Jenkins中进入「系统管理 -> 系统配置」,找到钉钉机器人配置项,填写`Webhook URL`和`Access Token`。 #### 3. **设置Jenkins Job触发器** - 打开需要配置的Job,进入「配置」页面。 - 在「构建触发器」部分,选择「触发远程构建」,生成一个`身份验证令牌`(例如`12345`)[^3]。 - 记录触发URL,格式为: $$JENKINS\_URL/job/[Job名称]/build?token=[身份验证令牌]$$ 例如:`http://jenkins.example.com/job/test-job/build?token=12345`。 #### 4. **配置钉钉机器人发送触发请求** - 通过钉钉机器人的Outgoing功能(需开启自定义关键词),当用户发送特定指令(如`#build`)时,触发HTTP请求到上述Jenkins URL[^4]。 - 示例钉钉机器人代码片段(Python): ```python from dingtalkchatbot.chatbot import DingTalkChatbot import requests def send_jenkins_trigger(): webhook = 'https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN' jenkins_url = 'http://jenkins.example.com/job/test-job/build?token=12345' requests.get(jenkins_url) # 发送GET请求触发构建 ``` #### 5. **验证安全性** - 建议在Jenkins中配置IP白名单或使用Token验证,防止未授权触发[^4]。 - 在钉钉机器人设置中启用「加签」或「自定义关键词」提升安全性。 #### 6. **测试触发流程** - 在钉钉群中发送指令(如`#build`),观察Jenkins Job是否自动启动。 - 检查构建日志确认触发来源是否为钉钉请求。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值