Azure / azure-service-bus-java

☁️ Java client library for Azure Service Bus
https://azure.microsoft.com/services/service-bus
MIT License
60 stars 59 forks source link

[Question] How to increase receiving throughput #324

Closed warrenzhu25 closed 5 years ago

warrenzhu25 commented 5 years ago

I found receiver side of queue cannot catch up with producer speed. I found there're some possible ways to improve this:

  1. Increase max concurrent calls in MessageHandlerOptions. Does it have some side effects?
  2. Pass a big thread pool when registering message handler. How should I decide the size of thread pool. Is this related with max concurrent calls?
  3. According to official doc, To increase the overall receive rate from the queue, use multiple message factories to create receivers. Does that mean I should create multiple queue client to receive?
  4. Increase prefetch count.

I would suggest to have a wiki page about how to increase receiver throughput.

yvgopal commented 5 years ago

If you are using PEEKLOCK mode, Receive is two operations (receive + complete) while send is only one operation. So Send throughput is generally higher than receive throughput. Answer to your questions..

  1. No side effects. That means more parallel threads receiving messages. It will help.
  2. Ideally threadpool size should be equal (or little more) to the maxconcurrent calls. Each onMessage call happens on a thread. If maxconcurrent calls is 10, then queueclient will try to use 10 threads at the same time. If threadpool doesn't have 10 threads, it becomes a bottleneck.
  3. Yes. 1 QueueClient = 1 Factory = 1 TCP connection
  4. This will help too. We will add a wiki page with best practices, across all our SDKs.
warrenzhu25 commented 5 years ago

Thanks for your reply. I try to understand the basic flow of receiving:

  1. Receiver will send a request to broker to receive the message. The number of messages returned is controlled by prefetch count.
  2. Then suppose prefetch count is 10. We have 10 message on the receiver side. So we can start 10 concurrent calls of OnMessage if maxConcurrentCall is greater than 10.
  3. These concurrent calls are scheduled on the thread pool provided. If message processing time is long, the extra concurrent calls will be blocked.

Is my understanding right?

yvgopal commented 5 years ago
  1. Not exactly. PrefetchCount says how many messages to receive as soon as a receiver is created, even before your application calls receive() method. That makes your receive faster as the message was already fetched from the broker, even before a receive is called.
  2. PrefetchCount is not related to concurrent calls. Even with 0 prefetch count, you can have 10 max concurrent calls. Prefetch count as its name says only pre-fetches messages.
  3. Right.
warrenzhu25 commented 5 years ago

Thanks for clarification. I got the point of prefetch count. But I'm still confusing about max concurrent calls.

  1. I thought max concurrent calls is specific for user-defined message handler and it should be limited by the number of messages receiver have got in the client buffer. But it seems not. It's more like the number of concurrent call to try to retrieve message from client buffer. So setting this too high will make many unnecessary check like busy loop. Do I make this right?
  2. I suppose you have a dedicated thread for fetching messages from broker, then put available message into client buffer. Will this fetching only happen on demand when client buffer is almost empty? How the number of messages to be fetched decided? or only one for each call?
  3. The prefetch count actually controls when to fetch messages. It's when buffer size is smaller than prefetch count.

Thanks a lot.