在ASP.NET中长期运行RabbitMQ连接

时间:2018-07-31 14:21:11

标签: c# asp.net iis rabbitmq

我知道建立RabbitMQ连接非常昂贵,因此不建议在我想将消息放入队列时{连接/发布/断开连接}。但是,我找不到在许多请求之间建立长期运行的RabbitMQ连接的方法。

我要实现的是在运行于IIS的ASP.NET应用程序中仅具有一个(或数量有限的)RabbitMQ连接,并将其用于不同的请求,而不是为每个请求创建不同的连接

以下是我到目前为止的代码。我需要以某种方式删除这些using语句并使我的连接保持打开状态。

非常感谢

public ReturnCode AtomicPublish(string userName, string password, string virtualHost, string hostName, string exchangeName, string queueName, string message)
{
    using (IConnection conn = new ConnectionFactory()
    {
        UserName = userName,
        Password = password,
        VirtualHost = virtualHost,
        HostName = hostName
    }.CreateConnection())
    {
        using (IModel model = conn.CreateModel())
        {
            model.ExchangeDeclare(exchangeName, ExchangeType.Fanout, true);
            model.QueueDeclare(queueName, true, false, false, null);
            model.QueueBind(queueName, exchangeName, "", null);
            byte[] messageBodyBytes = System.Text.Encoding.UTF8.GetBytes(message);
            model.BasicPublish(exchangeName, string.Empty, null, messageBodyBytes);
        }
    }
    return ReturnCode.OK;
}

3 个答案:

答案 0 :(得分:1)

离开我的头顶。

private static IConnection _connection {get;set;}
private static object LockObject = new object();
private static IConnection GetConnection (string username, string password, string virtualHost, string hostName)
    get{
        // do work here in case the connection is closed as well.
        if (_connection == null){
            lock(LockObject){
                if (_connection == null){
                    _connection = new ConnectionFactory
                       {
                           UserName = userName,
                           Password = password,
                           VirtualHost = virtualHost,
                           HostName = hostName

                       }.CreateConnection();
                }
            }

        }
        return _connection;
    }
}

public ReturnCode AtomicPublish(string userName, string password, string virtualHost, string hostName, string exchangeName, string queueName, string message)
{

        using (IModel model = GetConnection(userName, password, virtualHost, hostName).CreateModel()) //lazy loads the get connection
        {
            model.ExchangeDeclare(exchangeName, ExchangeType.Fanout, true);
            model.QueueDeclare(queueName, true, false, false, null);
            model.QueueBind(queueName, exchangeName, "", null);

            byte[] messageBodyBytes = System.Text.Encoding.UTF8.GetBytes(message);
            model.BasicPublish(exchangeName, string.Empty, null, messageBodyBytes);
        }

    return ReturnCode.OK;
}

答案 1 :(得分:1)

您应该将服务器端存储用于变量连接,

如果同一用户的所有请求的连接都相同,则将其保存在ASP.NET的会话对象中,

如果所有用户都相同,则将其保存在Cache应用程序对象中。

然后,当您需要再次加载并重新使用它时,将其从Session或Cache中取回,请参见此处的示例:Application vs Session vs Cache

答案 2 :(得分:-1)

就像您说的那样,建立RabbitMQ连接非常昂贵,因此当您打开连接时,您不应发送消息并断开连接。 实际上,RabbitMQ基于AMQP协议,它可以向许多不同主题的接收者发送消息(而不是使用队列),这意味着每个接收者都在监听一个不同的主题,例如:

using System;
using System.Linq;
using RabbitMQ.Client;
using System.Text;
class EmitLogTopic
{
public static void Main(string[] args)
{
    var factory = new ConnectionFactory() { HostName = "localhost" };
    using(var connection = factory.CreateConnection())
    using(var channel = connection.CreateModel())
    {
        channel.ExchangeDeclare(exchange: "topic_logs",
                                type: "topic");

        var routingKey = (args.Length > 0) ? args[0] : "anonymous.info";
        var message = (args.Length > 1)
                      ? string.Join(" ", args.Skip( 1 ).ToArray())
                      : "Hello World!";
        var body = Encoding.UTF8.GetBytes(message);
        channel.BasicPublish(exchange: "topic_logs",
                             routingKey: routingKey,
                             basicProperties: null,
                             body: body);
        Console.WriteLine(" [x] Sent '{0}':'{1}'", routingKey, message);
    }
}
}

link提供了更多信息的教程。