【问题标题】:Reactive program exiting early before sending all messages to Kafka反应程序在将所有消息发送到 Kafka 之前提前退出
【发布时间】:2021-05-08 19:10:07
【问题描述】:

这是对先前反应式 kafka 问题 (Issue while sending the Flux of data to the reactive kafka) 的后续问题。

我正在尝试使用响应式方法将一些日志记录发送到 kafka。这是使用响应式 kafka 发送消息的响应式代码。

public class LogProducer {

    private final KafkaSender<String, String> sender;

    public LogProducer(String bootstrapServers) {

        Map<String, Object> props = new HashMap<>();
        props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
        props.put(ProducerConfig.CLIENT_ID_CONFIG, "log-producer");
        props.put(ProducerConfig.ACKS_CONFIG, "all");
        props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
        props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
        SenderOptions<String, String> senderOptions = SenderOptions.create(props);

        sender = KafkaSender.create(senderOptions);
    }

    public void sendMessages(String topic, Flux<Logs.Data> records) throws InterruptedException {
    
        AtomicInteger sentCount = new AtomicInteger(0);
        sender.send(records
        .map(record -> {
            LogRecord lrec = record.getRecords().get(0);
            String id = lrec.getId();
            Thread.sleep(0, 5); // sleep for 5 ns
            return SenderRecord.create(new ProducerRecord<>(topic, id,
                    lrec.toString()), id);
        })).doOnNext(res -> sentCount.incrementAndGet()).then()
        .doOnError(e -> {
            log.error("[FAIL]: Send to the topic: '{}' failed. "
                    + e, topic);
        })
        .doOnSuccess(s -> {
            log.info("[SUCCESS]: {} records sent to the topic: '{}'", sentCount, topic);
        })
        .subscribe();
    }

}


public class ExecuteQuery implements Runnable {

    private LogProducer producer = new LogProducer("localhost:9092");

    @Override
    public void run() {
        Flux<Logs.Data> records = ...
        producer.sendMessages(kafkaTopic, records);
        .....
        .....
        // processing related to the messages sent
    }

}

所以即使Thread.sleep(0, 5); 存在,有时它也不会将所有消息发送到kafka,并且程序存在早期打印成功消息(log.info("[SUCCESS]: {} records sent to the topic: '{}'", sentCount, topic);)。有没有更具体的方法来解决这个问题。例如,使用某种回调,让线程等待所有消息发送成功。

我有一个 spring 控制台应用程序并通过调度程序以固定速率运行 ExecuteQuery,类似于这样

public class Main {

private ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
private ExecutorService executor = Executors.newFixedThreadPool(POOL_SIZE);

public static void main(String[] args) {
     QueryScheduler scheduledQuery = new QueryScheduler();
     scheduler.scheduleAtFixedRate(scheduledQuery, 0, 5, TimeUnit.MINUTES);
}

class QueryScheduler implements Runnable {

  @Override
  public void run() {
      // preprocessing related to time
      executor.execute(new ExecuteQuery());
      // postprocessing related to time
  }

}
}

【问题讨论】:

    标签: apache-kafka project-reactor flux reactor reactive-kafka


    【解决方案1】:

    您的Thread.sleep(0, 5); // sleep for 5 ns 没有任何值可以阻止主线程,因此它会在需要时退出,而您的ExecuteQuery 可能还没有完成它的工作。

    不清楚你是如何启动你的应用程序的,但我建议 Thread.sleep() 正好在一个主线程中阻塞。准确地说是public static void main(String[] args) { 方法实现。

    【讨论】:

    • 更新了如何调用它的问题。关于 Thread.sleep(0, 5) 放置,它在大多数情况下确实有效,但我已经看到它在其他一些机器上提前退出,所以它不是解决这个问题的可靠方法。
    • 对此有任何指示吗?你认为使用非反应式 kafka 方法可以解决这个问题吗?
    猜你喜欢
    • 2019-02-25
    • 1970-01-01
    • 2015-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多