目錄:apache beam 個人使用經驗總結目錄和入門指導(Java)
衆所周知數據處理分批處理和流處理,beam是基於底層計算引擎並支持2者的。 這一章先只介紹批處理的幾種數據輸入方式,即一次性全部輸入全部數據的方式。
內存輸入數據
內存輸入方式之前介紹過了,可以通過組裝Create類進行內存輸入
PCollection<String> pcStart = pipeline.apply(
Create.of(
"HELLO!",
"THIS IS BEAM DEMO!",
"HAPPY STUDY!"));
也可也輸入其他數據類型
PCollection<Integer> pcStartInt = pipeline.apply(Create.of(1,2,3,4));
Create.of裏的內容可以是T… , 或者是Iterable<T>
本地文本
輸入
PCollection<String> pText =
pipeline.apply(TextIO.read().from("beam.txt"));
from裏是文本文件的路徑
讀入後,會自動根據換行符進行分割,分割成1個個String類型的數據集元素。
當我讀入如下beam.txt文本,並用PrintStrFn進行輸出時的情況:
可以看到確實是根據換行符進行了分割
輸出
輸出的sdk使用方式如下:
pText.apply(TextIO.write().to("/tmp/beamtest").withSuffix(".txt").withoutSharding());
注意事項:如果是基於分佈式計算引擎,使用TextIo讀取和輸出本地文件很可能會失敗,除非文件路徑在每一個executor節點都存在。
hdfs文本輸入
上面提到如果是在分佈式計算引擎上計算,讀取本地文件可能會失敗,因此分佈式讀取文本都是基於hdfs文件進行操作的。
hdfs輸入方式步驟如下:
1.pom文件增加hdfs依賴包
<dependency>
<groupId>org.apache.beam</groupId>
<artifactId>beam-sdks-java-io-hadoop-file-system</artifactId>
<version>{beam.version}</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>{hadoop.version}</version>
</dependency>
2.使用的PipelineOption至少要繼承自HadoopFileSystemOptions
public interface MyTestOption extends HadoopFileSystemOptions {...
3.創建的option要設置hdfs配置
MyTestOption option = PipelineOptionsFactory.fromArgs(args).withoutStrictParsing().as(MyTestOption.class);
Configuration conf = new Configuration();
// 輸入fs.defaultFS(可參考集羣的core-site.xml)
conf.set("fs.defaultFS", "hdfs://hacluster");
// 輸入文件系統執行引擎
conf.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem");
List<Configuration> list = new ArrayList<Configuration>();
list.add(conf);
option.setHdfsConfiguration(list);
4.調用TextIo
PCollection<String> pText =
pipeline.apply(TextIO.read().from("hdfs://hacluster/user/beam.txt"));
hdfs文本輸出sdk使用方式同本地文本輸出。
jdbc輸入
輸入
簡單的jdbc輸入可使用JdbcIO這個sdk, 首先得引入org.apache.beam的beam-sdks-java-io-jdbc這個包。
然後輸入如下代碼:
PCollection<String> pReadColumnFirst = pipeline.apply(
JdbcIO.<String>read()
// 組裝數據連接信息
.withDataSourceConfiguration(configuration)
// 組裝查詢語句
.withQuery("select name from worker")
// 如何把resultSet轉成需要的數據集元素
.withRowMapper(new JdbcRowMapper())
// 元素需要設定正確編碼,否則可能無法識別。
.withCoder(StringUtf8Coder.of())
);
configuration的生成方式如下:
JdbcIO.DataSourceConfiguration configuration
= JdbcIO.DataSourceConfiguration
.create(dbDriver, url)
.withUsername(userName)
.withPassword(password);
JdbcRowMapper的定義如下,需要實現JdbcIo.RowMapper接口:
static class JdbcRowMapper implements JdbcIO.RowMapper<String> {
// 如何將Jdbc的ResultSet轉成需要的元素
@Override
public String mapRow(ResultSet resultSet) throws Exception {
return resultSet.getString(1);
}
}
對於編碼的選取,可以見apache beam入門之編碼Coder相關
***注意事項: 該jdbcIO僅支持讀少量數據,如果要讀入超過jvm限制的數據,則會出現omm報錯
輸出
輸出要用preStatement的方式做插入或更新操作
pReadColumnFirst.apply(
JdbcIO.<String>write()
.withDataSourceConfiguration(configuration)
.withStatement("update worker set level = 10 where name = ?")
.withPreparedStatementSetter(new JdbcPreStatementSetter()));
JdbcPreStatementSetter的實現如下,就是定義瞭如何把數據集中的元素set到Statement中
static class JdbcPreStatementSetter implements JdbcIO.PreparedStatementSetter<String> {
@Override
public void setParameters(String element, PreparedStatement preparedStatement) throws Exception {
preparedStatement.setObject(1, element);
}
}
自定義輸入方式
如果beam自帶的sdk無法滿足需求(例如希望加入一些安全認證或者異常操作等),則可以用自定義的輸入方式。
自定義輸入需要先定義一個新的DoFn類,輸入類型定義爲Void,如下所示:
static class SafeReadFn extends DoFn<Void, String> {
@ProcessElement
public void processElement(ProcessContext context) {
// 可運行業務需要所的安全認證
safeLogin();
// 用自己定義的方式讀取數據
String readElement = readData(context);
// 輸出數據
context.output(readElement);
}
}
注意這個執行類中,不需要取輸入元素,因爲輸入元素Void一般都是null,不需要取。
然後先通過Create.of()建立1個空的Void元素,然後在處理這個元素時, 進行自定義輸入即可。
PCollection<String> pReadData
= pipeline.apply(Create.<Void>of(null))
.apply(ParDo.of(new SafeReadFn()));
輸出同理,如果是自定義輸出(即後面不再有計算操作), 定義1個DoFn<類型, Void>即可