我知道建立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;
}
答案 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提供了更多信息的教程。