目錄
數據存儲/接收器
數據接收器使用DataStream將他們轉發到文件,socket,外部系統或者打印他們。Flink帶有各種被指的輸出格式,這些格式封裝再DataStream上的算子操作後面:
writeAsText() / TextOutputFormat -按字符串順序寫入數據元。通過調用每個數據元的toString()方法獲得字符串。
writeAsCsv(...) / CsvOutputFormat - 將元組寫爲逗號分割的文件。(Execl/hive等使用)。行和字段分隔符是可配置的。每個字段的值來自對象的toString()方法。 初學時記得調用execute方法後纔會有程序輸出。
print() / printToErr() -在標準輸出/標準錯誤流上打印每個數據元的toSting()值。可選地,可以提供前綴(msg) ,其前綴爲輸出。這有助於區分不同地打印調用。如果並行度大於1,則輸出也將與生成輸出的任務的標識符一起添加。
writeUsingOutputFormat() / FileOutputFormat --自定義文件輸出的方法和基類。支持自定義對象到字節的轉換。
writeToSocket --根據a將數據元寫入套接字SerializationSchema
addSink --調用自定義接收器函數。Flink捆綁了其它系統(如Apache Kafka)的連接器,這些系統實現爲接收器函數。
請注意:
write*()方法DataStream主要用於調試目的。他們呢沒有參與Flink的檢查點,這意味着這些函數通常具有至少一次的語義。刷新到目標系統的數據取決於OutputFormat的實現。這意味着非所有發送到OutputFormat的數據元都會立即顯示在目標系統中。此外,在失敗的情況下,這些記錄可能會丟失。
要將流可靠準確一次的發送到文件系統,請使用flink-connector-filesystem。此外,通過該.addSink(...)方法的自定義實現可以參與Flink的精確一次語義檢查點。
迭代:
迭代流程序實現不僅函數並將其嵌入到IterativeStream。由於DataStream程序可能永遠不會完成,因此沒有最大迭代次數。相反,您需要指定流的哪個部分反饋到迭代,那個部分使用split轉行或轉發到下游fliter。在這裏,我們展示了使用過濾器的示例。首先,我們定義一個IterativeStream
IterativeStream<Integer> iteration = input.iterate();
然後,我們使用一系列轉換指定將在循環內執行的邏輯(這是一個簡單的map 轉換)
DataStream<Integer> iterationBody = iteration.map(/* this is executed many times */);
要關閉迭代並定義迭代尾部,請調用closeWith(feedbackStream)方法IterativeStream。賦予closeWith函數的DataStream將反饋給迭代頭。常見的模式是使用過濾器來分離的流的部分和向前傳播的流的部分。這些濾波器可以定義例如“終止”邏輯,其中允許元件向下遊傳播而不是反饋。
iteration.closewith(iterationBody.filter(/* one part stream*/));
DataStream<Integer> output = iterationBody.filter(/* some other part of the stream */);
例如,這裏是從一系列整數中連續減去1,直到它們達到零的程序:
DtaStream<Long> sonmeIntegers = env.generateSequence(0,1000);
IterativeStream<Long> iteration = someInteger.iterate();
DataStream<Long> minusOne = iteration.map(new MapFunction<Long,Long>(){
@Override
public Long map(Long value) throws Execption {
return value -1;
}
});
DataStream<Long> stillGreaterThanZero = minusOne.fliter(new FilterFunction<Long>() {
@Override
public boolean filter(Long value) throws Exception {
return (value > 0);
}
});
iteration.closeWith(stillGreaterThanZero);
DataStream<Long> lessThanZero = minusOne.filter(new FilterFuction<Long>() {
@Override
public boolean filter(Long value) throws Exception{
return (value <= 0);
}
});
迭代流程序實現步進函數並將器嵌入到IterativeStream。由於DataStream程序可能永遠不會完成,因此沒有最大迭代次數。相反,您需要指定流的哪個部分反饋到迭代,哪個部分使用split轉換或者轉發到下游fliter。這裏,我們展示了一個示例迭代,其中正文(重複計算部分)是一個簡單的映射轉換,反饋的元素使用過濾器向下遊轉化分區的元素。
val iteratedStream = someDataStream.iterate(
iteration => {
val iterationBody = iteration.map(/* this is eecuted many times */)
(iterationBody.filter(/* one part of the stream */), iterationBody.fliter(/* some other part of the stream*/))
}
)
例如,這是從一系列整數中連續減去1直到它們到達0的程序:
val someIntegers:DataStream[Long] = env.generateSequence(0,1000)
val iteratedStream = someIntegers.iterate(
iteration => {
val minusOne = iteration.map( v => v -1)
val stillGreaterThanZero = minusOne.filter (_ > 0)
val lessThanZero = minusOne.fliter(_ <= 0)
(stillGreaterThanZero,lessThanZero)
}
)
執行參數:
該StreamExecutionEnvironment包含ExecutionConfig允許爲運行時設置工作的具體配置值。
有關大多數參數的說明,請參閱執行配置。這些參數特別適合DataStream API:
setAutoWatermarkInterval(long milliseconds):設置自動水印發射的間隔。您可以使用獲取當前值long getAutoWatermarkInterval()
容錯:
待補
控制延遲:
默認情況下,數據元不會逐個傳輸到網絡上(這會導致不必要多的網絡流量),但會被緩衝。可以在Flink配置文件中設置緩衝區的大小(實際在計算機之間傳輸)。雖然此方法適用於優化吞吐量,但當傳入流速度不夠快時,可能會導致延遲問題。要控制吞吐量和延遲,您可以env.setBufferTimeout(timeoutMillis)在運行環境(或單個算子)上使用以設置緩衝區填充的最長等待時間。再次之後,即使緩衝區未滿,也會自動發送緩衝區。此超時的默認值爲100毫秒。
val env:LocalStreamEnvironment = StreamExecutionEnvironmet.createLocalEnvironment
env.setBufferTimeout(timeoutMillis)
env.generateSequence(1,10).map(myMap).setBufferTimeout(timeoutMillis)
爲了最大化吞吐量,設置setBufferTimeout(-1)將刪除超時,只有在緩衝區已滿的情況下才會被刷新。要最小化延遲,請將超時設置爲接近0的值(例如5或10ms)。應避免緩衝區超時未0,因爲它可能會導致嚴重的性能下降。