- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在编写一个向 REST API 服务发出频繁请求的 Android 应用程序。此服务的硬请求限制为每秒 2 个请求,之后它将返回 HTTP 503,没有其他信息。我想成为一名优秀的开发人员并限制我的应用程序以符合服务的要求(即在我的请求成功之前不要重试垃圾邮件服务),但事实证明这很难做到。
我正在尝试限制 OkHttpClient具体来说,因为我可以干净地将客户端实例插入 Coil和 Retrofit这样我的所有网络请求都会受到限制,而无需我在调用站点为它们中的任何一个做任何额外的工作:我可以调用 enqueue()
不假思索。然后重要的是我可以调用cancel()
或 dispose()
在 enqueue()
例如,当用户更改页面时,我可以避免执行不必要的网络请求。
我首先关注 this question 的答案使用 Guava RateLimiter
OkHttp 内部 Interceptor
,而且效果很好!直到我意识到我需要能够取消挂起的请求,而 Guava 的 RateLimiter
无法做到这一点。 , 因为它在 acquire()
时阻塞了当前线程s,然后防止请求被立即取消。
然后我尝试关注 this suggestion ,您调用Thread.interrupt()
让被阻止的拦截器恢复,但它不起作用,因为 Guava RateLimiter
s block uninterruptibly由于某些原因。 (注意:做 tryAcquire()
而不是 acquire()
然后中断 Thread.sleep()
不是一个很好的解决方案,因为你不知道要睡多久。)
因此,我开始考虑放弃 Guava 解决方案并实现一个自定义 ExecutorService ,它将请求保存在一个队列中,该队列将由计时器定期分派(dispatch),但对于一些可能工作或可能不工作的东西来说,这似乎是很多复杂的工作我现在已经远离杂草了。有没有更好或更简单的方法来做我想做的事?
最佳答案
最终我决定不配置 OkHttpClient
完全被限速。对于我的具体用例,我 99% 的请求是通过 Coil 完成的,剩下的少数请求不常见并且通过 Retrofit 完成,所以我决定:
Interceptor
根本,而是允许通过客户端的任何请求照常进行。假定改造请求很少发生,以至于我不在乎限制它们。 Queue
的类和 Timer
定期弹出并运行任务。它并不聪明,但它的效果出奇的好。我的线圈图像请求被放入队列中,以便它们调用 imageLoader.enqueue()
当他们到达前面时,但如果我需要取消请求,也可以从队列中清除它们。 import java.util.*
class RateLimitedQueue(private val millisecondsPerTask: Long) {
private val timer = Timer()
private val queue = ArrayDeque<Task>()
init {
timer.scheduleAtFixedRate(RunTaskTimerTask(this), 0, millisecondsPerTask)
}
private class RunTaskTimerTask(val parent: RateLimitedQueue) : TimerTask() {
override fun run() {
synchronized(parent.queue) {
if (!parent.queue.isEmpty())
parent.queue.pop().run()
}
}
}
fun interface Task {
fun run()
}
fun add(t: Task) {
synchronized(queue) {
queue.add(t)
}
}
fun remove(t: Task) {
synchronized(queue) {
queue.remove(t)
}
}
fun removeAll(filter: (Task) -> Boolean) {
synchronized(queue) {
queue.removeAll(filter)
}
}
}
我对这个解决方案很满意,但有一些值得注意的警告:
Timer
+ Queue
不是很聪明:它实际上只是每隔 X
检查一个任务毫秒,所以如果一个任务在很长的延迟之间到达一个空队列,它可能会不必要地等待。你可以想出一些更优雅的东西,但我发现它可以很好地处理我 500 毫秒的延迟。 Interceptor
那样干净,因为它不在 Retrofit 和 Coil 之间共享。 关于java - 如何让 OkHttpClient 遵守 REST API 速率限制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66684303/
我有许多不同的 OkHttpClient 请求拦截器。每个拦截器只需要应用程序发出的网络请求的一个子集。到目前为止,我已经提出了两种可能的设计。我应该: 将每个拦截器附加到单个 OkHttpClien
我的应用程序 API 执行奇怪的行为。我的一个实时应用程序的 API 预计响应时间为 2 到 3 秒,但响应时间很长! 测试用例: 使用 WIFI = 是 与 Airtel 运营商合作 = 是 与 J
我正在尝试使用 okHttpClient 4.2.1 库注册用户,作为响应,我得到了一些垃圾值 Respone is �������������V*.MNN-.V�JK�)N�Q�r�S���rR�
我将 OkHttp3 与 proxy-vole 库一起使用来自动选择要使用的代理。就我而言,使用自动配置有 4 个可能的代理可用(都是相同的概念,只是负载平衡)。然而,似乎只有其中之一可以在没有显式身
我想要获得正文响应,但收到错误 403,尽管页面在 webview 和浏览器中打开。我的代码: OkHttpClient client = new OkHttpClient();
我有一个 Web 容器 (Glassfish),在其系统属性上为一个应用程序配置了代理。 现在我在同一个 Web 容器上有另一个应用程序,我想使用 OkHttpClient 通过代码自定义代理使用。
尝试了解我在传输到 OkHttpClient 时可以定义的最佳 Java ThreadPoolTaskExecutor(延迟方面)。目前我们的定义如下: 最大队列容量(将打开新线程)为 20
在我的第一个 Android 项目中,我创建了一个 onClick 事件来调用函数: public void doSomething(View v) { String result =
okHttpClient在出现如下flag时会重试多少次才放弃public OkHttpClient.Builder retryOnConnectionFailure(boolean retryOnC
只是想模拟 OkHttpClient 以使用 Mockito 进行测试。遗憾的是,OkHttpClient 是 Mockito 不支持的最终类。有没有其他可能进行 mock ,你们在 cicrumst
我正在使用改造和 okHttp 客户端连接到我的 rest api。当我在 Tomcat 上禁用基本身份验证时,一切正常。在 Tomcat 上启用 Basic Auth 后,我收到 404 Page
我在我的类中使用注入(inject)的 OkHttpClient 对象。我正在使用方法注入(inject)在我的客户端对象上设置一些拦截器,如下所示: @Inject private OkHttpCl
我有一个 Android 应用程序需要使用 REST 连接到服务器。我使用 Retrofit 2 来处理请求,效果很好。问题是当我想使用 SSL 连接时。使用开放式 ssl,我有一个 client.c
OkHttpClient 是否可以限制实时连接数?因此,如果达到限制,则不会选择和建立新连接? 我的应用同时启动多个连接。 最佳答案 连接数可在Dispatcher中配置,而不是在仅允许配置最大空闲连
我正在为 OkHttpClient 设置连接失败时重试选项。 client = new OkHttpClient(); client.setRetryOnConnectionFailure(true)
我最近升级到 OkHttp3 ,并注意到您无法再直接从客户端取消通过标签调用。这必须由应用程序现在处理。 在 CHANGELOG 中说明这里: Canceling batches of calls i
我想使用 OkHttpClient 加载一个 url,如果给定 url 的网站以 pdf 内容类型响应,我将继续下载 PDF,否则我想忽略该响应。 我的问题是,我是否需要做任何特殊的事情来关闭请求/响
enter image description here Okhttp 使用 OkHttpClent 发送请求。 我可以使用相同的 OkHttpClent 实例在不同的线程中请求吗? 最佳答案 是的。
我想使用PipedOutputStream和 PipedInputStream流响应主体。我不太确定它在多线程方面是否安全。将从不同的线程访问响应。 public Streamer execute()
我正在努力实现这个目标 这是/delete/{id} 如何在 java 中执行此操作? String id = "123"; OkHttpClient client = new OkHttpClien
我是一名优秀的程序员,十分优秀!