流启动后生成Spark Stream新作业

时间:2018-07-14 16:49:31

标签: java apache-spark apache-kafka streaming spark-streaming

我遇到一种情况,我试图使用来自kafka的spark流进行流式处理。流是直接流。我能够创建一个流,然后开始流,也可以通过流在kafka上获取任何更新(如果有的话)。

当我有一个新请求以流式传输新主题时出现问题。由于每个jvm的SparkStreaming上下文只能为1,因此我无法为每个新请求创建一个新流。

我发现的方法是

  1. 一旦创建了DStream并且火花流已经在进行中,只需将新的流附加到它。这似乎不起作用,对于新的topic2,createDStream不返回流,并且停止了进一步的处理。流媒体会继续响应第一个请求(例如topic1)。

  2. 第二,我想停止流,创建DStream,然后再次开始流。我不能使用相同的流上下文(流停止后将无法添加作业),并且如果我为新主题(topic2)创建新流,则旧流主题(topic1)丢失并且流只有新的。

这是代码,看看

 JavaStreamingContext javaStreamingContext;
        if(null == javaStreamingContext) {
            javaStreamingContext =  JavaStreamingContext(sparkContext, Durations.seconds(duration));
        } else {
            StreamingContextState streamingContextState = javaStreamingContext.getState();
            if(streamingContextState == StreamingContextState.STOPPED) {
                javaStreamingContext =  JavaStreamingContext(sparkContext, Durations.seconds(duration));
            }


        }
Collection<String> topics = Arrays.asList(getTopicName(schemaName));
        SparkVoidFunctionImpl impl = new SparkVoidFunctionImpl(getSparkSession());

        KafkaUtils.createDirectStream(javaStreamingContext,
                LocationStrategies.PreferConsistent(),
                ConsumerStrategies.<String, String>Subscribe(topics, getKafkaParamMap()))
                .map((stringStringConsumerRecord) -> stringStringConsumerRecord.value())
                .foreachRDD(impl);
if (javaStreamingContext.getState() == StreamingContextState.ACTIVE) {

            javaStreamingContext.start();
            javaStreamingContext.awaitTermination();
        }

不用担心SparkVoidFunctionImpl,这是一个自定义类,是VoidFunction的实现。

以上是方法1,其中我不停止现有的流式传输。当新请求进入此方法时,它不会获得新的流对象,而是尝试创建dstream。问题是永远不会返回DStream对象。

KafkaUtils.createDirectStream(javaStreamingContext,
                    LocationStrategies.PreferConsistent(),
                    ConsumerStrategies.<String, String>Subscribe(topics, getKafkaParamMap()))

这不返回dstream,控件只是终止而没有错误。进一步的步骤将不执行。

我已经尝试了很多事情并阅读了多篇文章,但是我相信这是一个非常常见的生产级别问题。任何流式处理都必须在多个不同的主题上进行,并且每个主题的处理方式都不同。

请帮助

1 个答案:

答案 0 :(得分:1)

问题是spark master向工作人员发送代码,尽管数据正在流式传输,但除非重新启动作业,否则底层代码和变量值将保持不变。

我想不到的几种选择:

  1. Spark Job服务器:每次您要从其他主题订阅/流式播放而不是触摸已经在运行的作业时,就开始一个新作业。您可以从API主体中提供参数或主题名称。如果要停止特定主题的流式传输,只需停止相应的作业即可。它将为您提供很大的灵活性和对资源的控制。

  2. [理论]主题过滤器:订阅您认为想要的所有主题,当记录被拉长一段时间后,将根据主题列表过滤出记录。通过API处理此主题列表以增加或减小主题范围,它也可以是广播变量。这只是一个想法,我根本没有尝试过此选项。

  3. 另一种解决方法是在需要时使用微服务将Topic-2数据中继到Topic-1,并在不需要时停止。