在 dot net core 中初始化后台服务的正确方法

Ami*_*udi 5 c# rabbitmq asp.net-web-api asp.net-core

我有一项服务需要连接到 的另一项服务startup。另一项服务是Rabbitmq经纪人。

我正在监听一些事件,Rabbitmq因此我需要从应用程序启动时激活它。

我需要连接到两个不同的VHost,所以我需要创建两个连接。

问题是,当我启动应用程序时,它会不断创建连接,直到服务器崩溃!

在Rabbitmq管理中我可以看到很多Connection并且Channels被创建。

我不明白为什么会发生这种情况。

一般来说,我想知道在 dotnet core 中启动应用程序时连接到其他服务的正确方法是什么。

我正在使用此代码来执行此操作:

public void ConfigureServices(IServiceCollection services)
        {
            .....

            services.AddSingleton<RabbitConnectionService>();

            ...

            ActivatorUtilities.CreateInstance<RabbitConnectionService>(services.BuildServiceProvider());
        }
Run Code Online (Sandbox Code Playgroud)

RabbitConnectionService在我连接到的构造函数中Rabbitmq

public RabbitConnectionService(IConfiguration configuration)
        {   
            ServersMessageQueue = new MessageQueue(configuration.GetConnectionString("FirstVhost"), "First");
            ClientsMessageQueue = new MessageQueue(configuration.GetConnectionString("SecondVhost"), "Second");
        }
Run Code Online (Sandbox Code Playgroud)

消息队列类:

public class MessageQueue
    {

        private IConnection connection;

        private string RabbitURI;
        private string ConnectionName;

        static Logger _logger = LogManager.GetCurrentClassLogger();

        public MessageQueue(string connectionUri, string connectionName)
        {
            ConnectionName = connectionName;
            RabbitURI = connectionUri;
            connection = CreateConnection();
        }


        private IConnection CreateConnection()
        {
            ConnectionFactory factory = new ConnectionFactory();
            factory.Uri = new Uri(RabbitURI);
            factory.AutomaticRecoveryEnabled = true;
            factory.RequestedHeartbeat = 10;
            return factory.CreateConnection(ConnectionName);
        }

        public IModel CreateChannel()
        {
            return connection.CreateModel();
        }

        ...
    }
Run Code Online (Sandbox Code Playgroud)

Ami*_*udi 4

要启用后台处理,您需要创建一个实现IHostedService接口的类。

public interface IHostedService
{
    Task StartAsync(CancellationToken cancellationToken);
    Task StopAsync(CancellationToken cancellationToken);
}
Run Code Online (Sandbox Code Playgroud)

该接口有两个方法StartAsyncStopAsync。您需要使用依赖注入来注册服务,如下所示:

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddSingleton<IHostedService, DemoService>();
    ...
}
Run Code Online (Sandbox Code Playgroud)

IHostedService您可以从抽象类派生BackgroundService并实现抽象方法,而不是实现ExecuteAsync。下面是一个最小后台服务的示例,它监视 SQL Server 中的表并发送电子邮件:

public class DemoService : BackgroundService
{
    private readonly ILogger<DemoService> _demoservicelogger;
    private readonly DemoContext _demoContext;
    private readonly IEmailService _emailService;
    public DemoService(ILogger<DemoService> demoservicelogger, 
        DemoContext demoContext, IEmailService emailService)
    {
        _demoservicelogger = demoservicelogger;
        _demoContext = demoContext;
        _emailService = emailService;
    }
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _demoservicelogger.LogDebug("Demo Service is starting");
        stoppingToken.Register(() => _demoservicelogger.LogDebug("Demo Service is stopping."));
        while (!stoppingToken.IsCancellationRequested)
        {
            _demoservicelogger.LogDebug("Demo Service is running in background");
            var pendingEmailTasks = _demoContext.EmailTasks
                .Where(x => !x.IsEmailSent).AsEnumerable();
            await SendEmailsAsync(pendingEmailTasks);
            await Task.Delay(1000 * 60 * 5, stoppingToken);
        }
        _demoservicelogger.LogDebug("Demo service is stopping");
    }
}
Run Code Online (Sandbox Code Playgroud)

感谢伊恩·坎普。

参考资料