简体   繁体   中英

RabbitMQ in a WCF webservice, model usage and performance

I need to call a RabbitMQ RPC Service from within a C# WCF Web service hosted in IIS. We have this working OK, but being a good little soldier I was reading the RabbitMQ client documentation and it states the following "IModel should not be shared between threads" .

My understanding is that in RabbitMQ an IModel is actually a socket connection. this would mean that for every call the WCF service makes it's needs to create an IModel and dispose of it once completed.

This would seem to me to be somewhat excessive on performance and socket usage and I am wondering if my understanding is actually correct, or if there are other options available like using a connection pool of IModels between threads.

Any suggestions would be gratefully received. Here's a sample of the code I'm using below, the rabbitMQ connection is actually initialized in the Global.asax, I just have it there to you can see the usage.

        var connectionFactory = new ConnectionFactory();
        connectionFactory.HostName = "SampleHostName";
        connectionFactory.UserName = "SampleUserName";
        connectionFactory.Password = "SamplePassword";
        IConnection connection = connectionFactory.CreateConnection();
        // Code below is what we actually have in the service method.
        var model = connection.CreateModel();
        using (model)
        {
            model.ExchangeDeclare("SampleExchangeName", ExchangeType.Direct, false);
            model.QueueDeclare("SampleQueueName", false, false, false, null);
            model.QueueBind("SampleQueueName", "SampleExchangeName", "routingKey" , null);
            // Do stuff, like post messages to queues
        }

IModel is actually a socket connection

This is incorrect. IConnection represents a connection :) Model was introduced in order to allow several clients to use the same tcp connection. So Model is a "logical" connection over a "physical" one.

One of tasks Model does is splitting and re-assembling large messages. If message exceeds certain size, it is split into frames, frames are labeled and are assembled back by receiver. Now, imagine that 2 threads send large messages... Frame numbers will be messed up, and you will end up with Frankenstein message which consists of random parts of 2 messages.

You are right assuming that Model creation have some cost. Client sends a request to server to create a model, server creates a structure in memory for this model, and sends model Id back to the client. It is done over tcp connection which is already open, so no overhead due to establishing connection. But there is still some overhead because of network round trip.

I'm not sure about WCF binding, but base rabbit's .net library does not provide any pooling for models. If it is a problem in your case, you'll have to come up with something on your own.

You need a single IModel object for each session. This is pretty normal for network-based API's. For example the Azure Table Storage client is exactly the same. Why, well you can't have a single Channel with multiple concurrent communication streams running over them.

I would expect that a certain level of caching to occur (eg DNS) which would reduce the overhead of creating subsequent IModel instances.

Performance is alright when doing the same thing with Azure Tables so it should be perfectly fine with IModel. Only attempt to optimise this when you can prove you have a real need.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM