功能说明

LongIntervalRetries是基于Quartz.Net的一个长时间间隔重试的类库,其主要解决何时执行以及执行结果反馈的问题。

产生的原因

简单的说,我们提供了一系列的API供第三方调用,但因为实际API对应的业务处理时间较长,所以为了增加吞吐量,实际的业务逻辑并没包含在API服务器,而是分布在了不同的服务器上进行处理,在业务处理结束后,再通过调用第三方提供的回调Url通知处理结果,为了保证回调正确,那么我们需要有这么一个策略:如果回调失败,我们需要在指定时间间隔之后再次回调,如此反复直至回调成功或者达到重复次数上限。上述回调方案是不是很熟悉?嗯,好吧,直白的讲,回调这一部分我们借鉴(抄袭)了支付宝支付时的回调方案,所以我们要解决的,就是通过代码来实现回调这部分的业务场景,于是也就有了LongIntervalRetries

为什么不使用Polly

Polly是.NET基金会下的弹性和瞬态故障处理库,其解决的问题天然符合我们回调的业务场景,但为什么在此处却不被采用呢,原因如下:

  • Polly的重试机制是个短时间内的机制,在其重试机制时间内,当前Task一般是通过await阻塞的,而对于我们的场景来说,这明显是不合适的,我们的场景并不应该发生在当前线程内
  • Polly并不支持程序重启时的重试恢复,这一点在我们的业务场景中及其重要,总不能服务器重启后,我们还没回调成功的业务就全部丢了吧

设计思路及演变

一开始我们的设计思路非常简单,就是如何定时触发回调这个业务代码,但之后发现,为什么我们要仅限于回调呢?回调只是一个业务场景,但我们完全有可能有其它业务场景,恰恰我们也的确存在这样的业务场景,我们需要向第三方服务商进行一些请求,该请求同样耗时较长,该场景是不是很熟悉?只不过与我们作为服务商不同,该服务商居然没提供回调方案,它需要我们自己定时去回调!而同样是这个第三方,其业务请求参数具有相当的定制性,其需要我们预先做很多业务性的预处理,也就是需要做一些顺序性的工作后,我们才能得到完整的请求参数。

于是我们的设计思路开始调整,最终得出该封装应当具备的功能点:

  • 其内部应该封装掉如何定时触发这个功能
  • 其应该具备同时支持多种业务策略(策略模式)
  • 其应该允许设置什么时候来触发要执行的策略
  • 其应该支持服务启动时自动恢复未结束任务的能力
  • 其应该具备最终执行结果通知的能力

为什么会考虑基于Quartz.Net

无论是定时触发,还是业务策略,以及设置触发时间,这些都很明显的具备Job特性,而Quartz.Net本身就是一个Job类库,而且其本身允许进行并发线程数量设置,如果基于它,明显我们可以不用考虑线程相关的问题,这可以省掉我们很大的工作量

类库相关

该类库在github上的地址为:https://github.com/fdstar/LongIntervalRetries

该类库目前为v1.0.0版本,其nuget地址为:https://www.nuget.org/packages/LongIntervalRetries/

快速使用

此处仅是简单的代码示例,后续会有详细的使用说明

首先我们需要声明Job

    public class SomeJob: IJob
{
public virtual Task Execute(IJobExecutionContext context)
{
return Task.FromResult(1);//默认LongIntervalRetries是通过Job是否产生异常来判断是否执行成功的
}
}

然后我们可以将这个Job注册到LongIntervalRetries,同时设置重试策略,以及注册事件监控执行结果,完整的示例如下

var retry = new StdRetry();
//声明并注册重试规则
string simpleRuleName = "SimpleRepeatRetryRule";
var simpleRepeatRule = new SimpleRepeatRetryRule(simpleRuleName, 5, TimeSpan.FromSeconds(2));
retry.RuleManager.AddRule(simpleRepeatRule);
var registerInfo = new RetryJobRegisterInfo
{
//指定要采用的重试规则,如果不设置,则默认使用已注册的第一项
UsedRuleName = simpleRuleName,
//需要传递给IJob的上下文数据
JobMap = new Dictionary<string, object>
{
{"SomeKey","SomeValue" }
},
//开始执行时间,如果不指定则表示立刻执行
StartAt = DateTimeOffset.UtcNow.AddSeconds(3),
};
//注册要执行的Job
retry.RegisterJob<SomeJob>(registerInfo);
//注册每次Job执行后的通知事件
retry.RegisterEvent<SomeJob>(e =>
{//Some code
});
retry.Start();//启动Quartz服务
//启动服务后仍可以RegisterJob、RegisterEvent

