我正在开发一个Spark Streaming程序,该程序检索Kafka流,对流进行非常基本的转换,然后将数据插入到DB(如果相关的话,则为voltdb)。 我试图测量我向DB插入行的速率。我认为metrics可能很有用(使用JMX)。但是,我无法找到如何向Spark添加自定义指标。我查看了Spark的源代码,并找到了this thread,但它对我来说并不起作用。我还在conf.metrics文件中启用了JMX接收器。什么不起作用是我没有通过JConsole看到我的自定义指标。
有人可以解释如何添加自定义指标(最好通过JMX)来激发流媒体?或者如何测量我的数据库(特别是VoltDB)的插入速率? 我在Java 8中使用spark。
答案 0 :(得分:15)
在深入了解source code后,我发现了如何添加自己的自定义指标。它需要3件事:
答案 1 :(得分:5)
Groupon有一个名为spark-metrics
的库,它允许您在执行程序上使用简单的(类似Codahale)API,并将结果整理回驱动程序中并自动在Spark的现有指标注册表中注册。然后,当您根据Spark docs配置指标接收器时,这些会随着Spark的内置指标自动导出。
答案 2 :(得分:3)
从VoltDB中插入基于插入的行,使用累加器 - 然后从你的驱动程序中创建一个监听器 - 可能是这样的东西让你入门
sparkContext.addSparkListener(new SparkListener() {
override def onStageCompleted(stageCompleted: SparkListenerStageCompleted) {
stageCompleted.stageInfo.accumulables.foreach { case (_, acc) => {
在这里你可以访问那些组合累加器的行,然后你可以发送到你的接收器..
答案 3 :(得分:2)
这是一个很好的教程,涵盖了使用Graphite设置Spark的MetricsSystem所需的所有设置。这应该是诀窍:
http://www.hammerlab.org/2015/02/27/monitoring-spark-with-graphite-and-grafana/
答案 4 :(得分:0)
下面是Java中的一个有效示例。
已通过StreaminQuery
进行了测试(不幸的是,StreaminQuery
在Spark 2.3.1之前没有像StreamingContext
这样的ootb指标)。
步骤:
在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(event)中的数据
querySource.updateProgress(event.progress());
配置metrics.properties
*.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