发送 Webhook 实现跨应用异步回调


发送 Webhook

除了邮件发送和定时任务调度外,我们还可以通过消息队列异步对第三方服务发起网络请求,就像 JavaScript 中的 Ajax 那样,进行跨应用的消息推送。一个比较典型的场景就是通过发送 Webhook 实现异步回调通知。

我们创建一个队列任务类 SendWebhook 用于执行 Webhook 的发送工作,在 handle 方法中,通过 Laravel 自带的 HTTP 客户端发送包含事件数据的 POST 请求到给定 URL 作为 Webhook,URL 对应应用收到这个请求后,再进行后续处理工作:

这里,我们还设置了请求的超市时间是 5s,超过这个时间没有收到对方应用的响应,则认为请求超时。

接下来,就可以通过如下方式在控制器方法中将 SendWebhook 任务推送到消息队列异步处理了,在推送时将第三方服务和事件实例作为参数传递进来,以便在处理任务时使用:

请求失败后重试

既然是 HTTP 网络请求,那么就有可能因为各种原因导致请求失败,比如网络断开、对方服务器宕机、指定 URL 不存在、或者对方服务不可用。体现在 $response 的结果上就是抛出超时异常、得到 404 或者 500 响应,我们可以在判定响应失败后进行重试:

当然,如果我们为 SendWebhook 设置了最大尝试次数 tries,请求失败的情况下,Laravel 消息队列会自动重试这个任务,不过通过这种手动重试的方式可以更加精细地控制重试的底层逻辑,比如每次失败后延迟多久进行下一次重试,这里配置的其实是跳跃式重试,因为每次重试都会将 attempts 值加一:

之所以将延迟时间设置这么长,因为 HTTP 请求的响应时间是不可控的,而且如果一两次请求失败可能是网络抖动,但多次请求失败则很可能是服务已经不可用了(网络断开、服务器宕机、服务崩溃等),这个时候,频繁重试反而会浪费系统的资源,增加系统负载。

配置任务过期

以上任务推送、异步处理和失败重试都是自动进行的,诚如我们上面所说,如果是第三方服务确实不可用,再多次的重试也是徒劳的,只会毫无意义地增加系统资源的空耗(每执行一次任务需要消耗当前机器的 CPU 和内存资源)。

这个时候,我们可以设置任务重试次数的上限,或者给失败重试设置一个终止条件,比如一天后不再重试,这可以通过为任务类定义 retryUtil 方法来实现:

这种情况下,通常还需要配合将最大尝试次数设置为无限重试:

否则可能就不会触发 retryUtil 条件了,其实这两个任意设置一个即可,目的都是为了给失败重试设置终止条件,避免无限重试下去。

处理任务失败

最后,如果队列任务触发了最大尝试次数上限,或者在终止期限之前还没有执行成功,则会被标记为执行失败,你可以为任务类定义 failed 方法,以便在它执行失败后给开发者或者运营人员发送邮件/短信通知,人为介入进来,推动问题的解决,比如解决程序问题,或者反馈给第三方服务商解决问题:


点赞 取消点赞 收藏 取消收藏

<< 上一篇: 自动取消已放弃的订单

>> 下一篇: 取消会议和自动退款处理