We have an application that consists of two parts: a cloud backend API and an on-premises service that the client installs. The communication between the service and the client is done via a RMQ server, to which the backend connects via AMQP and the client - via MQTT.
The typical usage goes like this:
Everything happens in the context of a single long-running HTTP request.
The problem is that this approach does not scale well. When doing a load test with a couple hundred users sending requests simultaneously the RMQ server at some point stops creating new channels, either by timeout:
System.TimeoutException: The operation has timed out.
at RabbitMQ.Client.Impl.ModelBase.ModelRpc(MethodBase method, ContentHeaderBase header, Byte[] body)
at RabbitMQ.Client.Framing.Impl.AutorecoveringConnection.CreateModel()
Or an outright failure:
RabbitMQ.Client.Exceptions.ChannelAllocationException: The connection cannot support any more channels. Consider creating a new connection
at RabbitMQ.Client.Impl.SessionManager.Create()
at RabbitMQ.Client.Framing.Impl.AutorecoveringConnection.CreateModel()
The channel limit exception can (theoretically) be overcome by having multiple connections, but it will not help with the timeouts. Neither of the resources available on my PC (CPU time, memory) are being exhausted.
I also considered having one upstream queue for all responses from a single client, but it's not clear how the API will be able to separate results for each request.
Is there a better approach?
We found 2 approaches and experimented with them:
Key points are:
Key points:
In the end we decided on using the second approach, because being able to communicate via a MQTT connection is a dealbreaker for the project.