简单的写了一个类作为kafka的producer, 然后SparkStreaming的类作为consumer
Producer 的run方法产生数据:
public void run() { KafkaProducerproducer = getProducer(); int messageNum = 0; Random rd = new Random(); while(true){ String page = "Page_" + rd.nextInt(15) + ".html"; Integer click = rd.nextInt(10); float stayTime = rd.nextFloat(); Integer likeOrNot = rd.nextInt(3); String messageStr = page + "\t" + click + "\t" + stayTime + "\t" + likeOrNot; long startTime = System.currentTimeMillis(); System.out.println("sending message: " + messageStr); producer.send(new ProducerRecord<>(topic, 999, messageStr)); messageNum++; try { Thread.sleep(200); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
SparkStreaming的consumer:
val ssc = new StreamingContext("local[2]", "appName", Seconds(5),System.getenv("SPARK_HOME")) ssc.checkpoint("./") val kafkaStream = KafkaUtils.createStream(ssc, "10.32.190.165:2181", "test", Map("test"->1)) // val kafkaStream = KafkaUtils.createStream(ssc, Map("group.id"->"test","zookeeper.connect"->"10.32.190.165:2181", "zookeeper.connection.timeout.ms"->"10000"), Map("test"->1),StorageLevel.MEMORY_AND_DISK_SER_2) // kafkaStream.ytt val msgRDD = kafkaStream.map(_._2) val newRdd = msgRDD.map { x => (x.split("\t")(0), getValueOfPage(x.split("\t"))) }.reduceByKey((a,b) => a + b) val resultRdd = newRdd.transform(x =>x.sortByKey(false)) var updateFunc = (iterator: Iterator[(String, Seq[Double], Option[Double])]) => { iterator.flatMap(x=> { var page = x._1 var nowValue = x._2.sum var oldValue : Double = x._3.getOrElse(0) Some(nowValue + oldValue) }.map { y => (x._1, y) }) } val initRDD = ssc.sparkContext.parallelize(List(("page_0.html", 0.0))) val stateRDD = newRdd.updateStateByKey[Double](updateFunc, new HashPartitioner(ssc.sparkContext.defaultParallelism), true,initRDD); // val sortRDD = stateRDD.map(x => (x._2, x._1)) // newRdd. stateRDD.foreachRDD(r =>{ val sortedRDD = r.map(x => (x._2, x._1)).sortByKey(false) val topK = sortedRDD.take(3) topK.foreach(y => println(y)) }) // resultRdd.print() ssc.start() ssc.awaitTermination()
zookeeper和Kafka的config都是默认配置, 由于资源不够, 目前都是单机环境, 就改了一下zookeeper的server port, 和kafka这边zookeeper的host+port
结果运行的时候就报错:
16/06/28 16:55:33 WARN ClientUtils$: Fetching topic metadata with correlation id 1 for topics [Set(test)] from broker [BrokerEndPoint(0,localhost,9092)] failed
java.nio.channels.ClosedChannelException
at kafka.network.BlockingChannel.send(BlockingChannel.scala:110)
at kafka.producer.SyncProducer.liftedTree1$1(SyncProducer.scala:80)
at kafka.producer.SyncProducer.kafka$producer$SyncProducer$$doSend(SyncProducer.scala:79)
at kafka.producer.SyncProducer.send(SyncProducer.scala:124)
at kafka.client.ClientUtils$.fetchTopicMetadata(ClientUtils.scala:59)
at kafka.client.ClientUtils$.fetchTopicMetadata(ClientUtils.scala:94)
at kafka.consumer.ConsumerFetcherManager$LeaderFinderThread.doWork(ConsumerFetcherManager.scala:66)
at kafka.utils.ShutdownableThread.run(ShutdownableThread.scala:63)
16/06/28 16:55:33 INFO SyncProducer: Disconnecting from localhost:9092
16/06/28 16:55:33 WARN ConsumerFetcherManager$LeaderFinderThread: [test_CNCSHUM4L3C-1467104130749-71111338-leader-finder-thread], Failed to find leader for Set([test,0])
kafka.common.KafkaException: fetching topic metadata for topics [Set(test)] from broker [ArrayBuffer(BrokerEndPoint(0,localhost,9092))] failed
at kafka.client.ClientUtils$.fetchTopicMetadata(ClientUtils.scala:73)
at kafka.client.ClientUtils$.fetchTopicMetadata(ClientUtils.scala:94)
at kafka.consumer.ConsumerFetcherManager$LeaderFinderThread.doWork(ConsumerFetcherManager.scala:66)
at kafka.utils.ShutdownableThread.run(ShutdownableThread.scala:63)
Caused by: java.nio.channels.ClosedChannelException
at kafka.network.BlockingChannel.send(BlockingChannel.scala:110)
at kafka.producer.SyncProducer.liftedTree1$1(SyncProducer.scala:80)
at kafka.producer.SyncProducer.kafka$producer$SyncProducer$$doSend(SyncProducer.scala:79)
at kafka.producer.SyncProducer.send(SyncProducer.scala:124)
at kafka.client.ClientUtils$.fetchTopicMetadata(ClientUtils.scala:59)
... 3 more
可以看到kafka的broker是去找localhost:9092, 由于eclipse环境在本地, kafka和zookeeper是在vm上面, 基本锁定是这个原因。
关键是, localhost是在哪里改。。。。
尝试跟踪源码, 发现KafkaUtils.createStream 有一个方法是可以传一个Map进去, Map里面存的configuration。 尝试传入"metadata.broker.list", 结果从spark的日志中看到这个属性不能在这里设置, 直接被ingore了。
折腾了两天, 基本上把本机可以动的地方都动了, 没用。
后来想到会不会是kafka启动的时候用的server.properties里面有设置, 打开一看, 果然, 有一个属性:
#advertised.listeners=PLAINTEXT://your.host.name:9092
默认被注释掉了, 看说明如果被注释掉了后就直接设置成localhost了, 果断修改成Kafka的IP:Port,重启Kafka, 启动producer, 运行Consumer, 错误消失, 分析结果出来了