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-4429; records-lag should be zero if FetchResponse is empty #2155

Closed
wants to merge 6 commits into from

Conversation

lindong28
Copy link
Member

No description provided.

@@ -689,6 +689,9 @@ private void handleListOffsetResponse(Map<TopicPartition, Long> timestampsToSear
parsedRecords = new PartitionRecords<>(fetchOffset, tp, parsed);
ConsumerRecord<K, V> record = parsed.get(parsed.size() - 1);
this.sensors.recordsFetchLag.record(partition.highWatermark - record.offset());
} else if (partition.records.iterator().hasNext()) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem right. At a minimum, we're missing the '!' to invert the check. Additionally, iteration through a record set is not cheap (it may involve decompression), so we should try to use the work we've already done. In fact, maybe we could remove the check and compute the lag based on the high watermark and the current position of the consumer instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hachikuji Yes, good point. I think we can compute lag as partition.highWatermark - position if parsed result is empty. But I am not sure if we should use this as lag if parsed result is not empty. It may be a good solution. But doing so changes the semantic of the fetch lag metric since the metric would only be updated when position is updated in the next poll() call.

Copy link

@hachikuji hachikuji Nov 30, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. This is a little subtle, but it doesn't seem incorrect. Since we know that the fetched offset matches our current position, the fetch lag should be in sync with the position. In fact, it may be more intuitive if we use fetchOffset instead of position.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hachikuji Sorry for late reply. Sure, I will replace position with fetchOffset in the patch. I still keep the existing measurement of fetchLag in the case where the response is not empty because I don't want to cause any unexpected problem by making this subtle but backward incompatible change. On the other hand I don't mind if you or someone else want to change it.

@ewencp
Copy link
Contributor

ewencp commented Jan 2, 2017

@lindong28 FetcherTest has a test or two that do validation of metrics, might be worth adding a few assertions to validate this change (and maybe a test if both lag and non-lag conditions aren't available in existing tests).

@asfbot
Copy link

asfbot commented Jan 2, 2017

Refer to this link for build results (access rights to CI server needed):
https://builds.apache.org/job/kafka-pr-jdk7-scala2.10/421/
Test PASSed (JDK 7 and Scala 2.10).

@asfbot
Copy link

asfbot commented Jan 2, 2017

Refer to this link for build results (access rights to CI server needed):
https://builds.apache.org/job/kafka-pr-jdk8-scala2.11/423/
Test FAILed (JDK 8 and Scala 2.11).

@asfbot
Copy link

asfbot commented Jan 2, 2017

Refer to this link for build results (access rights to CI server needed):
https://builds.apache.org/job/kafka-pr-jdk8-scala2.12/422/
Test FAILed (JDK 8 and Scala 2.12).

@lindong28
Copy link
Member Author

@ewencp Sure, I just added a unit test for this patch. Can you take another look? Thank you.

@asfbot
Copy link

asfbot commented Jan 3, 2017

Refer to this link for build results (access rights to CI server needed):
https://builds.apache.org/job/kafka-pr-jdk7-scala2.10/428/
Test PASSed (JDK 7 and Scala 2.10).

@asfbot
Copy link

asfbot commented Jan 3, 2017

Refer to this link for build results (access rights to CI server needed):
https://builds.apache.org/job/kafka-pr-jdk8-scala2.12/429/
Test FAILed (JDK 8 and Scala 2.12).

@asfbot
Copy link

asfbot commented Jan 3, 2017

Refer to this link for build results (access rights to CI server needed):
https://builds.apache.org/job/kafka-pr-jdk8-scala2.11/430/
Test FAILed (JDK 8 and Scala 2.11).

}

private Map<TopicPartition, List<ConsumerRecord<byte[], byte[]>>> fetchRecords(MemoryRecords records, short error, long hw, int throttleTime) {
this.records = records;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I copied & pasted this logic without checking if it is needed. Fixed now.

MemoryRecordsBuilder builder = MemoryRecords.builder(ByteBuffer.allocate(1024), CompressionType.NONE, TimestampType.CREATE_TIME);
for (int v = 0; v < 3; v++)
builder.appendWithOffset((long) i * 3 + v, Record.NO_TIMESTAMP, "key".getBytes(), String.format("value-%d", v).getBytes());
records = fetchRecords(builder.build(), Errors.NONE.code(), 100L, 100 * i).get(tp);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: could we use a local variable instead of overriding the field?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, records is already a variable, but it seems we could move its initialization to here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes we can. Personally I think the logic is clearer by passing it as parameter of fetchRecords() instead of via the class variable. Do you think the updated patch looks better?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To clarify, what I meant is just to move the initialization of the records variable from above to here (since we don't actually need it outside of the loop):

List<ConsumerRecord<byte[], byte[]>> records = fetchRecords(builder.build(), Errors.NONE.code(), 100L, 100 * i).get(tp);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see. Sure, it is fixed now.


// recordsFetchLagMax should be hw - fetchOffset after receiving an empty FetchResponse
MemoryRecordsBuilder builder = MemoryRecords.builder(ByteBuffer.allocate(1024), CompressionType.NONE, TimestampType.CREATE_TIME);
fetchRecords(builder.build(), Errors.NONE.code(), 100L, 0);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could also use MemoryRecords.EMPTY here (I think).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice point. It works:)

@asfbot
Copy link

asfbot commented Jan 3, 2017

Refer to this link for build results (access rights to CI server needed):
https://builds.apache.org/job/kafka-pr-jdk8-scala2.12/443/
Test PASSed (JDK 8 and Scala 2.12).

@asfbot
Copy link

asfbot commented Jan 3, 2017

Refer to this link for build results (access rights to CI server needed):
https://builds.apache.org/job/kafka-pr-jdk8-scala2.11/444/
Test PASSed (JDK 8 and Scala 2.11).

@asfbot
Copy link

asfbot commented Jan 3, 2017

Refer to this link for build results (access rights to CI server needed):
https://builds.apache.org/job/kafka-pr-jdk7-scala2.10/442/
Test FAILed (JDK 7 and Scala 2.10).

@hachikuji
Copy link

LGTM. Thanks for the patch!

@asfbot
Copy link

asfbot commented Jan 3, 2017

Refer to this link for build results (access rights to CI server needed):
https://builds.apache.org/job/kafka-pr-jdk7-scala2.10/448/
Test PASSed (JDK 7 and Scala 2.10).

@asfgit asfgit closed this in b565dd7 Jan 3, 2017
@asfbot
Copy link

asfbot commented Jan 3, 2017

Refer to this link for build results (access rights to CI server needed):
https://builds.apache.org/job/kafka-pr-jdk8-scala2.11/450/
Test PASSed (JDK 8 and Scala 2.11).

@asfbot
Copy link

asfbot commented Jan 3, 2017

Refer to this link for build results (access rights to CI server needed):
https://builds.apache.org/job/kafka-pr-jdk8-scala2.12/449/
Test FAILed (JDK 8 and Scala 2.12).

@lindong28 lindong28 deleted the KAFKA-4429 branch January 5, 2017 21:41
soenkeliebau pushed a commit to soenkeliebau/kafka that referenced this pull request Feb 7, 2017
Author: Dong Lin <lindong28@gmail.com>

Reviewers: Ewen Cheslack-Postava <me@ewencp.org>, Jason Gustafson <jason@confluent.io>

Closes apache#2155 from lindong28/KAFKA-4429
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants