Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/apache-kafka/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache spark 如何获得spark结构化流媒体应用程序的kafka消费者延迟_Apache Spark_Apache Kafka_Spark Structured Streaming - Fatal编程技术网

Apache spark 如何获得spark结构化流媒体应用程序的kafka消费者延迟

Apache spark 如何获得spark结构化流媒体应用程序的kafka消费者延迟,apache-spark,apache-kafka,spark-structured-streaming,Apache Spark,Apache Kafka,Spark Structured Streaming,我正在为spark结构化流媒体应用程序构建监控,需要获得spark应用程序使用的特定主题的消费者延迟。我相信spark驱动程序必须意识到这种延迟,因为它拥有执行者的所有元数据。我不认为有任何方法可以从任何现有的spark文档或资源中获取这些指标。我签出了streaminQueryListener接口,但它的功能也很有限,因为我们只能从中获取每个查询的指标 下面是一种获取执行器节点上请求的信息的方法。每封邮件都会获取信息,您可以通过最适合您需要的方式(计数、时间等)减少请求量 下面我将监控信息发送

我正在为spark结构化流媒体应用程序构建监控,需要获得spark应用程序使用的特定主题的消费者延迟。我相信spark驱动程序必须意识到这种延迟,因为它拥有执行者的所有元数据。我不认为有任何方法可以从任何现有的spark文档或资源中获取这些指标。我签出了
streaminQueryListener
接口,但它的功能也很有限,因为我们只能从中获取每个查询的指标

下面是一种获取执行器节点上请求的信息的方法。每封邮件都会获取信息,您可以通过最适合您需要的方式(计数、时间等)减少请求量

下面我将监控信息发送到另一个卡夫卡主题

我经常打开Kafka consumer connection(获取有关最大偏移量的信息),查看每一批流式消息。也许你不能接受

final JavaInputDStream<ConsumerRecord<String, byte[]>> stream = KafkaUtils.createDirectStream(jssc, LocationStrategies.PreferConsistent(),
        ConsumerStrategies.<String, byte[]>Subscribe(topics, kafkaParams));


JavaPairDStream<String, Income> streamPair = stream
.mapPartitionsToPair(new PairFlatMapFunction<Iterator<ConsumerRecord<String, byte[]>>, String, Income>() {

    private Map<String, Object> getProps() {
        Map<String, Object> kafkaParams2 = new HashMap<>();
        kafkaParams2.put("bootstrap.servers", ApiConsts.BOOTSTRAP_SERVERS);
        kafkaParams2.put("key.deserializer", StringDeserializer.class);
        kafkaParams2.put("value.deserializer", ByteArrayDeserializer.class);
        kafkaParams2.put("group.id", "ta_calc_spark" + UUID.randomUUID().toString());
        kafkaParams2.put("auto.offset.reset", "latest");
        kafkaParams2.put("enable.auto.commit", false);
        kafkaParams2.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, 30);
        kafkaParams2.put(ConsumerConfig.MAX_POLL_INTERVAL_MS_CONFIG, 1000);
        return kafkaParams2;
    }

    @Override
    public Iterator<Tuple2<String, Income>> call(Iterator<ConsumerRecord<String, byte[]>> t) throws Exception {
        KafkaConsumer consumer = new KafkaConsumer<>(getProps());

        ArrayList<TopicPartition> partitions0 = new ArrayList<TopicPartition>();
        IntStream.range(0, consumer.partitionsFor(ApiConsts.TOPIC_TA_CALC_SPARK_TASK).size())
                .forEach(i -> partitions0.add(new TopicPartition(ApiConsts.TOPIC_TA_CALC_SPARK_TASK, i)));
        consumer.assign(partitions0);
        KafkaProducer producerMonitoring = getKafkaProducer();

        List<Tuple2<String, Income>> result = new ArrayList<Tuple2<String, Income>>();
        try {
            t.forEachRemaining(t2 -> {
                // business logic - message handling

                try {
                    Set<TopicPartition> partitions = new HashSet<TopicPartition>();
                    TopicPartition actualTopicPartition = new TopicPartition(ApiConsts.TOPIC_TA_CALC_SPARK_TASK, t2.partition());
                    partitions.add(actualTopicPartition);
                    Long actualEndOffset = (Long) consumer.endOffsets(partitions).get(actualTopicPartition);
                    long actualPosition = consumer.position(actualTopicPartition);
                    String monitorValue = String.format(
                            "diff: %s   (partition:%s; actualEndOffsetStreaming:%s; actualEndOffset:%s; actualPosition=%s)",
                            actualEndOffset - actualPosition, t2.partition(), t2.offset(), actualEndOffset, actualPosition);
                    ProducerRecord<String, String> pRecord = new ProducerRecord<String, String>(ApiConsts.TOPIC_TA_CALC_SPARK_TEMP_RESULT,
                            UUID.randomUUID().toString(), monitorValue);
                    producerMonitoring.send(pRecord);
                } catch (Exception ex) {
                    log.error("################# mapPartitionsToPair.call() ERROR", ex);
                    ex.printStackTrace();
                }
            });
        } finally {
            producerMonitoring.close();
            consumer.close();
        }
        return result.iterator();
    }
});

跟踪结构化流媒体作业的消费者延迟的挑战在于,结构化流媒体不会将任何补偿提交回卡夫卡(有关更多详细信息,请参阅)。因此,卡夫卡并不知道结构化流媒体作业的实际进度

另一方面,Spark无法洞察当前卡夫卡主题中的消息/偏移量

为了监控消费者滞后,您需要将这些信息汇集在一起:

  • 连续请求TopicPartition内的最新偏移量
  • 持续检查结构化流媒体应用程序处理的当前偏移量
例如,您可以创建一个Kafka
AdminClient
,并在
onQueryProgress
调用
StreamingQueryListener
期间从Kafka获取所需信息。在该方法中,您需要将最新事件的上述偏移量与卡夫卡中可用的实际最高偏移量进行比较

Consumer Record:(f45cd24b-6232-45b2-b8f2-814753ae89bf, diff: 0   (partition:4; actualEndOffsetStreaming:1177; actualEndOffset:1178; actualPosition=1178), 2, 109)
Consumer Record:(3ec4f576-1fff-4c91-885f-fc709f7f4531, diff: 0   (partition:4; actualEndOffsetStreaming:1176; actualEndOffset:1178; actualPosition=1178), 3, 105)