1 .KafkaUtils.createDirectStream[ 这四个泛型:k就是topic,v就是topic对应的内容从kafk
Kd (解码器)vd(解码器)] 这个方法是在各个分区没有偏移量时的用的。
后面的参数是(ssc,kafkaparam,topics)是怎么回事,尤其是kafkaparam这个参数???
答:我们直接KafkaUtils.createDirectStream【string,string,stringDecoder,stringDecoder】(ssc,kafkaParams,tpics),map(_._2) 就得到了v(从kafka中读取的数据)
Kafkaparam=map((“metadata.broker.list”,”kafka1:9092”),( “metadata.broker.list”,”kafka2:9092”)) 这个参数就是kafka的节点的集合。
createDirectStream【string,string,stringDecoder,stringDecoder】中第一个String是topic的类型,第二个是topic中的内容类型,第三个,第四个是前两的解码器。这个写法是固定的,记住记性
map(_._2) 为什么是_2,因为我们要取的就是topic中的内容啊。
我们得到的就是Dstream类型的东东,就可以直接操作了
1,2直连(手动控制偏移量)的详细过程和代码
先介绍一下直连的方法,和上面的有所不同啊 defcreateDirectStream[K, V, KD <: Decoder[K], VD <: Decoder[V], R] (ssc: StreamingContext, kafkaParams: Map[String, String], fromOffsets: Map[TopicAndPartition, Long], messageHandler: (MessageAndMetadata[K, V])⇒ R)(implicit arg0: ClassTag[K], arg1: ClassTag[V], arg2: ClassTag[KD], arg3: ClassTag[VD], arg4: ClassTag[R]): InputDStream[R]
K type of Kafka message key V type of Kafka message value K type of Kafka message key decoder VD type of Kafka message value decoder R type returned by messageHandler Ssc StreamingContext object kafkaParams Kafka configuration parameters. Requires "metadata.broker.list" or "bootstrap.servers" to be set with Kafka broker(s) (NOT zookeeper servers) specified in host1:port1,host2:port2 form. fromOffsets Per-topic/partition Kafka offsets defining the (inclusive) starting point of the stream messageHandler Function for translating each message and metadata into the desired type returns DStream of R
|
解释一下:fromOffsets Per-topic/partition Kafka offsets defining the (inclusive) starting point of the stream 类型:fromOffsets: Map[TopicAndPartition, Long], 1、 Val brokerlist=”kafla1:9092,kakfa2:9092,kafka3:9092” Val groupId=”1705” topic=”test3” Val zkList=”hadoop1:2181,hdoop2:2181” #等取出来的偏移量存放的集合fromOffsets: Map[TopicAndPartition, Long], Val fromOffsets = Map() 2、各分区,从哪开始读取数据,偏移量来自zookeeper,所以我们需要创建一个目录,这个目录就是zookeeper里面用来保存偏移量的目录。稍后通过客户端获取偏移量。
Val topicDir=new ZKGroupTopicDirs(groupId,topic) Val zkPath=topicDir.consumerOffsetDir
3、数据后,我们又怎么将偏移量手动存储到zookeeper中那,我们就需要有一个zookeeper的客户端了 Val zkClient=new ZKClient( zlList ) #获取目录下有几个子节点注册了偏移量的数量 Val children=zkClient.countChildren( zkPath ) #到下面找,这是结果 val kafkaDstream:InputDStream【(String,String)】
If(children >0) { #分区是从0开始数的。 For (I <- 0 until children ) { #实例化各个分区 Val topicAndPartion=new TopicAndPartition(topic,i) #获得各个分区对应的偏移量 val partitionOffset = zkClient.readata【String】{s”${zkPath}/${i}” #将不同分区的偏移量记录下来 fromOffsets +=(topicAndPartion –>partitionOffset) } Val messageHandler= (mmd:MessageAndMetadata[String,String])=>(mmd.topic,mmd.message()) #注意泛型中,R就是messageHandler的返回值,所以是tuple类型的。 kafkaDstream= KafkaUtils.createDirectStream[String,String,StringDecoder,StringDecoder,(String,String)](ssc,kafkaParams,fromOffSet,messageHandler)
} elseIf { kafkaDstream= KafkaUtils.createDirectStream[String,String,StringDecoder,StringDecoder] (ssc,kafkaParams,tpic.split(“,”).toSet)
}
|
接着上面的我们就可以操作了,和更新偏移量了 |
Var offsetRange=Array【offsetRange】()
kafkaDstream.transform(rdd => { 我们通过这个得到我们连接上kafka后,消费后的偏移量 val offsetRange = rdd.asInstanceOf【HasOffsetRange】.offsetRange rdd }).map(msg =>msg._2) .foreachRDD( rdd => { rdd.foreachpartition(partition=>{ partition.foreach(record=> { #这个地方开始写业务代码 print(record) }) })
For( o <- offsetRange ) { Val newZKPath = s”${zkPath}/${o.patition}” //将partition的offset保存到zookeeper ZkUtils.updatePersistentPath(zkClient,newZkPath,o.fromOffset.toString) } |
|
2.持久化的时候
rdd.write.mode(Savemode.overwrite/append).jdbc(“”)
3.DstreamRDD 和RDD 区别 dstream.map 和dstream.transform 有什么区别?
答:dstream.transform(rddè)每次操作的元素是RDD
4.reducebyAndWindow 算子怎么用?
答:reducebyAndWindow((a:int,b:int)=>a+b,seconds(30),seconds(10))
意思是,每隔10秒钟就统计最近30秒的单词数。