SparkStreaming自定义Receiver

接触spark已经有一些时间了,线上跑的spark的版本是基于spark1.5的版本,一次业务需求,要上实时处理,一起我们也搭建过一套基于storm的实时处理平台,后来数据平台重新搭建之后,我们上了spark,因为在spark生态栈里已经包含了realtime的处理模块,再加上我们的业务对实时要求并不是特别高,鉴于系统的维护成本,我们在技术选型上决定上SparkStreaming来进行实时处理。

在Spark1.3的时候SparkStreaming已经支持了很多种的数据接入途径,我们常用的如kafka系统接入的两种方式,最开始是基于receiver方式,在1.3之后出来了另一种新的并且更加高效的API,那就是基于kafka,Direct方式,这种方式开发更加简洁,更加智能,效率更加高效,我们线上一直使用这种方式,效果比较满意。

接下来我们来自定义一种SparkStreaming数据流的接入方式,满足我们的个性化需求。

Spark Streaming Custom Receivers

Spark Streaming can receive streaming data from any arbitrary data source beyond the ones for which it has built-in support (that is, beyond Flume, Kafka, Kinesis, files, sockets, etc.). This requires the developer to implement a receiver that is customized for receiving data from the concerned data source. This guide walks through the process of implementing a custom receiver and using it in a Spark Streaming application. Note that custom receivers can be implemented in Scala or Java.【sparkStreaming支持任意类型的数据流进行接入,目前已经实现了如kafka,flume等接入方式。这些接入方式都必须实现receiver这样一个接口,通过实现该接口我们就可以自定义我们的Receiver了

Implementing a Custom Receiver

This starts with implementing a Receiver (Scala docJava doc). A custom receiver must extend this abstract class by implementing two methods

  • onStart(): Things to do to start receiving data.
  • onStop(): Things to do to stop receiving data.

Both onStart() and onStop() must not block indefinitely.【onStart和onStop方法是不能阻塞的】 Typically, onStart() would start the threads that are responsible for receiving the data, and onStop() would ensure that these threads receiving the data are stopped. 【通常在onStart中开启线程去接受数据,在onStop方法确保线程都接受完数据之后进行关闭】The receiving threads can also use isStopped(), a Receivermethod, to check whether they should stop receiving data.

Once the data is received, that data can be stored inside Spark by calling store(data), which is a method provided by the Receiver class. There are a number of flavors of store() which allow one to store the received data record-at-a-time or as whole collection of objects / serialized bytes. Note that the flavor of store() used to implement a receiver affects its reliability and fault-tolerance semantics. This is discussed later in more detail.

Any exception in the receiving threads should be caught and handled properly to avoid silent failures of the receiver. restart(<exception>) will restart the receiver by asynchronously calling onStop() and then calling onStart() after a delay. stop(<exception>) will call onStop() and terminate the receiver. Also, reportError(<error>) reports an error message to the driver (visible in the logs and UI) without stopping / restarting the receiver.

The following is a custom receiver that receives a stream of text over a socket. It treats ‘\n’ delimited lines in the text stream as records and stores them with Spark. If the receiving thread has any error connecting or receiving, the receiver is restarted to make another attempt to connect.

public class JavaCustomReceiver extends Receiver<String> {

  String host = null;
  int port = -1;

  public JavaCustomReceiver(String host_ , int port_) {
    super(StorageLevel.MEMORY_AND_DISK_2());
    host = host_;
    port = port_;
  }

  public void onStart() {
    // Start the thread that receives data over a connection
    new Thread()  {
      @Override public void run() {
        receive();
      }
    }.start();
  }

  public void onStop() {
    // There is nothing much to do as the thread calling receive()
    // is designed to stop by itself if isStopped() returns false
  }

  /** Create a socket connection and receive data until receiver is stopped */
  private void receive() {
    Socket socket = null;
    String userInput = null;

    try {
      // connect to the server
      socket = new Socket(host, port);

      BufferedReader reader = new BufferedReader(
        new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));

      // Until stopped or connection broken continue reading
      while (!isStopped() && (userInput = reader.readLine()) != null) {
        System.out.println("Received data '" + userInput + "'");
        store(userInput);
      }
      reader.close();
      socket.close();

      // Restart in an attempt to connect again when server is active again
      restart("Trying to connect again");
    } catch(ConnectException ce) {
      // restart if could not connect to server
      restart("Could not connect", ce);
    } catch(Throwable t) {
      // restart if there is any other error
      restart("Error receiving data", t);
    }
  }
}

Using the custom receiver in a Spark Streaming application

The custom receiver can be used in a Spark Streaming application by using streamingContext.receiverStream(<instance of custom receiver>). This will create an input DStream using data received by the instance of custom receiver, as shown below:

// Assuming ssc is the JavaStreamingContext
JavaDStream<String> customReceiverStream = ssc.receiverStream(new JavaCustomReceiver(host, port));
JavaDStream<String> words = lines.flatMap(new FlatMapFunction<String, String>() { ... });
...
java方式:https://github.com/apache/spark/blob/v2.1.0/examples/src/main/java/org/apache/spark/examples/streaming/JavaCustomReceiver.java
scala方式:https://github.com/apache/spark/blob/v2.1.0/examples/src/main/scala/org/apache/spark/examples/streaming/CustomReceiver.scala


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值