Spark權威指南(中文版)----第23章 生產環境中的結構化流

Spark The Definitive Guide(Spark權威指南) 中文版。本書詳細介紹了Spark2.x版本的各個模塊,目前市面上最好的Spark2.x學習書籍!!!

掃碼關注公衆號:登峯大數據,閱讀中文Spark權威指南(完整版),系統學習Spark大數據框架!

如果您覺得作者翻譯的內容有幫助,請分享給更多人。您的分享,是作者翻譯的動力

本書前幾章已經從用戶的角度介紹了結構化流。這自然是應用程序的核心。本章將介紹在開發應用程序之後,在生產環境中穩定運行結構化流所需的一些操作工具。在Apache Spark 2.2.0中,結構化流被標記爲可生產的,這意味着該版本具有生產使用所需的所有特性和穩定的API。許多組織已經在生產中使用該系統,因爲坦率地說,它與運行其他生產Spark應用程序沒有太大的不同。的確,通過諸如事務source/sink和精確的一次處理等特性,結構化流設計人員試圖使其儘可能易於操作。本章將帶您瞭解一些特定於結構化流的關鍵操作任務。這將補充我們在第2部分中看到和瞭解到的有關Spark操作的所有內容。

23.1.容錯和檢查點

流應用程序最重要的操作關注點是故障恢復。錯誤是不可避免的:例如丟失集羣中的一臺機器,模式將在沒有適當遷移的情況下意外更改,甚至可能故意重啓集羣或應用程序。在這些情況下,結構化流允許您通過重新啓動應用程序來恢復應用程序。爲此,必須將應用程序配置爲使用檢查點和WAL預寫日誌,這兩個操作都由引擎自動處理。具體地說,您必須配置一個查詢來寫入可靠文件系統(例如,HDFS、S3或任何兼容的文件系統)上的檢查點位置。然後,結構化流將定期將所有相關的進度信息(例如,給定觸發器中處理的偏移量範圍)以及當前中間狀態值保存到檢查點位置。在失敗場景中,您只需重新啓動應用程序,確保指向相同的檢查點位置,它就會自動恢復其狀態,並從停止的地方開始處理數據。您不必代表應用程序手動管理此狀態----結構化流媒體爲您做這些功能。

要使用檢查點,請在通過writeStream上的checkpointLocation選項啓動應用程序之前指定檢查點位置。你可以這樣做:

// in Scalaval static = spark.read.json("/data/activity-data")val streaming = spark  .readStream  .schema(static.schema)  .option("maxFilesPerTrigger", 10)  .json("/data/activity-data")  .groupBy("gt")  .count()val query = streaming  .writeStream  .outputMode("complete")  .option("checkpointLocation", "/some/location/")  .queryName("test_stream")  .format("memory")  .start()# in Pythonstatic = spark.read.json("/data/activity-data")streaming = spark\  .readStream\  .schema(static.schema)\  .option("maxFilesPerTrigger", 10)\.json("/data/activity-data")\  .groupBy("gt")\  .count()query = streaming\  .writeStream\  .outputMode("complete")\  .option("checkpointLocation", "/some/python/location/")\  .queryName("test_python_stream")\  .format("memory")\  .start()

如果丟失檢查點目錄或其中的信息,應用程序將無法從失敗中恢復,您將不得不從頭開始重新啓動流。

23.2.更新程序

爲了在生產環境中運行應用程序,啓用檢查點可能是最重要的。這是因爲檢查點將存儲到目前爲止您的流所處理的所有信息,以及它可能存儲的中間狀態。然而,檢查點確實帶來了一個小陷阱——當您更新流應用程序時,您將不得不對舊檢查點數據進行推理。當您更新您的應用程序時,您必須確保您的更新不是破壞性的更改。當我們查看這兩種類型的更新時,我們將詳細討論這些內容:對應用程序代碼的更新或運行新的Spark版本。

23.2.1.對應用程序代碼的更新

