stevenjin 2024-10-11 14:50 采纳率: 98%
浏览 3
已结题

Hangfire定时任务执行误差太大

重复任务时,下一次没有精确触发(到秒)
1.已将Hangfire的SchedulePollingInterval 设为1,按分重复执行任务时仍不能精确到按秒执行(如12:30:00执行一次,下一次应该是12:31:00,实际可能快二十几秒,有时又慢几秒)
2.demo很简单的,没有做其他任务,应该不会误差达十几秒。不知哪里没有写对?


using Hangfire;
using Hangfire.MySql;

namespace HandleFireTest
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);
            
            // Add services to the container.
            builder.Services.AddControllersWithViews();
            builder.Services.AddHangfire(configuration => configuration
           .SetDataCompatibilityLevel(CompatibilityLevel.Version_170)//此方法 只初次创建数据库使用即可
           .UseSimpleAssemblyNameTypeSerializer()
           .UseRecommendedSerializerSettings()
           .UseStorage(new MySqlStorage("Server=127.0.0.1;uid=root;pwd=123;database=Jobs;AllowLoadLocalInfile=true;Allow User Variables=True", new MySqlStorageOptions
           {
               TransactionIsolationLevel = (System.Transactions.IsolationLevel?)System.Data.IsolationLevel.ReadCommitted, //事务隔离级别。默认是读取已提交
               QueuePollInterval = TimeSpan.FromSeconds(1), //- 作业队列轮询间隔。默认值为15秒。            
               JobExpirationCheckInterval = TimeSpan.FromMinutes(20),
               CountersAggregateInterval = TimeSpan.FromMinutes(5),
               PrepareSchemaIfNecessary = true, // 如果设置为true,则创建数据库表。默认是true
               DashboardJobListLimit = 50000,
               TransactionTimeout = TimeSpan.FromMinutes(1),
               TablesPrefix = "Hangfire",
           })));

            builder.Services.AddHangfireServer(options =>
            {
                options.ServerName = "task";
                options.SchedulePollingInterval = TimeSpan.FromMicroseconds(1000);
                options.HeartbeatInterval = TimeSpan.FromMicroseconds(1000);
                options.WorkerCount = Math.Max(Environment.ProcessorCount, 20);//并行数
            });
            //builder.Services.AddHangfireServer();

            var app = builder.Build();

            // Configure the HTTP request pipeline.
            if (!app.Environment.IsDevelopment())
            {
                app.UseExceptionHandler("/Home/Error");
            }
            app.UseStaticFiles();

            app.UseRouting();      


            app.UseHangfireDashboard();
          

            app.UseAuthorization();

            app.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");

            app.Run();
        }
    }
}

using HandleFireTest.Models;
using Hangfire;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;

namespace HandleFireTest.Controllers
{
    public class MyJob
    {
        public string MyMethod()
        {
            Console.WriteLine("execute method!"+DateTime.Now);
            // 后台任务逻辑
            return "Hello, World!";
        }
    }

    public class HomeController : Controller
    {
        private readonly ILogger<HomeController> _logger;

        public HomeController(ILogger<HomeController> logger)
        {
            _logger = logger;
           
        }

        public void WriteLog(string msg)
        {
            //Debug.WriteLine($"Hangfire于{DateTime.Now}执行了任务[{msg}]");
        }

        public IActionResult Index()
        {
            //Console.Write("队列任务1");
            //支持基于队列的任务处理:任务执行不是同步的,而是放到一个持久化队列中,以便马上把请求控制权返回给调用者。        
            //var jobId = BackgroundJob.Enqueue(() => WriteLog("队列任务"));
            return View();
        }

