houseofcat / turbocookedrabbit

A user friendly RabbitMQ library written in Golang.
MIT License
107 stars 20 forks source link

How do I dynamically expand ConnectionPools under load? #13

Closed aadog closed 3 years ago

aadog commented 3 years ago

How to dynamically add channels? 1000 channels are not allowed to be set up in advance, because most of the time, it is only a peak value. After the peak value, he will not need 1000 channels

houseofcat commented 3 years ago

That is an incorrect plan.*

If you need more than 1000, then you need more than 1000. I don't know what you are doing but I highly question you need more than 1000 channels simultaneously firing in parallel (i.e. time to rethink design).

For others, here is an example of how to change the ChannelCount via settings.

image

    "PoolConfig": {
        "URI": "amqp://guest:guest@localhost:5672/",
        "ConnectionName": "TurboCookedRabbit",
        "SleepOnErrorInterval": 100,
        "MaxCacheChannelCount": 1000,  <- Here
        "MaxConnectionCount": 10,
        "Heartbeat": 6,
        "ConnectionTimeout": 10,
        "TLSConfig": {
            "EnableTLS": false,
            "PEMCertLocation": "test/catest.pem",
            "LocalCertLocation": "client/cert.ca",
            "CertServerName": "hostname-in-cert"
        }
    },

Maintaining the count (1000 channels) just so they can be sitting idle in the pool while already using 1000 channels is pointless for a couple of reasons.

Reason 1, Channels die all the time. They are transient. They will all probably be dead before you even get to use them.

Reason 2, the complexity of maintaining the lifetime of a dynamic expanding ConnectionPool that can also shrink back will be slow and buggy with all the edge cases.

Reason 3, the load balancing over connections becomes impossible without a Factory paradigm overseeing the Channel creation process and historics.

Reason 4, I already had this in an older flavor in v1 and removed it for simplicity and it actually works better now than it did.

Having 2000 channels pre-built is the perhaps the least correct approach. I have no intention of adding the functionality (adding channels at runtime) in this library when the whole point is to avoid developers manually handling channels like you are attempting to do. In addition to that, I anticipate the ConnectionPool is most likely not your real bottleneck or problem, instead it is the implementation. If it's thousands of Consumers draining the pool, I already anticipated this - they are a special case - and wired up in the Config the ability use TransientChannels. I encourage this setting to be used when there are many Consumer situations as to not drain the pool permanently of Channels.

If you are starving another part of your application because the ConnectionPool is being hammered heavily by an operation/elsewhere, make a second ConnectionPool. You can have as many as you want. This maybe the alternative to large ConnectionPools. Having a couple of a smaller ConnectionPools in isolation with the same or slightly different settings.

Multiple-connection pools are used to multi-plex between different servers (thus connection strings).

If you still insist on doing something ill advised, you can hack the library by creating your own ChannelHost and "Return" it to the ChannelPool. I do not support this idea however.