-
Notifications
You must be signed in to change notification settings - Fork 15.4k
KAFKA-9231: Streams Threads may die from recoverable errors with EOS enabled #7748
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
bd0bc94
19f22a9
f6ac2c6
7a7d1e9
33c36a1
02fdedd
db878d7
e6f7cab
a264c8e
96a2d96
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,11 +18,13 @@ | |
|
|
||
| import org.apache.kafka.clients.consumer.Consumer; | ||
| import org.apache.kafka.common.TopicPartition; | ||
| import org.apache.kafka.common.errors.RetriableException; | ||
| import org.apache.kafka.common.utils.LogContext; | ||
| import org.apache.kafka.streams.StreamsConfig; | ||
| import org.apache.kafka.streams.errors.LockException; | ||
| import org.apache.kafka.streams.errors.ProcessorStateException; | ||
| import org.apache.kafka.streams.errors.StreamsException; | ||
| import org.apache.kafka.streams.errors.TaskMigratedException; | ||
| import org.apache.kafka.streams.processor.ProcessorContext; | ||
| import org.apache.kafka.streams.processor.StateStore; | ||
| import org.apache.kafka.streams.processor.TaskId; | ||
|
|
@@ -172,7 +174,14 @@ public String toString(final String indent) { | |
| * Flush all state stores owned by this task | ||
| */ | ||
| void flushState() { | ||
| stateMgr.flush(); | ||
| try { | ||
| stateMgr.flush(); | ||
| } catch (final ProcessorStateException e) { | ||
| if (e.getCause() instanceof RetriableException) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this intentional?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, boy. You're right... Really off my game today. |
||
| log.warn("Caught a retriable Kafka exception while flushing state. Initiating a rebalance to attempt recovery.", e); | ||
| throw new TaskMigratedException(this, e); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /** | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we catch it at this level? Seems we should move it into
ProcessorStateManger#flush()?Also note, that
ProcessorStateManger#flush()only throws the first exception what might not be what we want to detect this case correctly.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I wasn't sure... This way is a bit roundabout. On the other hand, right now,
TaskMigratedExceptionis only thrown by the tasks themselves or the threads that run them. It didn't seem within the responsibility of theProcessorStateManagerto reason about what specific exceptions imply about the state of the task.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough. It's not ideal that we get a
ProcessorStateExceptionand have to callgetCause(), but well, it is what it is.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reading the code here: we throw
TaskMigratedExceptionin bothStreamTaskas well asStreamThread. For the first case, the exception is thrown all the way to the caller ofTaskManagerand rethrown (hence in the level ofStreamThread); the latter case is only a few exceptional situations where the tasks are closed due to underlying exceptions.I feel throwing the exception in the level of
StreamTaskis fine, but we did too many capture / rethrow in different layers on top of it, which could be cleaned up in a separate tech-debt PR.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I very much agree. It's quite difficult to trace which exceptions would exist in different parts of the stack, and it would be nice to clean it up in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vvcephei while working on the cleanup PR I realized that when we call
store.flushinternally we should not blindly wrap all thrown exceptions from stores, but only those notStreamsException-- i.e. if the error is not from the store itself (like an IOException) but from the streams library, then just throw it out directly.Will do this small refactoring in my PR.