本文轉自個人微信公衆號,原文鏈接。本博客評論系統需要梯子,大家關注下公衆號方便交流。
本文基於Apache Flink 1.7。
Source 就是Flink 程序的數據輸入,Flink 提供了多種數據輸入方式,下面逐一介紹。
概念
Flink預定義Sources
Flink 預定義了多種Sources。
- 基於文件的,如
readTextFile(path)
、readFile(fileInputFormat, path)
等; - 基於socket的,如
socketTextStream
; - 基於collections and iterators的,如
fromCollection(Seq)
、fromElements(elements: _*)
等,常用於開發測試。
Connectors
connectors 用於給接入第三方數據提供接口,現在支持的connectors 包括:
- Apache Kafka
- RabbitMQ
- Apache NiFi
- Twtter Streaming API
- Amazon Kinesis Streams
另外,通過 Apache Bahir,可以支持ActiveMQ/Netty之類的Source。
Async I/O API
Flink 提供了外部數據存儲的異步I/O API。流計算中經常需要與外部存儲系統交互,比如取某個表的數據以便跟流中數據進行關聯,一般來說,如果用同步I/O的方式,會造成系統中出現大的等待時間,影響吞吐和延遲。爲了解決這個問題,異步I/O可以併發處理多個請求,提高吞吐,減少延遲,如下圖所示。
Queryable State
如果Flink 應用需要將大量數據寫到外部存儲,這時候很容易產生I/O 瓶頸,如果需要寫的數據是讀少寫多的數據,那麼是否可以讓外部應用自己來拉取數據呢?Queryable State 就是這個用途,提供了接口給外部應用,允許外部應用根據需要查詢Flink state,現階段Queryable State 還是Beta版,期待ing。
容錯
Flink 提供了容錯機制,以便Jobs從Failure恢復並繼續執行,Flink 提供source的 exactly-once需要source的支持,如下圖所示(注:圖片來源於Flink 官網):
實戰
預定義Sources
預定義的Source比較簡單,在程序開發、調試階段,可以採用基於Collection的Source,舉例來說:
val env = StreamExecutionEnvironment.getExecutionEnvironment
env.setStreamTimeCharacteristic(TimeCharacteristic.ProcessingTime)
val stream = env.fromCollection(List(1,2,3,4,5))
stream.print
env.execute
Kafka Connector
Connectors 就以最常用的Kafka Connectors來說。Flink 提供了Flink Kafka Consumer 讀取Kafka topics的數據,Flink Kafka Consumer 集成了Flink的checkpoint 機制以提供exactly-once 語義,不僅以來Kafka Consumer 的offset 追蹤,同時將這些信息存到checkpoint。
Kafka Connector 在Flink 1.7.0後有大的改動,但還處於beta階段,所以,下面還是以flink-connector-kafka-0.11_2.11 爲例,而且,我們在生產環境也是用的這個版本。大家也可以用最新的flink-connector-kafka_2.11,這是一個通用版本,兼容0.10.0後邊的版本。
首先,在項目中import Flink Kafka Connector。
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-connector-kafka-0.11_${scala.binary.version}</artifactId>
<version>${flink.version}</version>
</dependency>
代碼如下:
/** 註釋1
* 啓動checkpoint(可選)
* env.enableCheckpointing(5000); //checkpoint every 5000 msecs
*/
val properties = new Properties();
properties.setProperty("bootstrap.servers", "127.0.0.1:9092");
properties.setProperty("group.id", "groupXXX");
/** 註釋2
* 下面配置讀取kafka topic partition 的起始偏移量(可選)
* consumer.setStartFromEarliest();
* consumer.setStartFromLatest();
* consumer.setStartFromTimestamp(...);
* consumer.setStartFromGroupOffsets(); // 默認
*/
val consumer = new FlinkKafkaConsumer011[]("topic_name", SimpleStringSchema, properties)
/** 註釋3
* Watermark (可選)
* consumer.assignTimestampsAndWatermarks(new CustomWatermarkEmitter());
*/
val stream = env.addSource(consumer)
1. 構造函數 ,需要三個參數:
- topic 名
- 反序列化方法
- Kafka consumer的Properties
2. checkpoint,從註釋1 可以看出,Flink Kafka Consumer 可以啓動checkpoint機制,會週期性的給Kafka offsets 和 Flink的其它states 做 checkpoints,當Job 失敗時,Flink 讀取checkpoint裏最新的state並從對應offset 開始消費數據恢復運算。
3. 起始偏移量,從註釋2可以看出,Flink Kafka Consumer 允許設置讀取 Kafka Partition的起始偏移量,而且,允許不同Partitions 分別進行設置。但要注意,設置起始偏移量不適用於兩種情況:
- Job 從failure 自動恢復。
- 手動從某savepoint 啓動任務。
4. Kafka Topic 和Partition 自發現,比如構建Kafka Consumer時,topic名可以是正則表達式,這時候,如果有符合該正則的新的topic 加入到Kafka 集羣,可以被自動發現;另外,如果對Kafka Topic 進行RePartition,也可以自動發現,使用不多,可以自行查閱文檔。
5. Kafka Consumer與Watermark ,從註釋3可以看出,結合上篇文章,可以給數據設置方法以便給數據帶上watermark。
總結
本文主要以 Flink Kafka Connector 爲例講了Flink 裏的Sources,主要是考慮Kafka廣泛使用在實時系統中,甚至可以說是標配,後邊將開始講解Sink以及Flink SQL。
看到這裏,請掃描下方二維碼關注我,Happy Friday !