IE盒子

搜索
查看: 130|回复: 0

在.NET Core中使用Redis队列与Hangfire异步处理任务

[复制链接]

4

主题

7

帖子

15

积分

新手上路

Rank: 1

积分
15
发表于 2023-1-19 10:00:57 | 显示全部楼层 |阅读模式
最近在开发中遇到了并发过多导致服务器负载过高的问题,结合实际情况优化了一下,特此记录。以下内容已隐去业务细节。
业务逻辑

该问题涉及到的接口主要处理第三方发出的回调,主要是由回调数据给数据库中的数据条目打标签(可视为更新Stamp字段)。应用程序调用一次第三方接口后,至多会收到1000次回调,造成数据库压力过大。该任务对实时性要求不高,适合作为后台任务处理。使用Redis队列与Hangfire优化了数据库并发以改善性能。主要思路如下:
请求到达时,将打标签所用参数序列化后加入Redis队列,再由Hangfire定时任务每分钟处理队列中的任务。
简要实现

以下是代码只展示关键逻辑,其中使用了StackExchange.Redis。ConvertHelper.Serialize<T>(object item)及ConvertHelper.Deserialize<T>(byte[] objBytes)为通用的序列化方法,读者可实现为适当的序列化形式,如JSON,Protobuf等。IScoped接口是一个空接口,表示将该类加入依赖注入容器中。
StampQueueHelper.cs
public class StampQueueHelper : IScoped
{
    private readonly IDataBase _database;

    public StampQueueHelper(IDatabase database)
    {
        _database = database
    }

    private string QueueName = "StampQueue";

    public async Task Enqueue(StampModel model)
    {
        await _dataBase.ListRightPushAsync(QueueName, ConvertHelper.Serialize(model));
    }

    private async Task<StampModel> Dequeue()
    {
        return await _database.ListLeftPush(QueueName)
    }
}
StampHelper.cs
public class StampHelper : IScoped
{
    private readonly StampQueueHelper _stampQueueHelper;

    public StampHelper(StampQueueHelper stampQueueHelper)
    {
        _stampQueueHelper = stampQueueHelper;
    }
    public async Task ProcessStamp()
    {
        var random = new Random();
        while(true)
        {
            var model = await _stampQueueHelper.Dequeue();
            if (model == null)
                break;
            await AddStamp(model) // 执行业务的函数

            // 随机等待,进一步减小数据库压力
            await Task.Delay(random.next(100, 200));
        }
    }
}
HTTP接口
[HttpPost]
public async Task StampCallBack(StampModel model)
{
    await _stampQueueHelper.Enqueue(model);
}
Hangfire配置
RecurringJob.AddOrUpdate<StampHelper>(c => c.ProcessStamp(), Cron.Minutely, TimeZoneInfo.Local);
本文采用 CC BY-NC-ND 4.0 协议 ,转载请注明出处。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表