-
Notifications
You must be signed in to change notification settings - Fork 3.7k
[enh] Broker - Shared subscription: run filters in a separate (per-subscription) thread (dispatcherDispatchMessagesInSubscriptionThread) #16603
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
Conversation
lhotari
left a comment
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.
LGTM
| dispatcherMaxReadBatchSize=100 | ||
|
|
||
| # Dispatch messages and execute broker side filters in a per-subscription thread | ||
| dispatcherDispatchMessagesInSubscriptionThread=true |
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.
Should we keep it false by default? Most of the users don't have broker-side filters. Enabled by default will introduce more thread switching.
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 am adding this flag only to rollback in case of problem with particular workloads.
We are doing performance testing, I believe that this new behaviour is generally better, not only for the case of server side filters, but especially in these cases:
- multiple subscriptions on the same topic
- concurrent produce and consume
| } | ||
|
|
||
| protected void sendMessagesToConsumers(ReadType readType, List<Entry> entries) { | ||
| protected synchronized void sendMessagesToConsumers(ReadType readType, List<Entry> entries) { |
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.
It's better to have a check and only apply the lock if dispatcherDispatchMessagesInSubscriptionThread is enabled.
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.
sendMessagesToConsumers is usually called by readEntriesComplete, that is already synchronized
Line 492 in 019493d
| public synchronized void readEntriesComplete(List<Entry> entries, Object ctx) { |
the JVM is smart enough to understand that there is no need for extra work for synchronized
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.
Alternatively, I think you could add a synchronized (this) block around the runnable's call to this method.
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.
there is no difference.
I think that this is not a problem.
@codelipenghui do you agree ?
| topic.getBrokerService().getTopicOrderedExecutor() | ||
| .executeOrdered(name, | ||
| safeRun(() -> sendMessagesToConsumers(readType, entries))); |
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.
We can have a pinned executor instead of selecting the executor for each operation.
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.
this is an interesting point.
Let me investigate.
I am not sure about the threadpool that we can use here as "pinned", I would like to pick a thread from "TopicOrderedExecutor"
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.
@codelipenghui I have pinned the Subscription to a thread.
I think that this is what you suggested
thanks
| // sendMessagesToConsumers is responsible for running broker-side filters | ||
| // that may be quite expensive | ||
| topic.getBrokerService().getTopicOrderedExecutor() | ||
| .executeOrdered(name, |
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.
- do we care about potential (unchecked) RejectedExecutionException here?
- we may need to prevent this code from submitting unlimited amount of runnables into that executor / handle long backlog.
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.
do we care about potential (unchecked) RejectedExecutionException here?
we usually don't deal with RejectedExecutionException in Dispatcher code.
in any case even if the execution is rejected the Dispatcher will read more entries for some other reasons
we may need to prevent this code from submitting unlimited amount of runnables into that executor / handle long backlog.
This shouldn't be a problem because there is a "natural" backpressure mechanism here, we trigger this code when new entries are read from storage (BK/Offloaders) but we request new reads from Storage after dispatching them to Consumers.
So usually there is only one of this tasks that is pending for the subscription.
|
@eolivelli Please provide a correct documentation label for your PR. |
019493d to
7d80f8b
Compare
…ead (dispatcherDispatchMessagesInSubscriptionThread) (cherry picked from commit 9d0ae97)
709c3ad to
5c1cf84
Compare
...che/pulsar/broker/service/persistent/PersistentStickyKeyDispatcherMultipleConsumersTest.java
Outdated
Show resolved
Hide resolved
…ersistent/PersistentStickyKeyDispatcherMultipleConsumersTest.java Co-authored-by: Lari Hotari <lhotari@users.noreply.github.com>
|
/pulsarbot rerun-failure-checks |
… (per-subscription) thread (dispatcherDispatchMessagesInSubscriptionThread) (apache#16603)" Fixes apache#16802 This reverts commit abe5d15.
### Motivation See apache#16802 and the discussion in apache#16803. Before reverting apache#16603, disabling the `dispatcherDispatchMessagesInSubscriptionThread` option first. ### Modifications Change the default value of `dispatcherDispatchMessagesInSubscriptionThread` to false.
|
This enhancement may fix the |
|
And this PR has bug, the fix PR at here: #16812 |
|
Hi, @gaoran10 |
|
@eolivelli Please provide a correct documentation label for your PR. |
|
@eolivelli just wanted to check in - any docs required to be updated for this improvement? |
Motivation
Server side filters may be very heavy weight, and currently they are running (very often) in the same thread that handles writes and also all the subscriptions.
We want to improve performances in presence of heavy server side filters:
Modifications
Add a new flag,
dispatcherDispatchMessagesInSubscriptionThread, enabled by default, to dispatch messages to consumers in a Shared subscription using a separate thread than the BK executor thread.With this patch we choose a thread depending on the topic + subscription name and we run the actual dispatching of messages (sendMessagesToConsumers) in such thread.
Verifying this change
I did some manual testing with a dummy filter that slows down (Thread.sleep(100)) consumption and even with a simply workload (50k msg/s) I have verified that: