Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/340.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.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
Java 在Spark Executors上向Kafka提交偏移量_Java_Apache Spark_<img Src="//i.stack.imgur.com/RUiNP.png" Height="16" Width="18" Alt="" Class="sponsor Tag Img">elasticsearch_Apache Kafka - Fatal编程技术网 elasticsearch,apache-kafka,Java,Apache Spark,elasticsearch,Apache Kafka" /> elasticsearch,apache-kafka,Java,Apache Spark,elasticsearch,Apache Kafka" />

Java 在Spark Executors上向Kafka提交偏移量

Java 在Spark Executors上向Kafka提交偏移量,java,apache-spark,elasticsearch,apache-kafka,Java,Apache Spark,elasticsearch,Apache Kafka,我从卡夫卡那里获取事件,在Spark上丰富/过滤/转换它们,然后将它们存储在ES中。我要把补偿交还给卡夫卡 我有两个问题: (1)我目前的Spark工作非常缓慢 我有50个主题分区和20个执行器。每个执行器都有2个内核和4g内存。我的司机有8g内存。我每秒消耗1000个事件/分区,批处理间隔为10秒。这意味着,我在10秒内消耗了500000个事件 我的ES群集如下所示: 20分片/索引 3个主实例c5.xlarge.elasticsearch 12个实例m4.xlarge.elasticsear

我从卡夫卡那里获取事件,在Spark上丰富/过滤/转换它们,然后将它们存储在ES中。我要把补偿交还给卡夫卡

我有两个问题:

(1)我目前的Spark工作非常缓慢

我有50个主题分区和20个执行器。每个执行器都有2个内核和4g内存。我的司机有8g内存。我每秒消耗1000个事件/分区,批处理间隔为10秒。这意味着,我在10秒内消耗了500000个事件

我的ES群集如下所示:

20分片/索引

3个主实例c5.xlarge.elasticsearch

12个实例m4.xlarge.elasticsearch

磁盘/节点=1024 GB,总共12 TB

我得到了巨大的日程安排和处理延迟

(2)如何在执行器上提交偏移量?

目前,我在executors上丰富/转换/过滤我的事件,然后使用BulkRequest将所有内容发送到ES。这是一个同步过程。如果我得到肯定的反馈,我会将偏移列表发送给驱动程序。如果没有,我会发回一个空列表。在驱动程序上,我向卡夫卡提交偏移量。我相信,应该有一种方法,我可以在执行者身上提交补偿,但我不知道如何将卡夫卡流传递给执行者:

((CanCommitOffsets) kafkaStream.inputDStream()).commitAsync(offsetRanges, this::onComplete);
这是向Kafka提交偏移量的代码,它需要Kafka流

以下是我的总体代码:

 kafkaStream.foreachRDD( // kafka topic
                rdd -> { // runs on driver
                    rdd.cache();
                    String batchIdentifier =
                            Long.toHexString(Double.doubleToLongBits(Math.random()));

                    LOGGER.info("@@ [" + batchIdentifier + "] Starting batch ...");

                    Instant batchStart = Instant.now();

                    List<OffsetRange> offsetsToCommit =
                            rdd.mapPartitionsWithIndex( // kafka partition
                                    (index, eventsIterator) -> { // runs on worker

                                        OffsetRange[] offsetRanges = ((HasOffsetRanges) rdd.rdd()).offsetRanges();

                                        LOGGER.info(
                                                "@@ Consuming " + offsetRanges[index].count() + " events" + " partition: " + index
                                        );

                                        if (!eventsIterator.hasNext()) {
                                            return Collections.emptyIterator();
                                        }

                                        // get single ES documents
                                        List<SingleEventBaseDocument> eventList = getSingleEventBaseDocuments(eventsIterator);

                                        // build request wrappers
                                        List<InsertRequestWrapper> requestWrapperList = getRequestsToInsert(eventList, offsetRanges[index]);

                                        LOGGER.info(
                                                "@@ Processed " + offsetRanges[index].count() + " events" + " partition: " + index + " list size: " + eventList.size()
                                        );

                                        BulkResponse bulkItemResponses = elasticSearchRepository.addElasticSearchDocumentsSync(requestWrapperList);

                                        if (!bulkItemResponses.hasFailures()) {
                                            return Arrays.asList(offsetRanges).iterator();
                                        }

                                        elasticSearchRepository.close();
                                        return Collections.emptyIterator();
                                    },
                                    true
                            ).collect();

                    LOGGER.info(
                            "@@ [" + batchIdentifier + "] Collected all offsets in " + (Instant.now().toEpochMilli() - batchStart.toEpochMilli()) + "ms"
                    );

                    OffsetRange[] offsets = new OffsetRange[offsetsToCommit.size()];

                    for (int i = 0; i < offsets.length ; i++) {
                        offsets[i] = offsetsToCommit.get(i);
                    }

                    try {
                        offsetManagementMapper.commit(offsets);
                    } catch (Exception e) {
                        // ignore
                    }

                    LOGGER.info(
                            "@@ [" + batchIdentifier + "] Finished batch of " + offsetsToCommit.size() + " messages " +
                                    "in " + (Instant.now().toEpochMilli() - batchStart.toEpochMilli()) + "ms"
                    );
                    rdd.unpersist();
                });
kafkaStream.foreachRDD(//kafka topic
rdd->{//在驱动程序上运行
缓存();
字符串批处理标识符=
Long.toHexString(Double.Double-tolongbits(Math.random());
LOGGER.info(“@[”+batchIdentifier+“]开始批处理…”);
Instant batchStart=Instant.now();
列出offsetsToCommit=
rdd.mapPartitionsWithIndex(//kafka分区
(索引,eventsIterator)->{//在辅助服务器上运行
OffsetRange[]offsetRanges=((HasOffsetRanges)rdd.rdd()).offsetRanges();
LOGGER.info(
“@@consing”+offsetRanges[index]。count()+“events”+“partition:”+index
);
如果(!eventsIterator.hasNext()){
返回集合。emptyIterator();
}
//获取单个ES文档
List eventList=getSingleEventBaseDocuments(eventsIterator);
//构建请求包装器
List requestWrapperList=getRequestsToInsert(eventList,offsetRanges[index]);
LOGGER.info(
“@@Processed”+offsetRanges[index].count()+“events”+“partition:“+index+”列表大小:“+eventList.size()
);
BulkResponse bulkItemResponses=elasticSearchRepository.addElasticSearchDocumentsSync(requestWrapperList);
如果(!bulkItemResponses.hasFailures()){
返回Arrays.asList(offsetRanges.iterator();
}
elasticSearchRepository.close();
返回集合。emptyIterator();
},
真的
).收集();
LOGGER.info(
“@@[“+batchIdentifier+”]收集了“+(Instant.now().toEpochMilli()-batchStart.toEpochMilli())+”ms中的所有偏移量”
);
OffsetRange[]offsets=新的OffsetRange[offsetsToCommit.size()];
对于(int i=0;i
您可以将偏移逻辑移到rdd循环上方。。。我使用下面的模板来更好地处理偏移和性能

JavaInputDStream<ConsumerRecord<String, String>> kafkaStream = KafkaUtils.createDirectStream(jssc,
                LocationStrategies.PreferConsistent(),
                ConsumerStrategies.<String, String>Subscribe(topics, kafkaParams));



        kafkaStream.foreachRDD( kafkaStreamRDD -> {
            //fetch kafka offsets for manually commiting it later
            OffsetRange[] offsetRanges = ((HasOffsetRanges) kafkaStreamRDD.rdd()).offsetRanges();

            //filter unwanted data
            kafkaStreamRDD.filter(
                    new Function<ConsumerRecord<String, String>, Boolean>() {
                @Override
                public Boolean call(ConsumerRecord<String, String> kafkaRecord) throws Exception {
                    if(kafkaRecord!=null) {
                        if(!StringUtils.isAnyBlank(kafkaRecord.key() , kafkaRecord.value())) {
                            return Boolean.TRUE;
                        }
                    }
                    return Boolean.FALSE;
                }
            }).foreachPartition( kafkaRecords -> {

                // init connections here

                while(kafkaRecords.hasNext()) {
                    ConsumerRecord<String, String> kafkaConsumerRecord = kafkaRecords.next();
                    // work here
                }

            });
            //commit offsets
            ((CanCommitOffsets) kafkaStream.inputDStream()).commitAsync(offsetRanges);
        });
JavaInputDStream kafkaStream=KafkaUtils.createDirectStream(jssc,
LocationStrategies.PreferConsistent(),
订阅(主题,卡夫卡帕兰));
kafkaStream.foreachRDD(kafkaStreamRDD->{
//获取卡夫卡偏移量,以便稍后手动提交
OffsetRange[]offsetRanges=((HasOffsetRanges)kafkaStreamRDD.rdd()).offsetRanges();
//过滤不需要的数据
kafkaStreamRDD.filter(
新函数(){
@凌驾
公共布尔调用(ConsumerRecord kafkaRecord)引发异常{
if(kafkaRecord!=null){
如果(!StringUtils.isAnyBlank(kafkaRecord.key(),kafkaRecord.value())){
返回Boolean.TRUE;
}
}
返回Boolean.FALSE;
}
}).foreachPartition(卡夫卡雷德记录->{
//在这里初始化连接
while(kafkaRecords.hasNext()