从 Java (中间件) 转型到 Go (围绕 k8s 二开)发现一个有趣事情,不同语言的主导生态不一样,有很多细节上的区别。
之前写 Java 的时候经常用的 Ratelimiter 比如 resilience4j ratelimiter 一般都是当抵达上线的时候会触发一个 RuntimeExpection
Try.run(restrictedCall)
.andThenTry(restrictedCall)
.onFailure((RequestNotPermitted throwable) -> LOG.info("Wait before call it again :)"));
算是一种 Fast Fail
的类型,但是前段时间在 CodeReview 代码的时候,
RateLimiter: workqueue.NewMaxOfRateLimiter(
workqueue.NewItemExponentialFailureRateLimiter(1*time.Second, 120*time.Second),
&workqueue.BucketRateLimiter{Limiter: rate.NewLimiter(rate.Limit(10), 100)},
),
习惯性的认为,在这个逻辑是,超过 10QPS 的时候会触发一个 Error ,然后进入 workqueue 重试,最短 1 秒,最长 120 秒。
但是实际上 BucketRateLimiter
是返回了一个预期的延期执行 Duration ,随着请求增加,最长是 1000S ,并没有什么 Error
type RateLimiter interface {
// When gets an item and gets to decide how long that item should wait
When(item interface{}) time.Duration
// Forget indicates that an item is finished being retried. Doesn't matter whether its for perm failing
// or for success, we'll stop tracking it
Forget(item interface{})
// NumRequeues returns back how many failures the item has had
NumRequeues(item interface{}) int
}
这个不一致导致了一些故障。
感觉不同的语言生态里面的这种具体实现的区别还是很大的,有点知识的诅咒的感觉,原理虽然相通,但是实践上还是要谨慎。
1
rekulas 2022-08-10 13:36:45 +08:00
是因为库开发者并不是同一个团队吧?每个项目的思路不同,肯定不可能确保各种逻辑实现一样的,除非已经有标准规范大家基于规范来开发-例如各种区块链协议、redis 协议
没有标准协议但同一个团队开发的跨语言库就比较好迁移,因为他们都会尽量确保一致性 |