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.Redis / Hangfire.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));