发送 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
方法,以便在它执行失败后给开发者或者运营人员发送邮件/短信通知,人为介入进来,推动问题的解决,比如解决程序问题,或者反馈给第三方服务商解决问题:
1 Comment
大佬就是大佬,思路极度清晰