TrafficBackgroundService.cs 6.34 KB
using HHECS.BllModel;
using HHECS.DAQShared.Models;

namespace HHECS.DAQServer.Services
{
    public class TrafficBackgroundService : BackgroundService
    {
        private readonly DataCacheService _dataCacheService;
        private readonly IFreeSql _freeSql;
        private readonly ILogger<TrafficBackgroundService> _logger;

        public TrafficBackgroundService(DataCacheService dataCacheService, IFreeSql freeSql, ILogger<TrafficBackgroundService> logger)
        {
            _dataCacheService = dataCacheService;
            _freeSql = freeSql;
            _logger = logger;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            DeleteRecord();
            var records = new List<TrafficRecord>();
            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                    //5秒更新一次
                    await Task.Delay(5000, stoppingToken);
                    //这里超过设定值,说明上一次处理失败了
                    if (records.Count >= 1000)
                    {
                        var result1 = AddRecord(records);
                        if (!result1.Success)
                        {
                            continue;
                        }
                        //保存成功,则清空
                        records.Clear();
                    }

                    while (!_dataCacheService.TrafficRecords.IsEmpty)
                    {
                        _dataCacheService.TrafficRecords.TryDequeue(out var temp);
                        if (temp == null)
                        {
                            continue;
                        }
                        records.Add(temp);
                    }

                    if (records.Count == 0)
                    {
                        continue;
                    }

                    var result = AddRecord(records);
                    if (!result.Success)
                    {
                        continue;
                    }
                    //保存成功,则清空
                    records.Clear();
                }
                catch (Exception ex)
                {
                    _logger.LogError($"[{nameof(TrafficBackgroundService)}]线程异常:{ex.Message}");
                }
            }
        }

        /// <summary>
        /// 记录到数据库
        /// </summary>
        /// <param name="records"></param>
        /// <returns></returns>
        private BllResult AddRecord(IEnumerable<TrafficRecord> records)
        {
            try
            {
                var recordGroup = records.GroupBy(x => new
                {
                    x.ClientId,
                    x.Origin,
                    x.RequestPath,
                    x.Method,
                    x.UserAgent,
                    x.RemoteIpAddress,
                });

                using var trafficRecordRepository = _freeSql.GetRepository<TrafficRecord>();
                foreach (var item in recordGroup)
                {
                    //按时间分组,30分钟一组
                    var datetimeGroup = item.GroupBy(x =>
                    {
                        var time = x.Created.Value;
                        return new DateTime(time.Year, time.Month, time.Day, time.Hour, time.Minute / 30 * 30, 0);
                    });

                    foreach (var item2 in datetimeGroup)
                    {
                        var startTime = item2.Key;
                        var endTime = startTime.AddMinutes(30);
                        var lastRecord = trafficRecordRepository.Where(x => x.ClientId == item.Key.ClientId
                        && x.Origin == item.Key.Origin
                        && x.RequestPath == item.Key.RequestPath
                        && x.Method == item.Key.Method
                        && x.UserAgent == item.Key.UserAgent
                        && x.RemoteIpAddress == item.Key.RemoteIpAddress
                        && x.Created >= startTime && x.Updated < endTime).First();

                        //不存在,则新增
                        if (lastRecord == null)
                        {
                            lastRecord = new TrafficRecord
                            {
                                ClientId = item.Key.ClientId,
                                Origin = item.Key.Origin,
                                RequestPath = item.Key.RequestPath,
                                Method = item.Key.Method,
                                UserAgent = item.Key.UserAgent,
                                RemoteIpAddress = item.Key.RemoteIpAddress,
                                RequestSize = item2.Sum(x => x.RequestSize),
                                ResponseSize = item2.Sum(x => x.ResponseSize),
                                Created = item2.Min(x => x.Created),
                                Updated = item2.Max(x => x.Created),
                            };
                            trafficRecordRepository.Insert(lastRecord);
                            continue;
                        }

                        //存在,则更新
                        trafficRecordRepository.Attach(lastRecord);
                        lastRecord.RequestSize += item2.Sum(x => x.RequestSize);
                        lastRecord.ResponseSize += item2.Sum(x => x.ResponseSize);
                        lastRecord.Updated = item2.Max(x => x.Created);
                        trafficRecordRepository.Update(lastRecord);
                    }
                }

                return BllResultFactory.Success();
            }
            catch (Exception ex)
            {
                _logger.LogError($"[{nameof(TrafficBackgroundService)}]保存记录失败:{ex.Message}");
                return BllResultFactory.Error(ex.Message);
            }
        }

        private BllResult DeleteRecord()
        {
            try
            {
                _freeSql.Delete<TrafficRecord>().Where(x => x.Created < DateTime.Today.AddMonths(-3)).ExecuteAffrows();
                return BllResultFactory.Success();
            }
            catch (Exception ex)
            {
                _logger.LogError($"[{nameof(TrafficBackgroundService)}]删除记录失败:{ex.Message}");
                return BllResultFactory.Error(ex.Message);
            }
        }
    }
}