        private static object Deserialize(string result)
        {
            // 反序列化逻辑
            return result;
        }
        private string SendEmail(string email) { return "ol"; }
        public IActionResult Privacy()
        {
            // 使用 Hangfire 的实例化方法         
            //var jobId1 = BackgroundJob.Enqueue(() => Console.WriteLine("Fire-and-forget!"));
            //var jobId2 = BackgroundJob.Enqueue<MyJob>(x => x.MyMethod());
            //var jobId3 = BackgroundJob.Schedule<MyJob>(x => x.MyMethod(), TimeSpan.FromSeconds(8));
            //RecurringJob.AddOrUpdate<MyJob>(x => x.MyMethod(), Cron.MinuteInterval(1));
            RecurringJob.AddOrUpdate<MyJob>(x=>x.MyMethod(), "0 */1 * * * ?");//每1分一次

            //如果存在就删除周期任务
            //RecurringJob.RemoveIfExists("some-id");
            //触发周期任务
            //RecurringJob.Trigger("some-id");
            // 获取Hangfire连接对象
            //var connection = JobStorage.Current.GetConnection();

            // 获取后台任务的详细信息
            //var jobData = connection.GetJobData(jobId1);
            //RecurringJob.Trigger(jobId1);
            // 获取返回对象
            //var result = jobData.Result;

            //// 反序列化返回对象
            //var deserializedResult = Deserialize(result);

            //var server = new BackgroundJobServer();
            //// 做一些其它事情...
            //server.SendStop();

            return View();
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }
}

  • 写回答

1条回答 默认 最新

  • 香格里辣 2024-10-11 23:44
    关注

    以下回复参考:皆我百晓生券券喵儿等免费微信小程序作答:

    Hangfire 是一个用于处理后台任务的库,它在处理定时任务时通常是非常可靠的。然而,关于你提到的定时任务执行误差问题,这可能是由多种原因导致的。下面是一些建议和可能的解决方案:

    1. 数据库和Hangfire服务器的时钟同步:确保你的数据库服务器和Hangfire服务器运行在同一机器上或至少在时间上是同步的。时间上的任何差异都可能导致定时任务的触发时间出现误差。
    2. Hangfire的配置:确保你的Hangfire配置是正确的,特别是关于定时任务的部分。你已经设置了SchedulePollingIntervalTimeSpan.FromSeconds(1),这意味着Hangfire服务器会每秒检查一次新的定时任务。然而,实际任务的触发时间可能会受到其他因素的影响。
    3. 并发与线程安全:如果你的应用程序在多线程环境中运行,并且存在多个Hangfire服务器实例同时处理任务,可能会出现任务执行时间的偏差。确保你的后台任务是线程安全的,并考虑对Hangfire服务器的实例进行适当的配置和管理。
    4. MySQL作为存储后端:当你使用MySQL作为Hangfire的存储后端时,需要考虑数据库的性能和响应速度。如果数据库响应缓慢或存在性能瓶颈,可能会导致任务的触发时间出现延迟。
    5. 日志和监控:增加日志记录以监控任务的触发时间和执行时间。这可以帮助你更准确地确定问题的根源,并验证任务的触发是否受到外部因素的影响。
    6. 分布式系统和负载均衡:如果你在分布式系统或使用负载均衡的环境中运行应用程序,确保你的Hangfire配置考虑到这些因素。在多个服务器之间分配和处理任务时可能会出现偏差。
    7. 考虑其他因素:确保没有其他外部因素(如网络延迟、硬件资源限制等)影响任务的触发和执行时间。

    如果问题仍然存在,建议查看Hangfire的官方文档和社区论坛,看看是否有其他用户遇到了类似的问题和解决方案。此外,考虑使用其他后台任务库或解决方案来验证是否问题特定于Hangfire。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 10月20日
  • 已采纳回答 10月12日
  • 修改了问题 10月11日
  • 修改了问题 10月11日
  • 展开全部

悬赏问题

  • ¥60 Matlab联合CRUISE仿真编译dll文件报错
  • ¥15 脱敏项目合作,ner需求合作
  • ¥15 脱敏项目合作,ner需求合作
  • ¥30 Matlab打开默认名称带有/的光谱数据
  • ¥50 easyExcel模板 动态单元格合并列
  • ¥15 res.rows如何取值使用
  • ¥15 在odoo17开发环境中,怎么实现库存管理系统,或独立模块设计与AGV小车对接?开发方面应如何设计和开发?请详细解释MES或WMS在与AGV小车对接时需完成的设计和开发
  • ¥15 CSP算法实现EEG特征提取,哪一步错了?
  • ¥15 游戏盾如何溯源服务器真实ip?需要30个字。后面的字是凑数的
  • ¥15 vue3前端取消收藏的不会引用collectId