yuzd / Hangfire.HttpJob

httpjob for Hangfire,restful api for Hangfire,job调度与业务分离
https://github.com/yuzd/Hangfire.HttpJob/wiki
MIT License
626 stars 185 forks source link

使用过程遇到的一些问题整理 #74

Closed zhujiancc closed 3 years ago

zhujiancc commented 3 years ago
  1. hangfire 的执行结果和httpagent不一致, 感觉可以做一些整合处理, 比如http agent 失败了 推送到 hangfire fail list 或者dashboard 增加可查看的相关列。
  2. 全局的DingTalkOption 不能传递到 httpagent: OnException(JobContext jobContext, Exception ex) 的 context 中, 只有jobitem的可以。
  3. hangfire的调度结果和httpagent 的执行结果拆分。 最好可以封装一些两者通用的工具类。比如mail ,dingding 之类的。
  4. httpagent 的单例模式,多次执行导致的异常。 归hangfire 调度失败吗? 我感觉属于httpagent 的行为。
  5. JobContext 可否添加多一些数据。 比如执行的JobId
  6. dingding 的模板能否自定义
  7. dingding 的sign 模式只能手动append 到querystring 。

写的比较零散, 说的不好希望不要介意:)

yuzd commented 3 years ago

谢谢你的问题整理

1.hangfire 的执行结果和httpagent不一致, 感觉可以做一些整合处理, 比如http agent 失败了 推送到 hangfire fail list 或者dashboard 增加可查看的相关列。


hangfire和agent的结果不一致的原因是  
hangfire调度jobagent,就是发http请求给jobagent,
然后jobagent端check可以运行会直接返回response返回给hangfire,
实际上jobagent真正的job代码是异步(新线程)执行。

所以hangfire调度jobagent 拿到的结果仅仅是调度成功与否。而不是实际jobagent内的代码真正执行成功与否!
但,对于hangfire来说此次调度就已经结束了。

2全局的DingTalkOption 不能传递到 httpagent: OnException(JobContext jobContext, Exception ex) 的 context 中, 只有jobitem的可以。 这个我查下看看

3.hangfire的调度结果和httpagent 的执行结果拆分。 最好可以封装一些两者通用的工具类。比如mail ,dingding 之类的。

关于这点,要么就是这样
在JobContext 提供一个Notify的接口实现。
把hangfire调度端配置的mail或者dingding的参数全都能传到jobagent上
 jobagent的 OnException方法搞成虚方法,不必强制实现。默认的实现就是去看在调度端如何配置的 是发邮件呢还是发钉钉。

4.httpagent 的单例模式,多次执行导致的异常。 归hangfire 调度失败吗? 我感觉属于httpagent 的行为。

单例模式在没有处理完 重复调度 会出异常。这个是jobagent端check住直接返回给hangfire的异常。
你可以理解为hangfire在去调度jobagent没有成功。

5.JobContext 可否添加多一些数据。 比如执行的JobId 应该可以 我看看

6.dingding 的模板能否自定义 7.dingding 的sign 模式只能手动append 到querystring 。

关于钉钉的通知这块没有太多考虑这2点。如果jobagent你自己发dingding的话 都可以自定义

zhujiancc commented 3 years ago

Thanks for your answer:

问题1:

hangfire 调度结果和httpagent 的执行结果拆离, 我是完全赞同的。
现在hangfire 的异常推送之类是基本没问题的。 
只是不好监控到 httpagent的 执行情况, 有了调度的推送,最好也有执行的推送,如果可以把执行情况集成到dashboard 上就更好了。 
在使用过程中, 关注的更多是,当job非常多的时候, 怎么快速发现问题,处理问题。
yuzd commented 3 years ago

这个只能想办法给hangfire的dashbord上进行扩展了,加一个jobagent的页面。数据让jobagent直接插入到hangfire的存储storage 那你怎么认为jobagent的执行是成功还是失败呢?自己没catch异常 抛出来被我抓到了就算是异常?

zhujiancc commented 3 years ago