結構化流的設計允許在應用程序重啓之間對應用程序代碼進行某些類型的更改。最重要的是,允許您更改用戶定義函數(udf),只要它們具有相同的類型簽名。這個特性對於bug修復非常有用。例如,假設應用程序開始接收一種新類型的數據,並且當前邏輯中的數據解析函數之一崩潰。使用結構化流,您可以使用該函數的新版本重新編譯應用程序,並在流中它之前崩潰的同一位置重新編譯。

雖然添加新列或更改UDF之類的小調整不會破壞更改,也不需要新的檢查點目錄,但是較大的更改確實需要一個全新的檢查點目錄。例如,如果更新流應用程序以添加新的聚合鍵或從根本上更改查詢本身,Spark就不能從舊檢查點目錄爲新查詢構造所需的狀態。在這些情況下,結構化流將拋出一個異常,說它不能從檢查點目錄開始,您必須從頭開始使用一個新的(空的)目錄作爲檢查點位置。

23.2.2.運行新的Spark版本

結構化的流處理應用程序應該能夠從一箇舊的檢查點目錄重新啓動到Spark的補丁版本更新(例如,從Spark 2.2.0到2.2.1再到2.2.2)。檢查點格式被設計爲向前兼容的,所以它可能被破壞的唯一方法是由於關鍵的錯誤修復。如果Spark發行版不能從舊檢查點恢復,那麼它的發行說明中將清楚地記錄這一點。結構化流媒體開發人員還希望在較小的版本更新(如Spark 2.2)之間保持格式的兼容性。但是您應該檢查發佈說明,看看是否支持每次升級。在這兩種情況下,如果不能從檢查點啓動,都需要使用新的檢查點目錄重新啓動應用程序。

23.2.3.調整應用程序的規模大小

通常,集羣的大小應該能夠輕鬆地處理高於數據速率的突發事件。下面討論應用程序和集羣中應該監控的關鍵指標。一般來說,如果您看到您的輸入速率遠遠高於您的處理速率(稍後將進行詳細說明),那麼就該擴展您的集羣或應用程序了。根據您的資源管理器和部署,您可能只是能夠動態地將executor添加到應用程序中。當需要時,您可以用同樣的方法縮小應用程序的規模——刪除執行器(可能通過您的雲提供商)或使用更低的資源計數重新啓動應用程序。這些更改可能會導致一些處理延遲(當刪除執行器時,將重新計算數據或重新分配分區)。最後,是否值得創建一個具有更復雜的資源管理功能的系統是一個業務決策。

雖然對集羣或應用程序進行底層基礎設施更改有時是必要的,但有時更改可能只需要重新啓動應用程序或使用新配置的流。例如在流處理程序運行過程中,更改 spark.sql.shuffle.partitions參數是不會生效的。這需要重新啓動實際的流處理程序,而不一定是整個應用程序。較重的更改(如更改任意Spark應用程序配置)可能需要重新啓動應用程序。

23.3.度量和監控

流應用程序中的度量和監視與使用第18章中描述的工具的一般Spark應用程序基本相同。不過,結構化流確實添加了一些更具體的內容,以幫助您更好地理解應用程序的狀態。您可以使用兩個關鍵api來查詢流查詢的狀態並查看其最近的執行進度。使用這兩個api,您可以瞭解您的流是否按預期運行。

23.3.1.Query Status 查詢狀態

查詢狀態是最基本的監控API,因此它是一個很好的起點。它的目的是回答這個問題:“我的流現在正在執行什麼處理?” 此信息在startStream返回的查詢對象的status字段中報告。例如,您可能有一個簡單的計數流,它提供了由以下查詢定義的物聯網設備的計數(這裏我們只是使用了與前一章相同的查詢,沒有初始化代碼):

 

query.status

要獲得給定查詢的狀態,只需運行命令query.status將返回流的當前狀態。這爲我們提供了關於流中在那個時間點上發生的事情的詳細信息。下面是查詢此狀態時將返回的示例:

