前面的文章,已经简单提到过怎么样关闭流程序。由于Spark Streaming流程序比较特殊,因此不能直接执行kill -9 这种暴力方式停掉,若是使用这种方式停程序,那么就有可能丢失数据或者重复消费数据。git
为何呢?由于流程序一旦起来基本上是一个7*24小时的状态,除非特殊状况,不然是不会停的,由于每时每刻都有可能在处理数据,若是要停,也必定要确认当前正在处理的数据执行完毕,而且不能在接受新的数据,只有这样才能保证不丢不重。github
如何优雅的关闭spark streaming呢?方式主要有三种:redis
第一种:全人工介入浏览器
首先程序里面设置下面的配置参数curl
sparkConf.set("spark.streaming.stopGracefullyOnShutdown","true")//优雅的关闭
而后按照下面的步骤依次操做:socket
(1)经过Hadoop 8088页面找到运行的程序oop
(2)打开spark ui的监控页面ui
(3)打开executor的监控页面url
(4)登陆liunx找到驱动节点所在的机器ip以及运行的端口号spa
(5)而后执行一个封装好的命令
sudo ss -tanlp | grep 5555 |awk '{print $6}'|awk -F, '{print $2}' | sudo xargs kill -15
从上面的步骤能够看出,这样停掉一个spark streaming程序是比较复杂的。那么有没有更加优雅的方式来中止它呢?答案是有的
第二种:使用HDFS系统作消息通知
在驱动程序中,加一段代码,这段代码的做用每隔一段时间能够是10秒也能够是3秒,扫描HDFS上某一个文件,若是发现这个文件存在,就调用StreamContext对象stop方法,本身优雅的终止本身,其实这里HDFS能够换成redis,zk,hbase,db均可以,这里惟一的问题就是依赖了外部的一个存储系统来达到消息通知的目的,若是使用了这种方式后。中止流程序就比较简单了,登陆上有hdfs客户端的机器,而后touch一个空文件到指定目录,而后等到间隔的扫描时间到以后,发现有文件存在,就知道须要关闭程序了。
第三种:内部暴露一个socket或者http端口用来接收请求,等待触发关闭流程序
这种方式,须要在driver启动一个socket线程,或者http服务,这里推荐使用http服务,由于socket有点偏底层处理起来稍微复杂点,若是使用http服务,咱们能够直接用内嵌的jetty,对外暴露一个http接口,spark ui页面用的也是内嵌的jetty提供服务,因此我不须要在pom里面引入额外的依赖,在关闭的时候,找到驱动所在ip,就能够直接经过curl或者浏览器就直接关闭流程序。
找到驱动程序所在的ip,能够在程序启动的log中看到,也能够在spark master ui的页面上找到。这种方式不依赖任何外部的存储系统,仅仅部署的时候须要一个额外的端口号用来暴露http服务。
至此,关于优雅的中止spark streaming的主流方式已经介绍完毕,推荐使用第二种或者第三种,若是想要最大程度减小对外部系统的依赖,推荐使用第三种方式。
关于具体第二种和第三种的样例代码,下篇文章会整理一下放在github中给你们参考。