jobagent 执行失败,或者catch 到内部异常,我认为就是执行失败了。 如果要区分,加个状态值即可。

yuzd commented 3 years ago

我的疑问是,写代码的人自己catch异常了,那我不知道这个agent job是执行成功还是失败

zhujiancc commented 3 years ago

那就不用管了, 说明他允许这么搞, 况且可以打日志的。

zhujiancc commented 3 years ago

@yuzd 大佬请教个问题: 我想在HttpAgent的OnException触发的时候, 修改当前Job的State,但没有找到合适的解决方法。 源码扒下来,这块涉及很多表的更新变动,虽然一个个表的修改也可以做到。(但不同的Storage实现还不一样~_~) 我没有找到暴露出来的相关接口。 Hangfire内部是通过 IBackgroundJobStateChanger ChangeState 来搞的。 框架外能复用这块代码吗?

yuzd commented 3 years ago

正如我上面所说的 hangfire内部的状态 只能是从hangfire调度那边下手。我能想到的是hangfire调度端增加一个接口让agent去调用。我还没时间开始动手,如果你搞的话可以给个pr

yuzd commented 3 years ago

第一个问题我是用storage作为媒介来改的, 原理是遇到jobagent的,之前的逻辑是两步,服务端只是调度 调度后状态就改了,新的逻辑是调度后状态不改变,等待agent上报后去改,服务端timer还没好,今天搞定,不过你可以测试一下,只是差状态没改。

yuzd commented 3 years ago

第二个问题,昨晚的代码修复了。第四个问题 我加了一个配置可以开关可以配置是否把这种错误视为正常。第五个问题也修复了加了jobid,job的url

yuzd commented 3 years ago

第六个问题,agent端的dingding消息,后面收口到agent上报,服务端timer拉到后进行处理,这个还没好

zhujiancc commented 3 years ago

新版本 TestHangfireRedisAgent 单例任务测试

public class TestJob : JobAgent
{
    private readonly ILogger<TestJob> _logger;

    public TestJob(ILogger<TestJob> logger)
    {
        _logger = logger;
        _logger.LogInformation($"Create {nameof(TestJob)} Instance Success");
    }
    public override async Task OnStart(JobContext jobContext)
    {
        jobContext.Console.WriteLine("开始等待10秒");
        jobContext.Console.WriteLine("结束等待10秒");
        jobContext.Console.WriteLine("哈哈哈哈", ConsoleFontColor.Cyan);
        jobContext.Console.WriteLine("开始测试Progressbar", ConsoleFontColor.Cyan);
        _logger.LogWarning(nameof(OnStart) + (jobContext.Param ?? string.Empty));

        var bar = jobContext.Console.WriteProgressBar("testbar");
        for (int i = 0; i < 5; i++)
        {
            bar.SetValue(i*10);
            await Task.Delay(1000);
        }
        _logger.LogWarning(nameof(OnStart) + (jobContext.Param ?? string.Empty));

        throw new Exception("xx");
    }

    public override void OnStop(JobContext jobContext)
    {
        _logger.LogInformation(nameof(OnStop));
    }

    //public override void OnException(JobContext jobContext, Exception ex)
    //{
    //    _logger.LogError(ex, nameof(OnException) + (ex.Data["Method"] ?? string.Empty));
    //}
}

bug

  1. 任务【hang/singleton】执行失败之后, 没有进入到 【jobs/failed】 的列表,都停留在processing 里边了。

新的问题

我们这边有很多长期执行的任务,如果我用 [HangJobUntilStop(true)] 标注这个任务, 那这个任务就会长期挂在processing 列表里 这边有几个问题:

  1. 如果任务执行的服务重启或者挂了,
    • hangfireserver 怎么重新启动这个任务
    • hangfireserver 怎么处理这个任务的状态【remove processing and enqueue to failed ?】
  2. 长期执行的任务执行异常了,怎么处理【推送消息||在processing detail console 打印failed 日志?】
yuzd commented 3 years ago

最新版已解决