C# 通过定时后台任务在dotnet core中设置Rabbitmq使用者
我尝试通过定时后台任务设置rabbitmq使用者,但是,它并不总是正确地使用消息它似乎从队列中获取消息,但没有正确记录收到的消息。这似乎很奇怪。我想这可能与接收消息的事件处理程序没有正确执行有关,但我不知道为什么 我执行中讨论的定时后台任务,因为我希望避免建立长期连接。我觉得在需要时创建新的队列连接更安全 然而,当使用具有长期连接的后台服务时,到目前为止,一切都正常工作 有人能告诉我下面的代码有什么问题吗C# 通过定时后台任务在dotnet core中设置Rabbitmq使用者,c#,asp.net-core,.net-core,rabbitmq,C#,Asp.net Core,.net Core,Rabbitmq,我尝试通过定时后台任务设置rabbitmq使用者,但是,它并不总是正确地使用消息它似乎从队列中获取消息,但没有正确记录收到的消息。这似乎很奇怪。我想这可能与接收消息的事件处理程序没有正确执行有关,但我不知道为什么 我执行中讨论的定时后台任务,因为我希望避免建立长期连接。我觉得在需要时创建新的队列连接更安全 然而,当使用具有长期连接的后台服务时,到目前为止,一切都正常工作 有人能告诉我下面的代码有什么问题吗 // consumer part using System; using System.C
// consumer part
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
namespace play_mq
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.AddConsole();
})
.ConfigureServices(services =>
{
services.AddHostedService<MessageListener>();
});
}
public class MessageListener : IHostedService, IDisposable
{
private readonly IOptions<RabbitOptions> _rabbitOptions;
private readonly ILogger<MessageListener> _logger;
private Timer _timer;
private int executionCount = 0;
public MessageListener(ILogger<MessageListener> logger, IOptions<RabbitOptions> rabbitOptions)
{
_logger = logger;
_rabbitOptions = rabbitOptions;
}
public Task StartAsync(CancellationToken cancellationToken)
{
_timer = new Timer(DoWork, null, TimeSpan.Zero,
TimeSpan.FromSeconds(5));
return Task.CompletedTask;
}
private void DoWork(object state)
{
var count = Interlocked.Increment(ref executionCount);
_logger.LogInformation(
"MessageListener is working. Count: {Count}", count);
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.ToArray());
_logger.LogInformation($"consume {message}");
};
channel.BasicConsume(queue: "hello", autoAck: true, consumer: consumer);
}
}
public Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("MessageListener is stopping.");
_timer?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
public void Dispose()
{
_timer?.Dispose();
}
}
}
它似乎从队列中获取消息,但没有正确记录收到的消息。
原因:
channel.BasicConsume(queue: "hello", autoAck: true, consumer: consumer);
autoAck设置为true,则在接收消息之前向代理确认为正。一旦确认,代理将其从队列中删除+
解决方案:不要在那里设置ack(true)(设置auroAck=false),而是在收到消息时设置ack
consumer.Received += (model, ea) =>
{
channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false);
//Other method available for negative ack
};
我想避免长期的联系。我觉得在需要时创建新的队列连接更安全
为了更好地回答您的问题,您可以检查代码
和在发布时接收消息
public class MessageListener : IHostedService, IDisposable
{
private readonly IOptions<RMQConfig> _rabbitOptions;
private readonly ILogger<MessageListener> _logger;
private Timer _timer;
private int executionCount = 0;
private readonly IConnection _connection;
public MessageListener(ILogger<MessageListener> logger, IOptions<RMQConfig> rabbitOptions)
{
_logger = logger;
_rabbitOptions = rabbitOptions;
var factory = new ConnectionFactory()
{
HostName = "localhost"
};
_connection = factory.CreateConnection();
}
public Task StartAsync(CancellationToken cancellationToken)
{
_timer = new Timer(DoWork, null, TimeSpan.Zero,
TimeSpan.FromSeconds(5));
return Task.CompletedTask;
}
private void DoWork(object state)
{
var count = Interlocked.Increment(ref executionCount);
_logger.LogInformation(
"MessageListener is working. Count: {Count}", count);
// using (var connection = factory.CreateConnection())
// using (var channel = connection.CreateModel())
// {
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.ToArray());
_logger.LogInformation($"consume {message}");
};
channel.BasicConsume(queue: "hello", autoAck: false, consumer: consumer);
// }
}
public Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("MessageListener is stopping.");
_timer?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
public void Dispose()
{
//Close _connection
_timer?.Dispose();
}
}
公共类MessageListener:IHostedService,IDisposable
{
私有只读IOptions\u rabbitOptions;
专用只读ILogger\u记录器;
私人定时器;
private int executionCount=0;
专用只读IConnection\u连接;
public MessageListener(ILogger记录器、IOptions rabbitOptions)
{
_记录器=记录器;
_兔子选项=兔子选项;
var factory=新连接工厂()
{
HostName=“localhost”
};
_connection=factory.CreateConnection();
}
公共任务StartSync(CancellationToken CancellationToken)
{
_计时器=新计时器(DoWork、null、TimeSpan.Zero、,
时间跨度从秒(5)开始;
返回Task.CompletedTask;
}
私有无效工作(对象状态)
{
变量计数=联锁增量(参考执行计数);
_logger.login信息(
“MessageListener正在工作。计数:{Count}”,计数);
//使用(var connection=factory.CreateConnection())
//使用(var channel=connection.CreateModel())
// {
var channel=_connection.CreateModel();
QueueDeclare(队列:“hello”、持久:false、独占:false、自动删除:false、参数:null);
var消费者=新事件基本消费者(渠道);
消费者.已接收+=(型号,ea)=>
{
变量体=ea.body;
var message=Encoding.UTF8.GetString(body.ToArray());
_logger.LogInformation($“消费{message}”);
};
channel.BasicConsume(队列:“你好”,自动确认:假,消费者:消费者);
// }
}
公共任务StopAsync(CancellationToken CancellationToken)
{
_logger.LogInformation(“MessageListener正在停止”);
_计时器?更改(Timeout.Infinite,0);
返回Task.CompletedTask;
}
公共空间处置()
{
//关闭连接
_计时器?.Dispose();
}
}
几个月前我也遇到过同样的问题,希望它能帮助其他人
它似乎从队列中获取消息,但没有正确记录收到的消息。
原因:
channel.BasicConsume(queue: "hello", autoAck: true, consumer: consumer);
autoAck设置为true,则在接收消息之前向代理确认为正。一旦确认,代理将其从队列中删除+
解决方案:不要在那里设置ack(true)(设置auroAck=false),而是在收到消息时设置ack
consumer.Received += (model, ea) =>
{
channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false);
//Other method available for negative ack
};
我想避免长期的联系。我觉得在需要时创建新的队列连接更安全
为了更好地回答您的问题,您可以检查代码
和在发布时接收消息
public class MessageListener : IHostedService, IDisposable
{
private readonly IOptions<RMQConfig> _rabbitOptions;
private readonly ILogger<MessageListener> _logger;
private Timer _timer;
private int executionCount = 0;
private readonly IConnection _connection;
public MessageListener(ILogger<MessageListener> logger, IOptions<RMQConfig> rabbitOptions)
{
_logger = logger;
_rabbitOptions = rabbitOptions;
var factory = new ConnectionFactory()
{
HostName = "localhost"
};
_connection = factory.CreateConnection();
}
public Task StartAsync(CancellationToken cancellationToken)
{
_timer = new Timer(DoWork, null, TimeSpan.Zero,
TimeSpan.FromSeconds(5));
return Task.CompletedTask;
}
private void DoWork(object state)
{
var count = Interlocked.Increment(ref executionCount);
_logger.LogInformation(
"MessageListener is working. Count: {Count}", count);
// using (var connection = factory.CreateConnection())
// using (var channel = connection.CreateModel())
// {
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.ToArray());
_logger.LogInformation($"consume {message}");
};
channel.BasicConsume(queue: "hello", autoAck: false, consumer: consumer);
// }
}
public Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("MessageListener is stopping.");
_timer?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
public void Dispose()
{
//Close _connection
_timer?.Dispose();
}
}
公共类MessageListener:IHostedService,IDisposable
{
私有只读IOptions\u rabbitOptions;
专用只读ILogger\u记录器;
私人定时器;
private int executionCount=0;
专用只读IConnection\u连接;
public MessageListener(ILogger记录器、IOptions rabbitOptions)
{
_记录器=记录器;
_兔子选项=兔子选项;
var factory=新连接工厂()
{
HostName=“localhost”
};
_connection=factory.CreateConnection();
}
公共任务StartSync(CancellationToken CancellationToken)
{
_计时器=新计时器(DoWork、null、TimeSpan.Zero、,
时间跨度从秒(5)开始;
返回Task.CompletedTask;
}
私有无效工作(对象状态)
{
变量计数=联锁增量(参考执行计数);
_logger.login信息(
“MessageListener正在工作。计数:{Count}”,计数);
//使用(var connection=factory.CreateConnection())
//使用(var channel=connection.CreateModel())
// {
var channel=_connection.CreateModel();
QueueDeclare(队列:“hello”、持久:false、独占:false、自动删除:false、参数:null);
var消费者=新事件基本消费者(渠道);
消费者.已接收+=(型号,ea)=>
{
变量体=ea.body;
var message=Encoding.UTF8.GetString(body.ToArray());