Abp Hangfire 占用 PostgreSql 连接数的另类解决方案

最近在使用 Hangfire 时遇到一个小问题,部署到生产环境后,不定时的会出现连接数占用超过 100,首先使用的方法就是将连接数提升到 10000。观察一段时间连接数后发现其实也不是很多,看起来连接数占满的情况倒是没有再出现。但是始终有种如鲠在喉的感觉,内心一直没有放下“解决”的念头。

 

经过一段时间断断续续的探索,最终尝试将数据库从 PostgreSql 改为 Redis。经过一番改造,现在也稳定运行了一段时间。彷佛一切都很顺利的样子。下面把修改的主要代码贴出来供参考。

 

最开始使用 PostgreSql 数据库时的配置:

services.AddHangfire(config =>
{
    config.UsePostgreSqlStorage(appConfiguration.GetConnectionString("Default"));
});

下面是改为 Redis 后的代码,考虑到项目可能运行在不同环境,而 Redis 不是必选配置,所以放了个开关,如果有 Redis 优先选择。没有也可以继续使用 PostgreSql 顺利的跑起来。

services.AddHangfire(config =>
{
    if (appConfiguration.GetIsEnabled("Abp:RedisCache:IsEnabled"))
    {
        //Use Redis to storage
        var options = new RedisStorageOptions()
        {
            Db = int.Parse(appConfiguration["Abp:RedisCache:DatabaseId"])
        };
        config.UseRedisStorage(appConfiguration["Abp:RedisCache:ConnectionString"], options);
    }
    else config.UsePostgreSqlStorage(appConfiguration.GetConnectionString("Default"));
});

在操作之前需要引入两个 NuGet 包:Hangfire.RedisHangfire.Redis.StackExchange.StrongName


至此数据库的配置就完成了。接下来再简单讲下 hangfire 的使用。下面的代码是演示通过 hangfire 发送短信验证码。首先创建 Job 执行类,在 Job 类中不需要做特别的事,只需要完成触发即可。

public class SendSmsJob : BackgroundJob<SendSmsJobInput>, ITransientDependency
{
    private readonly SmsManager _smsManager;

    public SendSmsJob(SmsManager smsManager)
    {
        _smsManager = smsManager;
    }

    public override void Execute(SendSmsJobInput args)
    {
        _smsManager.SendCaptcha(args.PhoneNumber, args.TemplateCode).GetAwaiter();
    }
}

调用的方式也很方便,除了参数赋值以外,一行代码搞定:

var entity = new SendSmsJobInput
{
    PhoneNumber = input.PhoneNumber,
    TemplateCode = templateCode
};
await _backgroundJobManager.EnqueueAsync<SendSmsJob, SendSmsJobInput>(entity);

还可以使用延时执行,比如在执行过程中存在事务的情况下,延时就起作用了。如果不使用延时执行就有很大的概率会获取到更新前的数据。所以延时执行就可以解决这个问题。

await _backgroundJobManager.EnqueueAsync<SendSmsJob, SendSmsJobInput>(entity, delay: TimeSpan.FromSeconds(3));

 

posted @ 2020-07-27 11:41  Jöhan  阅读(433)  评论(0编辑  收藏  举报