Пользовательские метрики потоковой передачи Spark

Я работаю над программой Spark Streaming, которая извлекает поток Кафки, выполняет очень базовое преобразование в потоке, а затем вставляет данные в БД (voltdb, если это актуально). Я пытаюсь измерить скорость, с которой я вставляю строки в БД. Я думаю показатели может быть полезно (используя JMX). Однако я не могу найти, как добавить пользовательские метрики в Spark. Я посмотрел исходный код Spark, а также нашел этой теме однако это не работает для меня. Я также включен JMX тонет в конф.файл метрик. Что не работает, так это то, что я не вижу свои пользовательские метрики с JConsole.

может кто-нибудь объяснить, как добавить пользовательские метрики (желательно через JMX) в Spark streaming? Или альтернативно, как измерить скорость вставки в мой DB (в частности, VoltDB)? Я использую spark с Java 8.

5 ответов


Ok после копания через исходный код Я нашел, как добавить свои собственные метрики. Требуется 3 вещи:

  1. создать свой собственный источник. Вроде как этой
  2. включить приемник Jmx в метриках spark.файл свойств. Конкретная строка, которую я использовал:*.sink.jmx.class=org.apache.spark.metrics.sink.JmxSink которые включают JmxSink для всех экземпляров
  3. зарегистрируйте мой пользовательский источник в системе метрик SparkEnv. Пример как это сделать можно видел здесь - Я действительно просматривал эту ссылку раньше, но пропустил часть регистрации, которая помешала мне увидеть мои пользовательские показатели в JVisualVM

Я все еще борюсь с тем, как на самом деле подсчитать количество вставок в VoltDB, потому что код работает на исполнителях, но это тема для другой темы :)

Я надеюсь, что это поможет другим


Groupon имеют библиотеку под названием spark-metrics это позволяет использовать простой (Codahale-подобный) API на ваших исполнителях и сопоставлять результаты в драйвере и автоматически регистрироваться в существующем реестре метрик Spark. Затем они автоматически экспортируются вместе со встроенными метриками Spark при настройке приемника метрик в соответствии с Spark docs.


чтобы вставить строки из на основе вставок из VoltDB, используйте аккумуляторы - а затем из вашего драйвера вы можете создать прослушиватель-может быть, что-то вроде этого, чтобы вы начали

sparkContext.addSparkListener(new SparkListener() {
  override def onStageCompleted(stageCompleted: SparkListenerStageCompleted) {
    stageCompleted.stageInfo.accumulables.foreach { case (_, acc) => {

здесь у вас есть доступ к этим строкам комбинированных аккумуляторов, а затем вы можете отправить в раковину..


вот отличный учебник, который охватывает все setps вам нужно настроить MetricsSystem СПАРК с графитом. Это должно сделать трюк:

http://www.hammerlab.org/2015/02/27/monitoring-spark-with-graphite-and-grafana/


Ниже приведен рабочий пример на Java.
Он протестирован с StreaminQuery (к сожалению StreaminQuery не имеет показателей ootb, таких как StreamingContext пока искра 2.3.1).

действия:

определите пользовательский источник в том же пакете Source класс

package org.apache.spark.metrics.source;

import com.codahale.metrics.Gauge;
import com.codahale.metrics.MetricRegistry;
import lombok.Data;
import lombok.experimental.Accessors;
import org.apache.spark.sql.streaming.StreamingQueryProgress;

/**
 * Metrics source for structured streaming query.
 */
public class StreamingQuerySource implements Source {
    private String appName;
    private MetricRegistry metricRegistry = new MetricRegistry();
    private final Progress progress = new Progress();

    public StreamingQuerySource(String appName) {
        this.appName = appName;
        registerGuage("batchId", () -> progress.batchId());
        registerGuage("numInputRows", () -> progress.numInputRows());
        registerGuage("inputRowsPerSecond", () -> progress.inputRowsPerSecond());
        registerGuage("processedRowsPerSecond", () -> progress.processedRowsPerSecond());
    }

    private <T> Gauge<T> registerGuage(String name, Gauge<T> metric) {
        return metricRegistry.register(MetricRegistry.name(name), metric);
    }

    @Override
    public String sourceName() {
        return String.format("%s.streaming", appName);
    }


    @Override
    public MetricRegistry metricRegistry() {
        return metricRegistry;
    }

    public void updateProgress(StreamingQueryProgress queryProgress) {
        progress.batchId(queryProgress.batchId())
                .numInputRows(queryProgress.numInputRows())
                .inputRowsPerSecond(queryProgress.inputRowsPerSecond())
                .processedRowsPerSecond(queryProgress.processedRowsPerSecond());
    }

    @Data
    @Accessors(fluent = true)
    private static class Progress {
        private long batchId = -1;
        private long numInputRows = 0;
        private double inputRowsPerSecond = 0;
        private double processedRowsPerSecond = 0;
    }
}

зарегистрировать источник сразу после создания SparkContext

    querySource = new StreamingQuerySource(getSparkSession().sparkContext().appName());
    SparkEnv.get().metricsSystem().registerSource(querySource);

обновление данных в StreamingQueryListener.onProgress(событие)

  querySource.updateProgress(event.progress());

метрики конфигурации.свойства

*.sink.graphite.class=org.apache.spark.metrics.sink.GraphiteSink
*.sink.graphite.host=xxx
*.sink.graphite.port=9109
*.sink.graphite.period=10
*.sink.graphite.unit=seconds

# Enable jvm source for instance master, worker, driver and executor
master.source.jvm.class=org.apache.spark.metrics.source.JvmSource
worker.source.jvm.class=org.apache.spark.metrics.source.JvmSource
driver.source.jvm.class=org.apache.spark.metrics.source.JvmSource
executor.source.jvm.class=org.apache.spark.metrics.source.JvmSource

выход образца в экспортере графита (сопоставленный с форматом Прометея)

streaming_query{application="local-1538032184639",model="model1",qty="batchId"} 38
streaming_query{application="local-1538032184639",model="model1r",qty="inputRowsPerSecond"} 2.5
streaming_query{application="local-1538032184639",model="model1",qty="numInputRows"} 5
streaming_query{application="local-1538032184639",model=model1",qty="processedRowsPerSecond"} 0.81