Config with only subscribers
nico3dfx opened this issue ยท 11 comments
Hi,
I have a config file with about 3k queues, bindings and subscriptions.
Every time the process starts I have a warmup time of about 15 minutes. The greatest time is for checking the queues and the bindings.
A little time is spent to subscribe the consumer to the queue.
Is it possible to have a config for another process with queues and bindings and a config for a process with only subscriptions to speed up the time for the consumers to listen the queues?
Thanks,
Nico.
Hi Nico,
Having two configs doesn't make much sense to me, they would both run in parallel, so you would risk subscribing to a queue that didn't exist.
Alternatively if you are confident the queue exists and are configured correctly, you can disable checking the queues / exchanges.
Another thing that might help is if there was an async option. Rascal this serially because it makes it far easier to work out where problem occurs, but I have no problem performing the checks asynchronously or even in batches.
If you're happy to have a go, I think it should be a case of changing this line to use async.eachLimit.
The default limit should be 1
for backwards compatibility. I'm not sure how I would specify a different value through config though, as the "queues" config object contains a set of queues, with each key being the queue name. It might have to go at the top level instead, so a little more thought required there.
Rinse and repeat for https://github.com/guidesmiths/rascal/blob/master/lib/amqp/tasks/assertExchanges.js#L6 and https://github.com/guidesmiths/rascal/blob/master/lib/amqp/tasks/applyBindings.js#L12
Hi Cressie,
if can help you, with debug active I notice that several minutes are "lost" when Rascal apply bindings to exchange
2022-09-28T10:37:26.201Z rascal:tasks:applyBindings Binding queue: QUEUE_NAME to exchange: EXCHANGE_NAME with binding key: FIRST.SECOND.other1
2022-09-28T10:37:26.241Z rascal:tasks:applyBindings Binding queue: QUEUE_NAME to exchange: EXCHANGE_NAME with binding key: FIRST.SECOND.other2
2022-09-28T10:37:26.283Z rascal:tasks:applyBindings Binding queue: QUEUE_NAME to exchange: EXCHANGE_NAME with binding key: FIRST.SECOND.other3
2022-09-28T10:37:26.324Z rascal:tasks:applyBindings Binding queue: QUEUE_NAME to exchange: EXCHANGE_NAME with binding key: FIRST.SECOND.other4
(and so on)
I have 6k log rows of "rascal:tasks:applyBindings" with a test configuration file of 450 queues!
Time:
- start: 2022-09-28T10:33:50.768Z
- end: 2022-09-28T10:38:00.839Z
About 4+ minutes to have consumers in every queue.
Unfortunately making the calls asynchronous doesn't help. The reason is that behind the scenes amqplib is waiting for a response before sending the next call.
With a creating 1,000 exchanges with a concurrency of 10 resulted in the following debug (I added a post success message locally)
rascal:tasks:assertExchanges Asserting exchange: a0490c6c-3814-453d-b0bf-253cb28bf693:e1 +0ms
rascal:tasks:assertExchanges Asserting exchange: a0490c6c-3814-453d-b0bf-253cb28bf693:e2 +0ms
rascal:tasks:assertExchanges Asserting exchange: a0490c6c-3814-453d-b0bf-253cb28bf693:e3 +1ms
rascal:tasks:assertExchanges Asserting exchange: a0490c6c-3814-453d-b0bf-253cb28bf693:e4 +0ms
rascal:tasks:assertExchanges Asserting exchange: a0490c6c-3814-453d-b0bf-253cb28bf693:e5 +0ms
rascal:tasks:assertExchanges Asserting exchange: a0490c6c-3814-453d-b0bf-253cb28bf693:e6 +0ms
rascal:tasks:assertExchanges Asserting exchange: a0490c6c-3814-453d-b0bf-253cb28bf693:e7 +0ms
rascal:tasks:assertExchanges Asserting exchange: a0490c6c-3814-453d-b0bf-253cb28bf693:e8 +0ms
rascal:tasks:assertExchanges Asserting exchange: a0490c6c-3814-453d-b0bf-253cb28bf693:e9 +0ms
rascal:tasks:assertExchanges Asserting exchange: a0490c6c-3814-453d-b0bf-253cb28bf693:e10 +0ms
rascal:tasks:assertExchanges Successfully asserted exchange: a0490c6c-3814-453d-b0bf-253cb28bf693:e1 +3ms
rascal:tasks:assertExchanges Asserting exchange: a0490c6c-3814-453d-b0bf-253cb28bf693:e11 +0ms
rascal:tasks:assertExchanges Successfully asserted exchange: a0490c6c-3814-453d-b0bf-253cb28bf693:e2 +3ms
However using wireshark the Exchange.Declare and Exchange.Declare-Ok messages still come in sequence
No. Time Source Destination Protocol Length Info
41 0.298930 ::1 ::1 AMQP 141 Exchange.Declare x=a0490c6c-3814-453d-b0bf-253cb28bf693:e1
43 0.301350 ::1 ::1 AMQP 88 Exchange.Declare-Ok
45 0.302188 ::1 ::1 AMQP 141 Exchange.Declare x=a0490c6c-3814-453d-b0bf-253cb28bf693:e2
47 0.304333 ::1 ::1 AMQP 88 Exchange.Declare-Ok
49 0.305039 ::1 ::1 AMQP 141 Exchange.Declare x=a0490c6c-3814-453d-b0bf-253cb28bf693:e3
51 0.306679 ::1 ::1 AMQP 88 Exchange.Declare-Ok
53 0.307083 ::1 ::1 AMQP 141 Exchange.Declare x=a0490c6c-3814-453d-b0bf-253cb28bf693:e4
55 0.308682 ::1 ::1 AMQP 88 Exchange.Declare-Ok
57 0.309298 ::1 ::1 AMQP 141 Exchange.Declare x=a0490c6c-3814-453d-b0bf-253cb28bf693:e5
59 0.311408 ::1 ::1 AMQP 88 Exchange.Declare-Ok
61 0.311851 ::1 ::1 AMQP 141 Exchange.Declare x=a0490c6c-3814-453d-b0bf-253cb28bf693:e6
63 0.314042 ::1 ::1 AMQP 88 Exchange.Declare-Ok
65 0.314599 ::1 ::1 AMQP 141 Exchange.Declare x=a0490c6c-3814-453d-b0bf-253cb28bf693:e7
67 0.332144 ::1 ::1 AMQP 88 Exchange.Declare-Ok
69 0.332802 ::1 ::1 AMQP 141 Exchange.Declare x=a0490c6c-3814-453d-b0bf-253cb28bf693:e8
71 0.339870 ::1 ::1 AMQP 88 Exchange.Declare-Ok
73 0.340720 ::1 ::1 AMQP 141 Exchange.Declare x=a0490c6c-3814-453d-b0bf-253cb28bf693:e9
75 0.343136 ::1 ::1 AMQP 88 Exchange.Declare-Ok
77 0.343977 ::1 ::1 AMQP 142 Exchange.Declare x=a0490c6c-3814-453d-b0bf-253cb28bf693:e10
79 0.346291 ::1 ::1 AMQP 88 Exchange.Declare-Ok
Therefore the best option I can think of is to set the assert
attribute to false and remove the bindings. This will speed up your start-up significantly, but you will need another way of asserting new queues/exchanges and binding them.
The other option is to change amqplib to support the nowait option, but the change looks complicated, and as one of the maintainers, I don't think anyone will get to it quickly. Especially as it's a mostly useless feature - if you are going to the trouble of creating a queue, it is hard to imagine a scenario where you wouldn't want to wait until it had been successfully created.
I've thought of another way that might help. If I use multiple channels, then amqplib will be able to create the queues and exchanges concurrently. I ran a quick test, and with 10 channels the time to create 1,000 exchanges dropped from 1,794ms to 465ms. I'll continue to experiment.
I've just published rascal@16.1.0. You can control the concurrency / number of channels used during initialisation by setting the concurrency
attribute of the vhost. e.g.
{
"vhosts": {
"/": {
"concurrency": 10
}
}
}
I suspect it will still take some time to create thousands of queues, but should make a significant improvement
Removed some debug from v16.1.1
Tested with the same config (6k log rows of "rascal:tasks:applyBindings" with a test configuration file of 450 queues)
Now the warm up time is about 30 seconds!
Before (About 4+ minutes):
- start: 2022-09-28T10:33:50.768Z
- end: 2022-09-28T10:38:00.839Z
After (About 30 seconds):
- start: 2022-09-29T07:08:56.234Z
- end: 2022-09-29T07:09:25.387Z
Inside the config I have 5 vhosts with param "concurrency": 10
About 11 seconds with concurrency = 30
- start: 2022-09-29T07:25:16.214Z
- end: 2022-09-29T07:25:27.162Z
Great! Thanks for updating. OK to close?
Yes to close.
Thank you!
Thank you too. I think this is a great improvement to Rascal, and wouldn't have crossed my mind if you hadn't taken the time to share it.