この記事では、最初に見出しに登場FLINKプログラムが実行されますか?FLINKは、ソースコードを簡単な手順を分析すると、歓迎の注目の見出し番号と、より乾燥のための「ビッグデータと人工知能」(マイクロ文字の検索bigdata_ai_tech)のマイクロチャネルパブリック番号を、私はまた、注意歓迎CSDNのブログを。
カバーthis've前にローカル環境をセットアップする方法とどのようにFLINK FLINKアプリケーション作成すると、どのようFLINKソース構築する方法この資料の例では、日常的な手順FLINKが何であるかを解決するためにSocketWindowWordCountの公式を使用し、それぞれの基本的な手順のを。
サンプルプログラム
public class SocketWindowWordCount {
public static void main(String[] args) throws Exception {
// the host and the port to connect to
final String hostname;
final int port;
try {
final ParameterTool params = ParameterTool.fromArgs(args);
hostname = params.has("hostname") ? params.get("hostname") : "localhost";
port = params.getInt("port");
} catch (Exception e) {
System.err.println("No port specified. Please run 'SocketWindowWordCount " +
"--hostname <hostname> --port <port>', where hostname (localhost by default) " +
"and port is the address of the text server");
System.err.println("To start a simple text server, run 'netcat -l <port>' and " +
"type the input text into the command line");
return;
}
// get the execution environment
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
// get input data by connecting to the socket
DataStream<String> text = env.socketTextStream(hostname, port, "\n");
// parse the data, group it, window it, and aggregate the counts
DataStream<WordWithCount> windowCounts = text
.flatMap(new FlatMapFunction<String, WordWithCount>() {
@Override
public void flatMap(String value, Collector<WordWithCount> out) {
for (String word : value.split("\\s")) {
out.collect(new WordWithCount(word, 1L));
}
}
})
.keyBy("word")
.timeWindow(Time.seconds(5))
.reduce(new ReduceFunction<WordWithCount>() {
@Override
public WordWithCount reduce(WordWithCount a, WordWithCount b) {
return new WordWithCount(a.word, a.count + b.count);
}
});
// print the results with a single thread, rather than in parallel
windowCounts.print().setParallelism(1);
env.execute("Socket Window WordCount");
}
// ------------------------------------------------------------------------
/**
* Data type for words with count.
*/
public static class WordWithCount {
public String word;
public long count;
public WordWithCount() {}
public WordWithCount(String word, long count) {
this.word = word;
this.count = count;
}
@Override
public String toString() {
return word + " : " + count;
}
}
}
これは、上記の公式ウェブサイトでSocketWindowWordCount
プログラム例は、最初のホストのコマンドラインとポートのソケット接続を取得し、その後、実行環境、ソケット接続から読み出されたデータ、解析およびデータ変換、最終的な出力データを取得します。
各手順は、以下のFLINKを数全体にわたって実質的に同一の部品が含まれています。
- 実行環境を手に入れよう、
- ロード/初期データを作成し、
- このデータの変換を指定し、
- 配置計算結果のために指定されました、
- トリガーの実行
FLINK実行環境
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
FLINKプログラムは、このコードから開始され、このコード行は、実行環境を返すプログラムの現在の実行コンテキストを表します。プログラムは、独立した呼び出された場合、このメソッドは戻りますcreateLocalEnvironment()
ローカル実行環境が作成されますLocalStreamEnvironment
。そのソースコードで見ることができます。
//代码目录:org/apache/flink/streaming/api/environment/StreamExecutionEnvironment.java
public static StreamExecutionEnvironment getExecutionEnvironment() {
if (contextEnvironmentFactory != null) {
return contextEnvironmentFactory.createExecutionEnvironment();
}
ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
if (env instanceof ContextEnvironment) {
return new StreamContextEnvironment((ContextEnvironment) env);
} else if (env instanceof OptimizerPlanEnvironment || env instanceof PreviewPlanEnvironment) {
return new StreamPlanEnvironment(env);
} else {
return createLocalEnvironment();
}
}
入力データの取得
DataStream<String> text = env.socketTextStream(hostname, port, "\n");
ソケットからこの例のソースデータは、この構成では、ソケット、復号システムのデフォルトの文字セットで受信した文字列から受信した無制限の文字列を含み、指定されたソケットのソケット接続を作成し、新しいデータ・ストリームを作成します。 。ソケット接続がクローズされた場合、データの読み取りがすぐに終了します。ソースを見て、見つけることができ、実際にソケットの設定を指定することにより、そこに構築されたSocketTextStreamFunction
例を、その後、データの安定した流れは、内部の入力ソケット接続から読み取られたデータ・ストリームを作成します。
//代码目录:org/apache/flink/streaming/api/environment/StreamExecutionEnvironment.java
@PublicEvolving
public DataStreamSource<String> socketTextStream(String hostname, int port, String delimiter, long maxRetry) {
return addSource(new SocketTextStreamFunction(hostname, port, delimiter, maxRetry),
"Socket Stream");
}
SocketTextStreamFunction
次のようにクラス階層は以下のとおりです。
それが分かるようにサブクラスは、すべてのストリームデータソースの基本的なインタフェースFLINKあります。これは次のように定義されます。SocketTextStreamFunction
SourceFunction
SourceFunction
SourceFunction
//代码目录:org/apache/flink/streaming/api/functions/source/SourceFunction.java
@Public
public interface SourceFunction<T> extends Function, Serializable {
void run(SourceContext<T> ctx) throws Exception;
void cancel();
@Public
interface SourceContext<T> {
void collect(T element);
@PublicEvolving
void collectWithTimestamp(T element, long timestamp);
@PublicEvolving
void emitWatermark(Watermark mark);
@PublicEvolving
void markAsTemporarilyIdle();
Object getCheckpointLock();
void close();
}
}
SourceFunction
定義run
とcancel
二つの方法およびSourceContext
内部インターフェース。
- データ取得ロジックのため、およびデータは、CTXを渡されたパラメータから下流ノードに転送することができる:(SourceContex)を実行します。
- キャンセル():ループ終了を引き起こす可能性があり、通常はrunメソッドでは、メソッドをキャンセルし、データを生成するために、連続したループがあるだろう、データソースをキャンセルします。
- SourceContext:機能および可能な透かしインタフェース、戻り型ソース発生素子を出射する光源素子。
理解SourceFunction
このインタフェース、およびその後を見てSocketTextStreamFunction
具体的な実装(主にrun
法)、ロジックは、非常に明確であるが連続的に指定したホスト名とポートからデータを読み込み、Enterキーを押して文字列に改行区切り文字を入力します。 、その後、ダウンストリームにデータを転送します。今すぐに戻って方法、それを呼び出すことによって返すインスタンスを。例を考え変数があるなぜソースの戻り値の型で入力し、それを?これは、親クラス、以下のクラス図は、Java多型の機能を反映して、見ることができます。StreamExecutionEnvironment
socketTextStream
addSource
DataStreamSource
text
DataStream
DataStreamSource
DataStream
DataStreamSource
データフローの操作
以下のために、上記DataStreamSourceに取得するにはflatMap
、keyBy
、timeWindow
、reduce
スイッチング動作。
DataStream<WordWithCount> windowCounts = text
.flatMap(new FlatMapFunction<String, WordWithCount>() {
@Override
public void flatMap(String value, Collector<WordWithCount> out) {
for (String word : value.split("\\s")) {
out.collect(new WordWithCount(word, 1L));
}
}
})
.keyBy("word")
.timeWindow(Time.seconds(5))
.reduce(new ReduceFunction<WordWithCount>() {
@Override
public WordWithCount reduce(WordWithCount a, WordWithCount b) {
return new WordWithCount(a.word, a.count + b.count);
}
});
DataStreamSourceデータフローのトップに取得するには、このロジックは、作られたflatMap
、keyBy
、timeWindow
、reduce
4つの変換動作、については以下の言ったflatMap
3人の他の読者が自分の外観を理解するためにソースコードを表示しようとすることができ、変換、変換動作。
見てflatMap
、次のようにソースコードは、それに近づきます。
//代码目录:org/apache/flink/streaming/api/datastream/DataStream.java
public <R> SingleOutputStreamOperator<R> flatMap(FlatMapFunction<T, R> flatMapper) {
TypeInformation<R> outType = TypeExtractor.getFlatMapReturnTypes(clean(flatMapper),
getType(), Utils.getCallLocationName(), true);
return transform("Flat Map", outType, new StreamFlatMap<>(clean(flatMapper)));
}
反射取得するには、まず、二つのことがないflatMap
第二は、オペレータが生成され、出力演算子のタイプを。FLINKフロー計算は、プロセスの最終的な出力ストリームチェーンオペレータの送信にプロセスからの入力データ・ストリームの中核概念です。論理演算子に処理されたデータの各。上記のコードの最後の行transform
の効果は、メソッドを返すことであるSingleOutputStreamOperator
継承、Datastream
クラス及び対流を操作しやすいいくつかのヘルパーメソッドを定義します。戻る前に、transform
この方法はまた、実行環境に登録します。この下にはのFLINKストリーミングデータフローへのマッピングプログラムの概略図です。
結果出力
windowCounts.print().setParallelism(1);
各ソースFLINK手順は終了に沈み開始されるprint
方法は、標準出力ストリームシンクの計算結果です。様々なコネクタの実際の開発では、通常、カスタムの公式サイトやコネクタなどカフカ、HBaseの、ファイルシステムとしてデータシンク指定されたエリアに計算結果によって提供、Elasticsearchが好きです。ここでsetParallelism
、この受信機のために設けられた並列度であり、値がゼロよりも大きくなければなりません。
プログラムの実行
env.execute("Socket Window WordCount");
FLINKリモートモードとローカルモードは2つの実行モードがあり、二つのモードは、ここでローカルモードで解決するには、少し異なっています。見てexecute
、次のように、メソッドのソースコード:
//代码目录:org/apache/flink/streaming/api/environment/LocalStreamEnvironment.java
@Override
public JobExecutionResult execute(String jobName) throws Exception {
// transform the streaming program into a JobGraph
StreamGraph streamGraph = getStreamGraph();
streamGraph.setJobName(jobName);
JobGraph jobGraph = streamGraph.getJobGraph();
jobGraph.setAllowQueuedScheduling(true);
Configuration configuration = new Configuration();
configuration.addAll(jobGraph.getJobConfiguration());
configuration.setString(TaskManagerOptions.MANAGED_MEMORY_SIZE, "0");
// add (and override) the settings with what the user defined
configuration.addAll(this.configuration);
if (!configuration.contains(RestOptions.BIND_PORT)) {
configuration.setString(RestOptions.BIND_PORT, "0");
}
int numSlotsPerTaskManager = configuration.getInteger(TaskManagerOptions.NUM_TASK_SLOTS, jobGraph.getMaximumParallelism());
MiniClusterConfiguration cfg = new MiniClusterConfiguration.Builder()
.setConfiguration(configuration)
.setNumSlotsPerTaskManager(numSlotsPerTaskManager)
.build();
if (LOG.isInfoEnabled()) {
LOG.info("Running job on local embedded Flink mini cluster");
}
MiniCluster miniCluster = new MiniCluster(cfg);
try {
miniCluster.start();
configuration.setInteger(RestOptions.PORT, miniCluster.getRestAddress().get().getPort());
return miniCluster.executeJobBlocking(jobGraph);
}
finally {
transformations.clear();
miniCluster.close();
}
}
この方法は、3つの部分からなる:、ストリームJobGraphを変換するユーザ定義(又はカバー)の内容を追加するためのプログラムが提供され、そしてタスクを実行miniClusterを開始します。JobGraphについて一時的にすぐ隣、以下のミッションについてはこちらを言って、話すことはありませんreturn miniCluster.executeJobBlocking(jobGraph);
、次のように、ソース行を:
//代码目录:org/apache/flink/runtime/minicluster/MiniCluster.java
@Override
public JobExecutionResult executeJobBlocking(JobGraph job) throws JobExecutionException, InterruptedException {
checkNotNull(job, "job is null");
final CompletableFuture<JobSubmissionResult> submissionFuture = submitJob(job);
final CompletableFuture<JobResult> jobResultFuture = submissionFuture.thenCompose(
(JobSubmissionResult ignored) -> requestJobResult(job.getJobID()));
final JobResult jobResult;
try {
jobResult = jobResultFuture.get();
} catch (ExecutionException e) {
throw new JobExecutionException(job.getJobID(), "Could not retrieve JobResult.", ExceptionUtils.stripExecutionException(e);
}
try {
return jobResult.toJobExecutionResult(Thread.currentThread().getContextClassLoader());
} catch (IOException | ClassNotFoundException e) {
throw new JobExecutionException(job.getJobID(), e);
}
}
このコードのコアロジックがすることですfinal CompletableFuture<JobSubmissionResult> submissionFuture = submitJob(job);
呼び出すMiniCluster
クラスのsubmitJob
メソッドを、この方法を見てみましょう。
//代码目录:org/apache/flink/runtime/minicluster/MiniCluster.java
public CompletableFuture<JobSubmissionResult> submitJob(JobGraph jobGraph) {
final CompletableFuture<DispatcherGateway> dispatcherGatewayFuture = getDispatcherGatewayFuture();
// we have to allow queued scheduling in Flip-6 mode because we need to request slots
// from the ResourceManager
jobGraph.setAllowQueuedScheduling(true);
final CompletableFuture<InetSocketAddress> blobServerAddressFuture = createBlobServerAddress(dispatcherGatewayFuture);
final CompletableFuture<Void> jarUploadFuture = uploadAndSetJobFiles(blobServerAddressFuture, jobGraph);
final CompletableFuture<Acknowledge> acknowledgeCompletableFuture = jarUploadFuture
.thenCombine(
dispatcherGatewayFuture,
(Void ack, DispatcherGateway dispatcherGateway) -> dispatcherGateway.submitJob(jobGraph, rpcTimeout))
.thenCompose(Function.identity());
return acknowledgeCompletableFuture.thenApply(
(Acknowledge ignored) -> new JobSubmissionResult(jobGraph.getJobID()));
}
ここにあるDispatcher
ジョブ投入を受信するための責任を負うコンポーネント、彼らは、ジョブを実行したときにホスト障害、それらを復元するためにJobManagersを生成し、永続的です。Dispatcher
ローカル環境の下で始まっ2つの実装、ありますMiniDispatcher
クラスタ環境で起動するには、StandaloneDispatcher
。以下は、クラスの構成図です。
ここでは、だDispatcher
打ち上げJobManagerRunner
手数料をJobManagerRunner
ジョブの開始にJobMaster
。次のように対応するコードは以下のとおりです。
//代码目录:org/apache/flink/runtime/jobmaster/JobManagerRunner.java
private CompletableFuture<Void> verifyJobSchedulingStatusAndStartJobManager(UUID leaderSessionId) {
final CompletableFuture<JobSchedulingStatus> jobSchedulingStatusFuture = getJobSchedulingStatus();
return jobSchedulingStatusFuture.thenCompose(
jobSchedulingStatus -> {
if (jobSchedulingStatus == JobSchedulingStatus.DONE) {
return jobAlreadyDone();
} else {
return startJobMaster(leaderSessionId);
}
});
}
JobMaster
ネストされた方法の一連の呼び出しの後、最終的には論理の次の部分を実行します。
//代码目录:org/apache/flink/runtime/jobmaster/JobMaster.java
private void scheduleExecutionGraph() {
checkState(jobStatusListener == null);
// register self as job status change listener
jobStatusListener = new JobManagerJobStatusListener();
executionGraph.registerJobStatusListener(jobStatusListener);
try {
executionGraph.scheduleForExecution();
}
catch (Throwable t) {
executionGraph.failGlobal(t);
}
}
ここでexecutionGraph.scheduleForExecution();
呼ばれるExecutionGraph
起動方法。FLINKの構造を考慮すると、ExecutionGraph
実際のが行われる場合、実際の実装のプロセスに提出するためにここに、一つのタスクからまでのように、それが終わって、その後、ローカル環境では、以下のプロセスの実装を検討し、次のとおりです。
- クライアント実行
execute
方法; MiniCluster
タスクのほとんどを完了した後、直接にタスクを委任MiniDispatcher
。Dispatcher
ジョブを受信した後、インスタンス化JobManagerRunner
、そしてあなたは、このインスタンスでジョブを開始。JobManagerRunner
仕事に次JobMaster
に対処します。JobMaster
使用してExecutionGraph
マップ全体を開始するために実行する方法を、全体のタスクが起動されます。