{  "message" : "Getting offsets from ...",  "isDataAvailable" : true,  "isTriggerActive" : true}

 

上面的代碼片段描述了從結構化流數據源獲取偏移量(因此描述獲取偏移量的消息)。有多種消息描述流的狀態。

注意我們以在Spark shell中調用的方式在這裏內聯顯示了status命令。但是,對於獨立應用程序,您可能沒有附加shell來在流程中運行任意代碼。在這種情況下,您可以通過實現監控服務器來公開它的狀態,例如一個小型HTTP服務器,它監聽端口並返回查詢。獲取請求時的狀態。或者,您可以使用稍後描述的更豐富的StreamingQueryListener API來偵聽更多事件。

23.3.2.Recent Progress當前進展

雖然可以查看查詢的當前狀態,但是查看查詢過程的能力同樣重要。progress API允許我們回答諸如“我處理元組的速度是多少?”或者“元組從源到達的速度有多快?” 通過運行query.recentProgress命令,流查詢過程還包括關於流內部的輸入源和輸出接收器的信息。

 

query.recentProgress

這是我們運行之前的代碼後Scala版本的結果;Python版本將是類似的:

Array({  "id" : "d9b5eac5-2b27-4655-8dd3-4be626b1b59b",  "runId" : "f8da8bc7-5d0a-4554-880d-d21fe43b983d",  "name" : "test_stream",  "timestamp" : "2017-08-06T21:11:21.141Z",  "numInputRows" : 780119,  "processedRowsPerSecond" : 19779.89350912779,  "durationMs" : {    "addBatch" : 38179,    "getBatch" : 235,    "getOffset" : 518,    "queryPlanning" : 138,    "triggerExecution" : 39440,    "walCommit" : 312  },  "stateOperators" : [ {    "numRowsTotal" : 7,    "numRowsUpdated" : 7  } ],  "sources" : [ {    "description" : "FileStreamSource[/some/stream/source/]",    "startOffset" : null,    "endOffset" : {      "logOffset" : 0    },    "numInputRows" : 780119,    "processedRowsPerSecond" : 19779.89350912779  } ],  "sink" : {    "description" : "MemorySink"  }})

正如您從剛纔顯示的輸出中所看到的,這包括關於流狀態的許多細節。需要注意的是,這是一個實時快照(根據查詢進度的時間)。爲了一致地獲得關於流狀態的輸出,您需要反覆查詢這個API以獲得更新後的狀態。前面輸出中的大多數字段應該是不言自明的。但是,讓我們詳細回顧一些更重要的字段。

Input rate and processing rate輸入速率和處理速率

輸入速率指定有多少數據從輸入源流向結構化流。處理速率是應用程序分析數據的速度。在理想情況下,輸入和處理速率應該同時變化。另一種情況可能是輸入速率遠遠大於處理速率。當這種情況發生時,流就會落後,您需要將集羣擴展到更高的級別來處理更大的負載。

Batch duration批次間隔

幾乎所有的流系統都利用批處理以任何合理的吞吐量進行操作(有些系統可以選擇高延遲來換取較低的吞吐量)。結構化流實現了這兩種功能。當它對數據進行操作時,您可能會看到批處理持續時間隨着結構化流處理事件數量的變化而振盪。當然,當連續處理引擎成爲執行選項時,這個度量將幾乎沒有相關性。

提示通常,將批處理持續時間、輸入和處理速率的變化可視化是最佳實踐。它比簡單地報告隨時間的變化更有幫助。

23.3.3.Spark UI

Spark web UI(在第18章中詳細介紹)還顯示了結構化流應用程序的任務、作業和數據處理指標。在Spark UI上,每個流應用程序都將顯示爲一系列短作業,每個觸發器對應一個短作業。但是,您可以使用相同的UI查看來自應用程序的度量、查詢計劃、任務持續時間和日誌。與DStream API不同的一點是,流選項卡不用於結構化流。

23.4.預警

