1

I have couple of ASP.Net application servers and I'd like to use rabbitMQ (or similar queuing tools like redis pub/sub) for invalidating Memory cache on all the servers.

the scenario is simple when an application server clears it's own cache sends a message to message queue (declared by rabbitMQ) and all the other servers are listening to the that queue (in this case Cache queue) and when they receive the message (via Consumer.Received even handler) they invalidate their own memory cache as well.

for doing so I have to put my listener inside my web application (can't put in a console app or a windows service) because each ASP.net web app has it's own memory cache which is only accessible from inside of web application itself (not outside).

I've written a listen method in a static class here is my Listen method codes

   public static void Listen()
    {
        var factory = new ConnectionFactory() { HostName = "localhost" };
        using (var connection = factory.CreateConnection())
        using (var channel = connection.CreateModel())
        {
            channel.QueueDeclare(queue: "hello",
                                 durable: false,
                                 exclusive: false,
                                 autoDelete: false,
                                 arguments: null);

            var consumer = new EventingBasicConsumer(channel);
            consumer.Received += (model, ea) =>
            {
                var body = ea.Body;
                var message = Encoding.UTF8.GetString(body);
               // cache invalidation goes here
            };
            channel.BasicConsume(queue: "hello",
                                 autoAck: true,
                                 consumer: consumer);
        }
    }

and I call the Listen method in Application_Start method in global.asax like so

   protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
        CacheNotifier.Listen();
    }

But when I send a message to queue from an other server the Consumer.Received is not fired to receive the sent message.

Whereas when I put the exact same Listen method inside a console application and call it (listen method) from Main method static void Main(string[] args) the event is fired correctly when a message arrives but as I said I can't put my listener in a separate console app or windows service, it has to be inside my web application itself

First, I'd like to know the reason why my listener doesn't work in a ASP.net web app but works in a console app, the official documentation of RabbitMQ also uses only console app

And second, I need a solution for it, consider that my listener has to be inside my asp.net web app

any help would be appreciated

Code_Worm
  • 4,069
  • 2
  • 30
  • 35

4 Answers4

2

I had the exact same experience: everything was working fine during integration testing, but when referencing my library code (that was making use of RabbitMQ client) from another project the message was consumed from the queue just fine (I was watching the graphs in the rabbitmq admin) but the OnReceived callback was never raised.

What happened was that inside the callback I was using an assembly type that the runtime was unable to locate, and it would throw an exception that the RabbitMQ client is catching https://github.com/rabbitmq/rabbitmq-dotnet-client/blob/master/projects/client/RabbitMQ.Client/src/client/impl/ConcurrentConsumerDispatcher.cs#L89.

So if anyone else happens upon this, just make sure you've attached a callback to your channel like this to find out what's going on

channel.CallbackException += (chann, args) =>
{
   //check args.Exception for details
   ///...
};
bottlenecked
  • 2,079
  • 2
  • 21
  • 32
2

the problem is you enclose your code with using block as that statement is disposing (closing) of channel and connection which of course will cancel your subscription.

Patrick Guimalan
  • 990
  • 9
  • 11
1

I did tried your route with lot of problems, basically there is no listener that stay because of the asp.net lifecycle request work.

I finally put the receiver portion of my code in a Windows Service. When you received the message you can call another web service or just write your data in your DB...

My Windows Service has now more then 10 instances running all the same code and I can replicate my message to all my sites.

0

First, I'd like to know the reason why my listener doesn't work in a ASP.net web app but works in a console app, the official documentation of RabbitMQ also uses only console app

This is a .NET and ASP.NET programming question that is not related to the RabbitMQ .NET client in particular. I suggest reading this StackOverflow thread and this thread.

Those threads also discuss solutions to your problem.

Luke Bakken
  • 8,993
  • 2
  • 20
  • 33