SparkStreaming + Flumeストリームコンピューティング

SparkStreaming + Flumeメソッドは初期のフォームです。新しいバージョンのSparkでは、Flumeに直接接続することはお勧めしませんが、データを処理するためにこのフォームが必要になる場合があります。

SparkはFlumeのデータを統合します。Sparkには、ポーリングプルとプッシュプッシュの2つの方法があります。2つのモードと比較して、ポーリングモードが優先されます。

プルモードでは、Sparkがシンクを提供し、SparkStreamingが主導権を握ってチャネルからデータを取得し、安定性の高い独自の条件に従ってデータを取得します。

プッシュモードでは、Flumeはキャッシュとして機能し、データを保存します。そして、Sparkを監視し、Sparkに到達できる場合は、データをプッシュします。(単純な低結合)欠点は、SparkStreamingプログラムが開始されていない場合、Flume側でエラーが報告され、SparkStreamingプログラムがデータを失うのが遅すぎて消費できない可能性があることです。

まず、Pollでデータをプルする方法を紹介します

次のように、jarをインポートする必要があります

<dependency>
    <groupId>org.apache.spark</groupId>
    <artifactId>spark-streaming-flume_2.11</artifactId>
    <version>2.0.2</version>
</dependency>

Pollをプルするときは、Flumeのバージョンが1.6以上である必要があり、1.8を使用し、flumeのlibディレクトリに2つのjarがあることを確認する必要があることに注意してください。私のバージョンは次のとおりです。

scala-library-2.11.8.jar 
spark-streaming-flume-sink_2.11-2.0.2.jar

scala-library-2.11.8.jarは、libに配置した後、名前をscala-library-2.10.5.jar.BAKに変更する必要があります。

以下はFlumeのエージェントを書くことです、ソースはncツールを使用します、あなたはあなた自身のエージェントを使うこともできます

a1.sources = r1
a1.sinks = k1
a1.channels = c1

#  source需要改动的是源和目的地,此处是源,使用nc工具
a1.sources.r1.type = netcat
a1.sources.r1.bind = localhost
a1.sources.r1.port = 44444

# Describe the sink 需要改动的是源和目的地,此处是目的地,且为Spark配置一个连接的地址
a1.sinks.k1.type = org.apache.spark.streaming.flume.sink.SparkSink
a1.sinks.k1.hostname=192.168.182.146
a1.sinks.k1.port = 8888
a1.sinks.k1.batchSize= 2000 


# Use a channel which buffers events in memory
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100

# Bind the source and sink to the channel
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1

水路を開始します

bin/flume-ng agent --conf conf --conf-file conf/socket-source.properties --name a1 -Dflume.root.logger=INFO,console

水路が開始された後、以前に設定されたncポートを介してデータを生成でき、Pollメソッドはエラーを報告せず、データはチャネルに一時的に保存されます。

コードを書いて始めましょう

package com.stream

import org.apache.spark.{
    
    SparkConf}
import org.apache.spark.streaming.flume.{
    
    FlumeUtils}
import org.apache.spark.streaming.{
    
    Seconds, StreamingContext}

object StreamFromFlume {
    
    
  def main(args: Array[String]): Unit = {
    
    
    val conf = new SparkConf().setAppName("StreamFromKafka").setMaster("local[2]")
    val scc = new StreamingContext(conf,Seconds(10))
    //设置checkpoint,可以忽略
    scc.checkpoint("D:\\checkpoint")
    // 从flume中拉取数据 这里的ip和端口是你agent中sink配置的
    val flumeStream = FlumeUtils.createPollingStream(scc,"192.168.182.146",8888)
    
    val lineStream= flumeStream.map(x=>new String(x.event.getBody.array()))

    //实现单词汇总
    val result = lineStream.flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_)

    result.print()
    scc.start()
    scc.awaitTermination()
  }

}

次に、データをプッシュするプッシュ方式を紹介します

データをプッシュするのは、Flumeが主導権を握っているため、あまりお勧めできません。また、作業で使用される可能性は低いです。結局のところ、データの損失はデータプロジェクトにとって不快な時間です。

Pushのときに最初Sparkを起動する必要あります。次に、Flume自体が所有するavroシリアル化を使用して、Pushが主導権を握るFlumeです。この方法では、Sparkだけでなくほとんどのフレームワークにデータを実際にプッシュできます。

受信コードとPollの違いは、APIが変更されたことです。

package com.stream

import org.apache.spark.{
    
    SparkConf}
import org.apache.spark.streaming.flume.{
    
    FlumeUtils}
import org.apache.spark.streaming.{
    
    Seconds, StreamingContext}

object StreamFromFlume {
    
    
  def main(args: Array[String]): Unit = {
    
    
    val conf = new SparkConf().setAppName("StreamFromKafka").setMaster("local[2]")
    val scc = new StreamingContext(conf,Seconds(10))
    //设置checkpoint,用来提高数据消费的安全
    scc.checkpoint("D:\\checkpoint")
    // ip和port任然是Flume配置文件中的
    val flumeStream: ReceiverInputDStream[SparkFlumeEvent] = FlumeUtils.createStream(scc,"192.168.182.146",8888,StorageLevel.MEMORY_AND_DISK)
    
    val lineStream= flumeStream.map(x=>new String(x.event.getBody.array()))

    //实现单词汇总
    val result = lineStream.flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_)

    result.print()
    scc.start()
    scc.awaitTermination()
  }

}

Spark Pushメソッドが開始された後、通常はFlumeがデータをプッシュするのを待ちます。次に、Flume側の準備を開始します。

a1.sources = r1
a1.sinks = k1
a1.channels = c1

#  source需要改动的是源和目的地,此处是源,使用nc工具
a1.sources.r1.type = netcat
a1.sources.r1.bind = localhost
a1.sources.r1.port = 44444

# Describe the sink 需要改动的是源和目的地
a1.sinks.k1.type = avro
a1.sinks.k1.hostname=192.168.182.146
a1.sinks.k1.port = 8888


# Use a channel which buffers events in memory
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100

# Bind the source and sink to the channel
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1

Flumeを起動した後、Sparkをチェックし、ncツールにデータを入力すると、対応する出力がSparkにあることがわかります。


最後に、補足を作成します。次のエラーの途中で2つのモードを実行すると、次のエラーが発生します。
org.apache.avro.AvroRuntimeException: Unknown datum type: java.lang.Exception: 
java.lang.NoClassDefFoundError: Could not initialize class 
org.apache.spark.streaming.flume.sink.EventBatch 

このエラーは、Flumeのavroシリアル化バージョンがSparkと互換性がないためです。個別にインポートする必要があります。pomファイルに次のjarをインポートしてください。

<dependency>
	<groupId>org.apache.avro</groupId>
	<artifactId>avro</artifactId>
<version>1.8.2</version>
</dependency>
<dependency>
	<groupId>org.apache.avro</groupId>
	<artifactId>avro-ipc</artifactId>
	<version>1.8.2</version>
</dependency>

そして、これら2つのjarファイルをFlumeのlibディレクトリにコピーし、lib内の元のjarファイルを削除します。

おすすめ

転載: blog.csdn.net/dudadudadd/article/details/115005546