理解和查看結構化流查詢的指標是重要的第一步。然而,這需要不斷地監控儀表板或度量,以發現潛在的問題。您將需要健壯的自動警報,以便在不手動監控作業的情況下,在作業失敗或無法跟上輸入數據速率時通知您。有幾種方法可以將現有的警報工具集成到Spark中,通常是基於我們前面介紹的recent progress API。例如,您可以直接將度量數據提供給監控系統,比如開源Coda Hale度量庫或Prometheus,或者您可以簡單地對它們進行日誌記錄,並使用Splunk這樣的日誌聚合系統。除了監控和警告查詢之外,還需要監控和警告集羣和整個應用程序的狀態(如果同時運行多個查詢)。

23.5.使用流監聽器進行高級監控

我們已經討論了結構化流中的一些高級監控工具。使用一些粘合邏輯,您可以使用status和queryProgress api將監控事件輸出到您選擇的監控平臺(例如,日誌聚合系統或Prometheus儀表板) 除了這些方法之外,還有一種更底層但更強大的方法來觀察應用程序的執行:StreamingQueryListener類。

StreamingQueryListener類允許您從流查詢接收異步更新,以便自動將此信息輸出到其他系統,並實現健壯的監控和警報機制。首先開發自己的對象來擴展StreamingQueryListener,然後將其附加到正在運行的SparkSession。一旦您使用sparkssession .streams. addlistener()附加自定義偵聽器,當查詢啓動或停止時,或者在活動查詢上取得進展時,您的類將收到通知。下面是結構化流文檔中偵聽器的一個簡單示例:

val spark: SparkSession = ...spark.streams.addListener(new StreamingQueryListener() {    override def onQueryStarted(queryStarted: QueryStartedEvent): Unit = {        println("Query started: " + queryStarted.id)    }    override def onQueryTerminated(      queryTerminated: QueryTerminatedEvent): Unit = {        println("Query terminated: " + queryTerminated.id)    }    override def onQueryProgress(queryProgress: QueryProgressEvent): Unit = {        println("Query made progress: " + queryProgress.progress)    }})

流監聽器允許您使用自定義代碼處理每個進度更新或狀態更改,並將其傳遞給外部系統。例如,StreamingQueryListener的以下代碼將把所有查詢進度信息轉發給Kafka。從Kafka讀取數據後,您必須解析這個JSON字符串,以便訪問實際的指標:

class KafkaMetrics(servers: String) extends StreamingQueryListener {  val kafkaProperties = new Properties()  kafkaProperties.put(    "bootstrap.servers",    servers)  kafkaProperties.put(    "key.serializer",    "kafkashaded.org.apache.kafka.common.serialization.StringSerializer")  kafkaProperties.put(    "value.serializer",    "kafkashaded.org.apache.kafka.common.serialization.StringSerializer")
  val producer = new KafkaProducer[String, String](kafkaProperties)
  import org.apache.spark.sql.streaming.StreamingQueryListener  import org.apache.kafka.clients.producer.KafkaProducer
  override def onQueryProgress(event:    StreamingQueryListener.QueryProgressEvent): Unit = {    producer.send(new ProducerRecord("streaming-metrics",      event.progress.json))  }  override def onQueryStarted(event:    StreamingQueryListener.QueryStartedEvent): Unit = {}  override def onQueryTerminated(event:StreamingQueryListener.QueryTerminatedEvent): Unit = {}}

 

使用StreamingQueryListener接口,您甚至可以通過在同一個(或另一個)集羣上運行結構化流應用程序來監控一個集羣上的結構化流應用程序。您還可以用這種方式管理多個流。

23.6.結束語

在本章中,我們討論了在生產環境中運行結構化流所需的主要工具:容錯檢查點和各種監控api,這些api允許您觀察應用程序如何運行。幸運的是,如果您已經在生產環境中運行Spark,那麼許多概念和工具都是類似的,因此您應該能夠重用大量現有知識。請務必檢查第4部分,以查看監控Spark應用程序的其他一些有用工具。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章