Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 通过定时后台任务在dotnet core中设置Rabbitmq使用者_C#_Asp.net Core_.net Core_Rabbitmq - Fatal编程技术网

C# 通过定时后台任务在dotnet core中设置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

我尝试通过定时后台任务设置rabbitmq使用者,但是,它并不总是正确地使用消息它似乎从队列中获取消息,但没有正确记录收到的消息。这似乎很奇怪。我想这可能与接收消息的事件处理程序没有正确执行有关,但我不知道为什么

我执行中讨论的定时后台任务,因为我希望避免建立长期连接。我觉得在需要时创建新的队列连接更安全

然而,当使用具有长期连接的后台服务时,到目前为止,一切都正常工作

有人能告诉我下面的代码有什么问题吗

// 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());