【LongIntervalRetries】让我们来实现支付宝的异步回调方案的更多相关文章

  1. 服务器收不到支付宝notify_url异步回调请求的问题 支付宝notify 异步通知与https的问题

    需确认页面是http还是https,如果是https,那么需要安装ssl证书,证书要求有如下:要求“正规的证书机构签发,不支持自签名”. 然后赶快,按照支付宝,宝爷的要求,去自检了一下自家的证书,下面 ...

  2. 服务器收不到支付宝notify_url异步回调请求的问题排查

    小背景 最近在调整支付宝支付的功能时发现,不能够正常接收支付宝付款成功之后的回调通知了,从代码到配置最后到服务器配置都排查了一遍,最终发现问题原因竟然是因为我们的回调地址notify_url是http ...

  3. 通知url必须为直接可访问的url,不能携带参数 异步接收微信支付结果通知的回调地址 不能携带参数。 回调地址后是否可以加自定义参数 同步回调地址 异步回调地址 return_url和notify_url的区别

    [微信支付]微信小程序支付开发者文档 https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_7 通知url必须为直接可访问的 ...

  4. 支付回调地址 同步回调地址 异步回调地址 return_url和notify_url的区别

    [微信支付]JSAPI支付开发者文档 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_16&index=10 退款结果通知 ...

  5. node 异步回调解决方法之yield

    先看如何使用 使用的npm包为genny,npm 安装genny,使用 node -harmony 文件(-harmony 为使用es6属性启动参数) 启动项目 var genny= require( ...

  6. c#线程之异步委托begininvoke、invoke、AsyncWaitHandle.WaitOne 、异步回调

    单靠自己看书学总是会走很多弯路,任何人也不列外,有些时候自己遇到的很多问题,其它别人在很久之前也可能遇到过,上网查查可以走很大捷径,对自己的学习有很大帮助,刚开始弄线程这块,一开始只是看书,很多东西都 ...

  7. Android异步回调中的UI同步性问题

    Android程序编码过程中,回调无处不在.从最常见的Activity生命周期回调开始,到BroadcastReceiver.Service以及Sqlite等.Activity.BroadcastRe ...

  8. java 中的异步回调

    异步回调,本来在c#中是一件极为简单和优雅的事情,想不到在java的世界里,却如此烦琐,先看下类图: 先定义了一个CallBackTask,做为外层的面子工程,其主要工作为start 开始一个异步操作 ...

  9. C“中断” 与 JS“异步回调” 横向对比

    在底层C语言中,有一个非常重要而特别的概念,叫做“中断”.用比喻来说,我正在写着博客,突然我妈打个电话过来,我就离开了键盘去接电话了,然后写博客就中断了,我聊完电话回来再继续写.乍一听似乎并没有什么大 ...

随机推荐

  1. 常用修图工具的一些使用技巧及问题解决方法——ai

    一.ai如何修改画布大小 一. ai如何修改画布大小: 1. 左上角菜单中的文件——文档设置(也可以直接点菜单栏下边的控制栏中的文档设置) 2. 文档设置界面中,点击右上角“编辑画板“ 3. 此时面板 ...

  2. 对于局部变量,text、ntext 和 image 数据类型无效

    开发存储过程时报如上错误.大多数人说用varchar(8000)代替text,但值我这里超过8000,不可取 解决: sql2005或以上版本支持新数据类型:varchar(max)nvarchar( ...

  3. 11-st跳舞消耗体力最少

    /*                                                   炫舞家 ST 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描述   ...

  4. php使用jquery Form ajax 提交表单,并上传文件

    在html5中我们通过FormData就可以ajax上传文件数据,不过因为兼容问题.我们选用jquery.form.min.js来进行ajax的表单提交.   一.jquery.form.js下载地址 ...

  5. PHP下ajax跨域的解决方案之CORS

    由于安全的限制(同源策略,javascript只能访问同域名下的内容),如果需要进行跨域操作,那就免不了要进行跨域.   CORS(跨域资源共享,Cross-Origin Resource Shari ...

  6. jxl 创建excel

    public static void performanceExcel(String sCurrPath,List<Record> list, String begin,String en ...

  7. Spring整合Struts2框架的第二种方式(Action由Spring框架来创建)(推荐大家来使用的)

    1. spring整合struts的基本操作见我的博文:https://www.cnblogs.com/wyhluckdog/p/10140588.html,这里面将spring与struts2框架整 ...

  8. src/lxml/includes/etree_defs.h:14:31: 致命错误:libxml/xmlversion.h:没有那个文件或目录

    fedora21平台下解决办法:yum install libxml-devel ubuntu下可以使用 apt-get intalll xxxx 如果仍然出现,可以尝试安装这两个包libxslt-d ...

  9. 04 Maven 仓库

    Maven 仓库 在 Maven 坐标与依赖 中详细介绍了 Maven 坐标和依赖,坐标和依赖是任何一个构件在 Maven 世界中的逻辑表示方式:而构件的物理表示方式是文件, Maven 通过仓库来统 ...

  10. 创建WRAPPER时, SQL20076N 未对指定的操作启用数据库的实例。

    您可以通过运行DB2 UPDATE DBM CFG USING FEDERATED YES来设置这个参数.修改这个参数后,必须重新启动实例才会生效(DB2STOP/DB2START).所以你会出现你的 ...