Skip to content
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

KAFKA-3933: close deepIterator during log recovery #1614

Closed
wants to merge 1 commit into from

Conversation

tcrayford
Copy link
Contributor

Avoids leaking native memory and hence crashing brokers on bootup due to
running out of memory.

Introduces kafka.common.ClosableIterator, which is an iterator that
can be closed, and changes the signature of
ByteBufferMessageSet.deepIterator to return it, then changes the
callers to always close the iterator.

This is a followup from #1598 with more native memory leaks in the broker code found and fixed.

Avoids leaking native memory and hence crashing brokers on bootup due to
running out of memory.

Introduces `kafka.common.ClosableIterator`, which is an iterator that
can be closed, and changes the signature of
`ByteBufferMessageSet.deepIterator` to return it, then changes the
callers to always close the iterator.
@tcrayford
Copy link
Contributor Author

@ijuma want to take a look now? I found there's a leak where we uncompress messages during handling of ProduceRequest (that we were hitting in production).

@tcrayford
Copy link
Contributor Author

@junrao mind reviewing this? Thanks a lot!

@ijuma
Copy link
Contributor

ijuma commented Jul 14, 2016

Thanks @tcrayford. I will take a deeper look tomorrow if Jun doesn't beat me to it. One question: have you given some thought on how we could test these changes?

@tcrayford
Copy link
Contributor Author

@ijuma yeah, we have a system that aggrevates these memory leaks when pointed at a Kafka cluster. I can release the new code to it and then watch for leaks like I did previously.

@tcrayford
Copy link
Contributor Author

@ijuma or were you talking about adding tests inside the project itself? Unfortunately it seems impossible to tell if a GZIPInputStream is closed.

@ijuma
Copy link
Contributor

ijuma commented Jul 20, 2016

Yes, I meant within the project itself. One way to check if GZipInputStream is closed is to call read which throws an IOException if the stream is closed.

@tcrayford
Copy link
Contributor Author

@ijuma the compressor isn't exposed by the iterator. I can expose that, but it feels like the classic "should we/shouldn't we" thing about private members. Seeing as I'm new to the codebase, I'd love your take on that.

@ijuma
Copy link
Contributor

ijuma commented Jul 25, 2016

I spent some time looking at this in more detail and after changing a number of additional places to use CloseableIterator, it occurred to me that there may be a much simpler solution. We currently have the following code in ByteBufferMessageSet.deepIterator that is executed during the constructor of the iterator:

        val messageAndOffsets = if (wrapperMessageAndOffset.message.magic > MagicValue_V0) {
         val innerMessageAndOffsets = new ArrayDeque[MessageAndOffset]()
         try {
           while (true)
             innerMessageAndOffsets.add(readMessageFromStream())
         } catch {
           case eofe: EOFException =>
             compressed.close()
           case ioe: IOException =>
             throw new InvalidMessageException(s"Error while reading message from stream compressed with ${wrapperMessage.compressionCodec}", ioe)
         }
         Some(innerMessageAndOffsets)
       } else None

So, we are reading the whole compressed message set during construction if message format > 0. I suggest we do the same for message format = 0, and then we don't need to change any other code. Thoughts @tcrayford?

@tcrayford
Copy link
Contributor Author

Nice spot! I was originally concerned about the resource utilization of something like this, but it seems much better than this PR in that no future logic needs to worry about it. Furthermore, seeing as most messages will be format > 0 in the future we don't save much anyway.

I can put another PR in for this today.

@ijuma
Copy link
Contributor

ijuma commented Jul 25, 2016

Yes, indeed. If we weren't doing it for message format > 0 (which will be the common case going forward, as you said), then it would make sense to try and avoid it.

@tcrayford tcrayford closed this Jul 25, 2016
@tcrayford
Copy link
Contributor Author

@ijuma #1660

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants