1

我的理解是IModel创建实例相当便宜,这就是我开始的。我为每个使用它的类创建了一个单独IModel的类:每个 Application Service 类都有自己IModelController. 它工作正常,但打开 30 多个频道有点令人担忧。

我想过序列化对共享的访问IModel

lock(publisherLock)
    publisherModel.BasicPublish(...);

但现在有一个没有充分理由的争论点。

那么,将消息从 ASP.NET MVC 应用程序发布到 RabbitMQ 交换的正确方法是什么?

4

2 回答 2

3

您不能做的是允许一个通道被多个线程使用,因此在多个请求中保持通道打开是一个坏主意。

IModel 实例的创建成本很低,但不是免费的,因此您可以采取以下几种方法:

最安全的做法是在每次要发布时创建一个通道,然后立即再次关闭它。像这样的东西:

using(var model = connection.CreateModel())
{
    var properties = model.CreateBasicProperties();
    model.BasicPublish(exchange, routingKey, properties, msg);
}

您可以在应用程序的整个生命周期内保持连接打开,但请务必检测您是否断开连接并有代码重新连接。

这种方法的缺点是您需要为每次发布创建一个通道的开销。

另一种方法是在专用发布线程上保持通道打开,并使用 BlockingCollection 或类似方法将所有发布调用编组到该线程。这将更有效,但实施起来更复杂。

于 2013-07-23T10:54:14.430 回答
0

这是你可以使用的东西,

BrokerHelper.Publish("Aplan chaplam, chaliye aai mein :P");

以下是 BrokerHelper 类的定义。

public static class BrokerHelper
{
    public static string Username = "guest";
    public static string Password = "guest";
    public static string VirtualHost = "/";
    // "localhost" if rabbitMq is installed on the same server,
    // else enter the ip address of the server where it is installed.
    public static string HostName = "localhost";
    public static string ExchangeName = "test-exchange";
    public static string ExchangeTypeVal = ExchangeType.Direct;
    public static string QueueName = "SomeQueue";
    public static bool QueueExclusive = false;
    public static bool QueueDurable = false;
    public static bool QueueDelete = false;
    public static string RoutingKey = "yasser";

    public static IConnection Connection;
    public static IModel Channel;
    public static void Connect()
    {
        var factory = new ConnectionFactory();
        factory.UserName = Username;
        factory.Password = Password;
        factory.VirtualHost = VirtualHost;
        factory.Protocol = Protocols.FromEnvironment();
        factory.HostName = HostName;
        factory.Port = AmqpTcpEndpoint.UseDefaultPort;
        Connection = factory.CreateConnection();
        Channel = Connection.CreateModel();
    }

    public static void Disconnect()
    {
        Connection.Close(200, "Goodbye");
    }

    public static bool IsBrokerDisconnected()
    {
        if(Connection == null) return true;
        if(Connection.IsOpen) return false;
        return true;
    }

    public static void Publish(string message)
    {
        if (IsBrokerDisconnected()) Connect();

        Channel.ExchangeDeclare(ExchangeName, ExchangeTypeVal.ToString());
        Channel.QueueDeclare(QueueName, QueueDurable, QueueExclusive, QueueDelete, null);
        Channel.QueueBind(QueueName, ExchangeName, RoutingKey);
        var encodedMessage = Encoding.ASCII.GetBytes(message);
        Channel.BasicPublish(ExchangeName, RoutingKey, null, encodedMessage);
        Disconnect();
    }
}

进一步阅读:RabbitMQ 与 C# .NET、ASP.NET 和 ASP.NET MVC 的介绍以及示例

于 2013-08-13T07:03:04.660 回答