【发布时间】:2021-06-15 10:52:33
【问题描述】:
我正在编写一个向 REST API 服务发出频繁请求的 Android 应用。此服务的硬请求限制为每秒 2 个请求,之后它将返回 HTTP 503,没有其他信息。我想成为一名优秀的开发人员并限制我的应用程序以符合服务的要求(即在我的请求成功之前不要重试向服务发送垃圾邮件),但事实证明这很难做到。
我正在尝试对OkHttpClient 进行速率限制,因为我可以干净地将客户端实例插入Coil 和Retrofit,这样我的所有网络请求都会受到限制,而无需我做任何额外的工作在他们中的任何一个的呼叫站点上:我可以直接拨打enqueue() 而无需考虑。然后重要的是我能够在enqueue()ed 请求上调用cancel() 或dispose(),这样我就可以避免在用户更改页面时进行不必要的网络请求。
我首先关注this question 的答案,该答案在 OkHttp Interceptor 内部使用 Guava RateLimiter,它运行良好!直到我意识到我需要能够取消挂起的请求,而 Guava 的 RateLimiter 无法做到这一点,因为它在 acquire()s 时阻塞了当前线程,从而阻止了请求立即被取消.
然后我尝试关注this suggestion,您在其中调用Thread.interrupt() 以使被阻止的拦截器恢复,但由于某种原因它无法工作,因为Guava RateLimiters block uninterruptibly。 (注意:使用tryAcquire() 而不是acquire() 然后中断Thread.sleep()ing 不是一个很好的解决方案,因为你不知道要睡多久。)
然后我开始考虑放弃 Guava 解决方案并实现一个自定义 ExecutorService 将请求保存在一个队列中,该队列将由计时器定期分派,但对于可能或可能的事情来说,这似乎是很多复杂的工作不工作,我现在离杂草很远。有没有更好或更简单的方法来做我想做的事?
【问题讨论】:
-
您可以手动控制您自己的 RateLimiting。这是来自 Misk 的一个例子。 github.com/cashapp/misk/blob/…
-
我必须调查一下,感谢您的指点。我宁愿不必编写自己的 RateLimiter,但如果这是唯一可以做的事情......
-
您可以在自定义 Call.Factory 中应用速率限制。这将允许您在执行前实现支持取消的自定义调用。
-
仅供参考,它是刮而不是刮。报废意味着像垃圾一样扔掉东西。
-
在上下文中我认为只有报废(像垃圾一样扔掉才有意义)
标签: java android kotlin okhttp