一.需求
在使用spark-streaming 处理流式任务时,由于spark-shell需要登录到和生产集群相连的机器开启,使用起来也有诸多不便,且默认不支持kafka等源,所以萌生使用zeppelin 中的spark interpreter来完成streaming 任务.
二.尝试
在网上找到了一个改版的zeppelin版wordcount例子.
第一步启动nc 监听端口7777
第二步在zeppelin spark interpreter 中启动streming任务
%spark
sc.version
import org.apache.spark.streaming._
import org.apache.spark.streaming.StreamingContext
import org.apache.spark.streaming.StreamingContext._
import org.apache.spark.streaming.dstream.DStream
import org.apache.spark.streaming.Duration
import org.apache.spark.streaming.Seconds
case class Message(createdAt:Long, text:String)
val ssc = new StreamingContext(sc, Seconds(10))
val lines = ssc.socketTextStream("10.104.90.40", 7777)
val errorLines = lines.window(Seconds(10))
val message = errorLines.map(status=>
Message(System.currentTimeMillis()/1000, status)
).foreachRDD(rdd=>
if (rdd.isEmpty()==false) {
rdd.toDF().registerTempTable("message")}
)
errorLines.print
ssc.start()
第三步在nc中输入一些测试数据,在zeppelin spark interpreter读取streaming处理的结果
%spark
val data = sqlContext.sql("select * from message")
data.show()
得到类似如下的输出
三.问题
尝试的过程中发现了如下问题:
1.停止streaming context的方式不正确
如果使用ssc.stop()停止spark streaming context 会导致zeppelin 服务端的spark context也一并停止,导致出现如下的错误,并且在web ui重启spark interpreter也不解决问题,最后只能重启整个zeppelin 服务.
java.lang.IllegalStateException: RpcEnv has been stopped
在zeppelin中停止streaming context的正确方式为
ssc.stop(stopSparkContext=false, stopGracefully=true)
2.nc server同一时间只能服务一个client
刚开始尝试nc用法时,先使用nc -lk 7777启动server端,再使用nc locahost 7777启动client,尝试互相传送信息成功,在zeppelin 中streaming任务却总是读不到任何数据
原因就在于nv server只能同时服务一个client端.
在多个client 端同时链接server 端时,按建立链接的先后会出现只有一个client端口能接收数据的情况.
如果zeppelin中的streaming任务作为client端接收到了server端的消息,即使按照1中的方法停止了streaming context,别的client端也依然接受不到消息,推测可能是server端服务对象仍然为streaming 任务.
3.ERROR [2017-05-02 11:31:12,686] ({dispatcher-event-loop-2} Logging.scala[logError]:70) - Deregistered receiver for stream 0: Restarting receiver with delay 2000ms: Error connecting to loc
alhost:7777 - java.net.ConnectException: Connection refuse
开始时使用localhost 作为socketTextStream中的host地址,却总是会出现上面的错误,但是使用telnet >open localhost 7777却可以成功建立链接
把localhost 改成10.104.90.40 则不会再出现上述错误,推测原因在于zepplin 使用的spark interpreter设置运行在了cluster mode,在除10.104.90.40 以为的机器上并没有nc 运行,7777端口也是不通的,所以会出现访问拒绝.
4.Attempted to use BlockRDD[36063] at socketTextStream at <console>:217 after its blocks have been removed!
当使用val data = sqlContext.sql("select * from message")查看streaming 处理结果时,查询后一段时间(几s)后再次运行查询任务就会出现如上错误.
在zeppelin spark interpreter日志中发现每个窗口执行完之后都与类似如下的日志
Removing RDD 37697 from persistence list
从这篇文章中的代码分析可见出错原因在于blockrdd 已经被删了导致,结合spark streaming dag任务结束后会删除数据可知
这个报错的原因在于message这张由registerTempTable 产生的表实际的存储rdd已经被删除导致.
5.hive接入问题,不解
INFO [2017-04-28 22:15:10,455] ({pool-2-thread-2} HiveMetaStoreClient.java[open]:376) - Trying to connect to metastore with URI thrift://10.104.90.40:9083
WARN [2017-04-28 22:15:10,456] ({pool-2-thread-2} UserGroupInformation.java[getGroupNames]:1492) - No groups available for user heyang.wang
WARN [2017-04-28 22:15:10,462] ({pool-2-thread-2} HiveMetaStoreClient.java[open]:444) - set_ugi() not successful, Likely cause: new client talking to old server. Continuing without it.
5.1假期前一度出现的问题,只要对rdd进行相关action类操作如rdd.toDf,rdd.collect等就会触发,但是当时hive cli和beeline都可以正常访问hive,hive metastore 日志中也没有报错信息.
但是5.1假期或却又没问题了.
四.尝试在livy中运行spark-streaming任务
经过测试,在livy中可以以同样的方式使用spark streaming,只需要改%spark为%livy.spark
五.接入kafka数据源(未完)
参考来源:
http://apache-spark-user-list.1001560.n3.nabble.com/Lifecycle-of-RDD-in-spark-streaming-td19749.html
http://www.jianshu.com/p/0e7e540de15c
http://stackoverflow.com/questions/29728151/how-to-listen-for-multiple-tcp-connection-using-nc