前面的文章,已經簡單提到過怎麼樣關閉流程序。由於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中給你們參考。