Apache Spark-在流事件中捕获Kafka数据以触发工作流

时间:2018-10-11 16:43:12

标签: java scala apache-spark cassandra apache-kafka

简而言之,我是一名开发人员,尝试使用Spark将数据从一个系统移动到另一个系统。在一个系统中将原始数据整理,汇总成一个本地分析系统。

我对Spark还是很陌生-我的知识仅限于过去一两周我能够挖掘和尝试的知识。

我所描绘的是;使用Spark监视来自Kafka的事件作为触发。在消费者事件中捕获该实体/数据,并使用它来告诉我在分析系统中需要更新的内容。然后,我将对原始的Cassandra数据运行相关的Spark查询,并将结果写入到分析侧的另一张表中,仪表板指标将其称为数据源。

我有一个简单的Kafka结构化流查询工作。虽然我可以看到消耗的对象已输出到控制台,但是当使用者事件发生时,我无法检索Kafka记录:

try {
    SparkSession spark = SparkSession
        .builder()
        .master(this.sparkMasterAddress)
        .appName("StreamingTest2")
        .getOrCreate();

    //THIS -> None of these events seem to give me the data consumed?
    //...thinking I'd trigger the Cassandra write from here?
    spark.streams().addListener(new StreamingQueryListener() {
        @Override
        public void onQueryStarted(QueryStartedEvent queryStarted) {
            System.out.println("Query started: " + queryStarted.id());
        }
        @Override
        public void onQueryTerminated(QueryTerminatedEvent queryTerminated) {
            System.out.println("Query terminated: " + queryTerminated.id());
        }
        @Override
        public void onQueryProgress(QueryProgressEvent queryProgress) {
            System.out.println("Query made progress: " + queryProgress.progress());
        }
    });

    Dataset<Row> reader = spark
        .readStream()
        .format("kafka")
        .option("startingOffsets", "latest")
        .option("kafka.bootstrap.servers", "...etc...")
        .option("subscribe", "my_topic")
        .load();

    Dataset<String> lines = reader
        .selectExpr("cast(value as string)")
        .as(Encoders.STRING());

    StreamingQuery query = lines
        .writeStream()
        .format("console")
        .start();
    query.awaitTermination();
} catch (Exception e) {
    e.printStackTrace();
}

我还可以通过Spark SQL查询Cassandra:

try {
    SparkSession spark = SparkSession.builder()
        .appName("SparkSqlCassandraTest")
        .master("local[2]")
        .getOrCreate();

    Dataset<Row> reader = spark
        .read()
        .format("org.apache.spark.sql.cassandra")
        .option("host", this.cassandraAddress)
        .option("port", this.cassandraPort)
        .option("keyspace", "my_keyspace")
        .option("table", "my_table")
        .load();

    reader.printSchema();
    reader.show();

    spark.stop();
} catch (Exception e) {
    e.printStackTrace();
}

我的想法是;使用前者触发后者,将其捆绑为Spark应用程序/程序包/任何东西,并将其部署到spark中。到那时,我希望它能够不断将更新推送到指标表。

这将是我需要的可行,可扩展,合理的解决方案吗?我在正确的道路上吗?如果某种程度上更轻松或更佳,则不反对使用Scala。

谢谢!

编辑:这是我遇到的挑战的图。

enter image description here

1 个答案:

答案 0 :(得分:0)

知道了。了解了有关ForeachWriter的信息。效果很好:

        StreamingQuery query = lines
            .writeStream()
            .format("foreach")
            .foreach(new ForeachWriter<String>() {
                @Override
                public void process(String value) {
                    System.out.println("process() value = " + value);
                }

                @Override
                public void close(Throwable errorOrNull) {}

                @Override
                public boolean open(long partitionId, long version) {
                    return true;
                }
            })
            .start();