-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Implement a higher-level consumer group #1099
Conversation
I thought it might make some sense to outline the requirements for this. Key Objectives
|
@eapache sorry to 'rush', but it would be good to get some feedback on this. I have created a tiny wrapper for this in https://github.com/bsm/sarama-cluster/tree/feature/v3-alt to be able to test various aspects but I am not sure I can find a better API that is able to fulfull all the objectives above. |
Sorry, I've been really busy recently with other things (Sarama is no longer related to my day-to-day at Shopify so it's been a bit of a trick to squeeze in time for it). I'll try and get to it soon, but even if it takes me another week or so, I haven't forgotten about it. |
is it moving forward? |
@eapache sorry to be a pain, just reminding |
Hmm, it is a complicated problem. I do like the general shape. Some thoughts:
Generally, I do think is a pretty good approach. Given the complexity of the problem I don't think I could do any better at least. |
The handling of groups, sessions, and claims does feel more natural in this approach than in #1083 though. |
@eapache thanks, I will try to address your feedback towards the end of next week. We have also found a little bug/oddity when members are dropped server-side which needs some additional error handling code. Finally, I am not 100% sure how to test all this (properly). The current vagrant approach is not sufficient for functional testing cluster functionality. In my latest sarama-cluster branch (which is based on this PR), I have created a docker-compose cluster with 3 brokers and 3 ZKs to make it work. Any thoughts? |
In what way is the vagrant setup not sufficient? It spins up five brokers with five zookeepers, all connected via toxiproxy for faking network isolations. |
@eapache I have pushed better functional tests, here's a few comments on your feedback:
Yes, I agree, and I was very hesitant about this initially, but there is a substantial caveat. Once the first consume goroutine exists, it must cancel the session and wait for all other goroutines to exit too, otherwise the user is in danger of consuming messages twice or locking the session beyond the server timeout. I also couldn't find any use case where the usage pattern would differ from my implementation. To consume partitions, the user needs to spin up a goroutine for each and perform the exact same steps as I did in my code https://github.com/Shopify/sarama/pull/1099/files#diff-9076b00c0e67e4484d0c04fb247353c7R507.
I agree and I didn't have it exported on the original draft. Instead of listening for
I agree, but again, I couldn't think of anything better. I used |
Makes sense. In that case I'm tempted to remove the
I'm wondering if we even need Minor additional nit, I'm not a big fan of having both |
We definitely need it to support objective #7. When the session is cancelled (either by the user or by a server rebalance) the individual
Not sure how to explain it better in the documentation. Happy to rename the
I am happy to remove that interface and simply accept a |
Ah, right. Following the same logic around |
And something else this made me think of; if we include a |
@eapache how about ^^? It is certainly safer to use but I am still not sure it's intuitive enough. What do you think? |
I like it. My only question is how the outer loop would work now? Does |
Or maybe instead of taking a edit: Or even just loop automatically on the same handler object. That would be convenient I think? |
Hmm, not sure about the loop, the goal was to allow users to change their subscriptions and I don't think that a handler factory is particularly intuitive. Currently, After some more fuzzy testing, we found one more issue, related to the offset manager. Currently, a partition offset manager will remain in a dirty state until it has successfully committed the stashed offsets. Unfortunately, any offset commit attempts after a rebalance are rejected by Kafka with a |
Oh, that also works for me. Re. the offset management issue, the issue is that if the POM doesn't manage to flush before the rebalance completes on the broker then it gets stuck? One mitigation (not a full solution) would be to add a little code to But fundamentally I don't think we can make any guarantees here. If some other client kicks off the rebalance and/or the broker rejects our offset storage request for some reason, it's always fundamentally possible for the rebalance to "leave us behind" like this. I think the best we can do is discard the stashed offsets entirely; the worst that happens is that the same offset gets consumed twice which is already part of the standard Kafka behaviour (excepting the new transactional stuff which I don't fully understand yet). |
While Kafka's 'at least once' is more hypothetical, discarding all stashed
offsets is likely to result in a substantial number of duplicates.
How would you feel about the consumer group doing its own offset commit
requests, bypassing the offset manager altogether? There may be some code
duplication but - from what I can see - making the member/generation cycles
work as part of the existing OffsetManager may prove an impossible effort.
…On Fri, 29 Jun 2018, 17:22 Evan Huus, ***@***.***> wrote:
Currently, Consume just blocks until the next rebalance (or until Close is
called).
Oh, that also works for me.
Re. the offset management issue, the issue is that if the POM doesn't
manage to flush before the rebalance completes on the broker then it gets
stuck? One mitigation (not a full solution) would be to add a little code
to PartitionOffsetManager.AsyncClose() to force an immediate flush,
rather than the current default which just waits for the next timer tick.
But fundamentally I don't think we can make any guarantees here. If some
other client kicks off the rebalance and/or the broker rejects our offset
storage request for some reason, it's always fundamentally possible for the
rebalance to "leave us behind" like this. I think the best we can do is
discard the stashed offsets entirely; the worst that happens is that the
same offset gets consumed twice which is already part of the standard Kafka
behaviour (excepting the new transactional stuff which I don't fully
understand yet).
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#1099 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AABA5pcmiH1OD0u0WqQl9RV3zevxc94Mks5uBlQogaJpZM4Ty5MB>
.
|
I'm just not sure how that would solve the problem? If Kafka is going to reject the requests, there's nothing the client can do whether the request is made from the offset manager or the consumer group? |
Re-balances do happen regularly and most of the time members inherit the same claims they just had in the previous session. In this case a member could just resume from its stashed offsets and commit at the next possible opportunity. Currently, we are creating a new offset manager with each session, effectively wiping all previous state. Ideally, the offset management should happen at the |
The fact that you had to add
Why can't we re-use the same offset manager and just update the member / generation IDs when we get the new session? You'll have to add a state to the POM I think, so it can get "paused" while a rebalance is in progress, but I think that fits pretty nicely in the existing design; have the broker abandon it as if the Coordinator changed, but then just hold off on selecting the new broker until we get a kick from the consumer? |
@eapache hmm, I can give it a go, but I remember running into a dead end the last time I tried. One thing I would like to clarify beforehand is: why does the OffsetManager need multiple BOMs? A consumer group can only have one active coordinator, so why not remove the |
I could provide a separate PR for the changes ^^ BTW |
Honestly, I just copied the broker/partition rebalance pattern from the consumer code without thinking about it too hard. I wanted to support offset tracking for multiple topic/partitions that didn't necessarily belong to the same consumer group, but even then the cluster only ever has one coordinator right? If there's no functional reason to support multiple BOMs then I'm happy to get rid of it. |
👍 I'll submit a PR for this |
The motivation is to listen to a list of topics, and dynamically to listen for more. I.E, collecting information from every topic with a specific pattern ( |
Yeah, that make sense, I haven't seen a mechanism to add topics at run time, but I could be wrong |
@varun06 @AlmogBaku no there isn't but it is a quite specific requirement and you can periodically check for new topics in the background yourself. If something's found, you could simply exit the current session and call |
Thanks @dim. While we are at it, a quick question, is there a stat to track how long it takes a consumeClaim function to execute? |
@varun06 this very much depends on how quickly other group consumers in the cluster are able to stop their sessions in order to rebalance. There are also various other timeout settings that Kafka uses as part of its (far from trivial) rebalance algorithm. I've mostly used Kafka's own documentation and added additional notes: |
@dim the reason I asked is, IIRC, because sarama-cluster used to support this feature... what was the motivation then? |
@dim is there an easy way to get claim batch size(len(claim.Messages()) and time taken to process one claim. I am not able to understand from the code around claim. Thanks in advance. I tried to do that in consumeClaim(), but that consume loop is long lived and I don't get anything until rebalance happens or I exit. |
@varun06 I don't quite understand your question. A claim is long lived and will only exit when (one of) the handler(s) exits or when the server signals a rebalance. I have tried to explain it all here: https://godoc.org/github.com/Shopify/sarama#ConsumerGroup. You can also see an example below. |
Thanks @dim and sorry for poor wording. I understand the long lived part of it and my batch question was stupid. So time to process a claim is also dictated by rebalance or exit, right? |
Once you have a claim, it will live until the next rebalance. The rebalance can be server-side (e.g. when another consumer decides to enter or exit the consumer group) it it can be client-side (i.e. when you call |
@vfiset there is an example in godoc -> https://godoc.org/github.com/Shopify/sarama#ConsumerGroup |
Thanks, totally missed it. Not as cool as the examples for the producer on github for a novice like me but good enough 👍 |
@varun06 is it maybe an idea to expand the examples to give new developers interested in Sarama a quick glance on how it works? It could also be used as a small "cheat sheet". I could create a PR to expand the examples. |
That would be great @jeroenrinzema |
I am trying to investigate a case where partitions are added to a Kafka topic during run time. Are the newly created partitions automatically added to the consumer group after creation? I have been trying to look through the code but did not find hints to it. |
@jeroenrinzema topics can be added/removed with every new loop iteration of |
@dim How can we recreate sarama-cluster's Whitelist feature using the new sarama.ConsumerGroup (which is automatically subscribing to any new topics that fulfill a regexp match) ? |
@Ocaenyth Why? I don't want to overcomplicate the library. You can implement whitelist subscriptions yourself: before starting a session, just get a list of known topics from the client and select the ones that match your regexp before calling |
I figured since you had implemented it in sarama-cluster to "do everything on its own" you might have implemented it in this PR as well, so I thought I was missing something. (And I thought that's what you were mentioning in this issue) But thanks for the quick response though, now I know I'll have to take a deeper look on how this works ! |
@dim
I saw this link but the readme file wasn't working and it is a bit hard to test. I wonder if adding such option is possible to "skip" unmarked offset until fresh point (after consumer is up) |
@levh there is no such option, but you could - between step 2 and 3 - simply delete the consumer group offset information and resume from OffsetLatest. |
@dim
I have an implementation suggestion for supporting that. can you please consider merging it? |
@dim if i'm looking at "ConsumeClaim" function |
Related to my other PR #1083, this is another attempt, this time with a higher-level consumer API. I have been going back and forth on this one, I can't find a better way to make it flexible enough to support all the use cases and comprehensible at the same time. I would really appreciate some feedback.