簡體   English   中英

Kafka KStreams - 處理超時

[英]Kafka KStreams - processing timeouts

我試圖使用帶有TimeWindows.of("name", 30000) <KStream>.process() TimeWindows.of("name", 30000)來批量處理一些KTable值並發送它們。 似乎30秒超過了消費者超時間隔,之后Kafka認為該消費者已經解散並釋放分區。

我已經嘗試提高輪詢頻率和提交間隔以避免這種情況:

config.put(StreamsConfig.COMMIT_INTERVAL_MS_CONFIG, "5000");
config.put(StreamsConfig.POLL_MS_CONFIG, "5000");

不幸的是,這些錯誤仍在發生:

(很多這些)

ERROR  o.a.k.s.p.internals.RecordCollector - Error sending record to topic kafka_test1-write_aggregate2-changelog 
org.apache.kafka.common.errors.TimeoutException: Batch containing 1 record(s) expired due to timeout while requesting metadata from brokers for kafka_test1-write_aggregate2-changelog-0

其次是:

INFO   o.a.k.c.c.i.AbstractCoordinator - Marking the coordinator 12.34.56.7:9092 (id: 2147483547 rack: null) dead for group kafka_test1
WARN   o.a.k.s.p.internals.StreamThread - Failed to commit StreamTask #0_0 in thread [StreamThread-1]: 
  org.apache.kafka.clients.consumer.CommitFailedException: Commit cannot be completed since the group has already rebalanced and assigned the partitions to another member. This means that the time between subsequent calls to poll() was longer than the configured session.timeout.ms, which typically implies that the poll loop is spending too much time message processing. You can address this either by increasing the session timeout or by reducing the maximum size of batches returned in poll() with max.poll.records.
at org.apache.kafka.clients.consumer.internals.ConsumerCoordinator$OffsetCommitResponseHandler.handle(ConsumerCoordinator.java:578)

顯然,我需要更頻繁地將心跳發送回服務器。 怎么樣?

我的拓撲結構是:

KStreamBuilder kStreamBuilder = new KStreamBuilder();
KStream<String, String> lines = kStreamBuilder.stream(TOPIC);
KTable<Windowed<String>, String>  kt = lines.aggregateByKey(
            new DBAggregateInit(),
            new DBAggregate(),
            TimeWindows.of("write_aggregate2", 30000));

DBProcessorSupplier dbProcessorSupplier = new DBProcessorSupplier();

kt.toStream().process(dbProcessorSupplier);
KafkaStreams kafkaStreams = new KafkaStreams(kStreamBuilder, streamsConfig);

kafkaStreams.start();

KTable每隔30秒按鍵對值進行分組。 Processor.init()中,我調用context.schedule(30000)

DBProcessorSupplier提供DBProcessor的一個實例。 這是AbstractProcessor的一個實現,其中提供了所有覆蓋。 他們只做LOG,所以我知道每個人都被擊中。

這是一個非常簡單的拓撲結構,但很明顯我在某個地方錯過了一個步驟。


編輯:

我知道我可以在服務器端進行調整,但我希望有一個客戶端解決方案。 我喜歡在客戶端退出/死亡時很快就可以使用分區的概念。


編輯:

為了簡化問題,我從圖中刪除了聚合步驟。 它現在只是消費者 - >處理器()。 (如果我將消費者直接發送到.print()它會很快工作,所以我知道沒關系)。 (類似地,如果我通過.print()輸出聚合(KTable),它似乎也可以。

我發現.punctuate() .process() - 應該每隔30秒調用.punctuate()實際上阻​​塞了可變長度的時間並且隨機輸出(如果有的話)。

進一步:

我將調試級別設置為'debug'並重新啟動。 我看到很多消息:

DEBUG  o.a.k.s.p.internals.StreamTask - Start processing one record [ConsumerRecord <info>

但是.punctuate()函數中的斷點沒有被擊中。 所以它做了很多工作,但沒有讓我有機會使用它。

一些澄清:

  • StreamsConfig.COMMIT_INTERVAL_MS_CONFIG是提交間隔的下限,即在提交之后,下一次提交不會在此時間之前發生。 基本上,Kafka Stream試圖在這段時間過后盡快提交,但無法保證下次提交實際需要多長時間。
  • StreamsConfig.POLL_MS_CONFIG用於內部KafkaConsumer#poll()調用,以指定的最大阻塞時間poll()調用。

因此,這兩個值對心跳更有幫助。

Kafka Streams在處理記錄時遵循“深度優先”策略。 這意味着,在每個記錄的poll()之后,將執行拓撲的所有運算符。 假設你有三個連續的地圖,那么在下一個/第二個記錄被處理之前,將為第一個記錄調用所有三個地圖。

因此,下一個poll()調用會進行,第一所有記錄后poll()得到全部處理。 如果你想更頻繁地心跳,你需要確保一個poll()調用獲取更少的記錄,這樣處理所有記錄所需的時間更少,下一個poll()將更早被觸發。

您可以使用配置參數KafkaConsumer ,你可以通過指定StreamsConfig得到這個工作(見https://kafka.apache.org/documentation.html#consumerconfigs ):

streamConfig.put(ConsumerConfig.XXX,VALUE);

  • max.poll.records :如果減小此值,將輪詢較少的記錄
  • session.timeout.ms :如果你增加這個值,那么有更多的時間來處理數據(為了完整性而添加它,因為它實際上是一個客戶端設置而不是服務器/代理端配置 - 即使你知道這個解決方案和不喜歡 :))

編輯

從Kafka 0.10.1 ,可以(並推薦)在流配置中為消費者和procuder配置添加前綴。 這避免了參數沖突,因為一些參數名稱用於消費者和生產者,否則無法區分(並且將同時應用於消費者生產者)。 要為參數添加前綴,可以分​​別使用StreamsConfig#consumerPrefix()StreamsConfig#producerPrefix() 例如: streamsConfig.put(StreamsConfig.consumerPrefix(ConsumerConfig.PARAMETER), VALUE);

還有一件事要提到:這個問題中描述的場景是一個已知問題,已經有KIP-62KafkaConsumer引入了一個發送心跳的后台線程,從而將heartbeats與poll()調用解耦。 Kafka Streams將在即將發布的版本中利用這一新功能。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM