okhttp连接池的bug导致网络连接慢甚至出现阻塞的情况

admin 2023-04-29 PM 3807℃ 65条

问题一:关于 OkHttp 请求延迟阻塞现象的解决记录

近期现场的设备出现了 loading 弹出异常的问题,通过排查日志,发现出现了很怪异的现象。

  • 网络请求前的日志正常打印,网络请求拦截器中的日志延迟很久才打印,最多有13分钟之后才打印网络请求。
  • 查服务器端日志,发现服务器也是13分钟之后接到的网络请求
  • 怀疑是线程阻塞或者机器卡住,对多项并行操作增加线程池管理之后问题仍然出现。
  • 查阅日志,在网络请求被延迟的这段时间,socket 正常。

最后通过查阅资料与源码,发现如果配置的 Dns 服务异常,会因为 okhttp 解析导致的网络请求延迟,而该代码在请求连接池之前,所以拦截器中的日志也没有执行。

更换Dns即可。

问题二:

脚本:
在没有互联网的情况下打开应用程序,该应用程序将尝试执行请求,但将失败
打开互联网连接,然后按下重试按钮以触发互联网请求
改装&okhttp总是给我HTTP失败:java.net.SocketTimeoutException:超时
从一开始就在启用互联网的情况下重新启动应用程序将使一切正常,除非我再次关闭它,并使请求失败,否则从那时起,它将给我同样的错误。我从来没有在Java上遇到过这个问题,只是在Kotlin上。

private val interceptor: Interceptor =
        object : Interceptor {
            override fun intercept(chain: Interceptor.Chain): Response {
                var builder = chain.request().newBuilder()
                Prefs.token?.let { token ->
                    builder = builder.addHeader("Authorization", "Bearer $token")
                }
                return chain.proceed(builder.build())
            }
        }

private val httpLoggingInterceptor: HttpLoggingInterceptor by lazy {
    val interceptor = HttpLoggingInterceptor()
    interceptor.level =
            if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE
    interceptor
}
private val httpClient: OkHttpClient by lazy {
    OkHttpClient.Builder()
            .addInterceptor(httpLoggingInterceptor)
            .addInterceptor(interceptor)
            .build()
}

val retrofit: Retrofit by lazy {
    Retrofit.Builder()
            .baseUrl("https://api.secret.com/v1/")
            .addConverterFactory(GsonConverterFactory.create(gson))
            .client(httpClient)
            .build()
}

服务类是这样的

@GET("something")
fun something(): Call<SomeResponse>

我试过使用超时值,无论超时时间如何,我都会得到同样的错误。
为每个请求创建一个新的http客户端可以解决这个问题,但我认为这不是一个好主意。

网友回答:

您的问题看起来像OkHttp Bug。如果你点击链接,你会发现有很多可能的解决方案进行了长时间的讨论。
以下解决方案适用于我的项目:

  • 1、将OkHttp更新至4.3.0版本。
  • 2、设置ping间隔,例如1秒

    okHttpClientBuilder.pingInterval(1, TimeUnit.SECONDS)
    

    它是如何工作

问题的根源在于,Android操作系统无法提供任何方式来知道连接不再处于活动状态。因此,对于库连接来说,这看起来是有生命的,但它已经死了。因此,我们在每个请求上都会出现超时异常。一旦我们设置了ping,OkHttp就会开始发送ping帧,这样,若服务器并没有响应,库就会知道连接已经断开,是时候创建一个新的连接了。
不推荐解决方案,但应该有效

  • 1、关闭连接池

    okHttpClientBuilder.connectionPool(new ConnectionPool(0, 1, TimeUnit.NANOSECONDS))
  • 2、使用Http 1.1

    okHttpClientBuilder.protocols(listOf(Protocol.HTTP_1_1))
    

    在这两种不推荐的解决方案中,您只需停止重复使用已经打开的连接,这会使每个请求的时间稍微长一点。

标签: okhttp

非特殊说明,本博所有文章均为博主原创。

上一篇 从内存中直接加载执行ELF - scz
下一篇 没有了

评论啦~



已有 65 条评论


  1. 1
    1

    1

    回复 2023-05-19 20:22
    1. 1
      1

      1

      回复 2023-05-19 21:01
      1. 1
        1

        555

        回复 2023-05-22 10:08
        1. 1
          1

          1

          回复 2023-05-22 13:23
        2. 1
          1

          1

          回复 2023-05-22 13:23
        3. 1
          1

          1

          回复 2023-05-22 13:23
        4. 1
          1

          1

          回复 2023-05-22 13:23
        5. 1
          1

          1

          回复 2023-05-22 13:23
        6. 1
          1

          1

          回复 2023-05-22 13:30
      2. 1
        1

        1

        回复 2023-05-22 13:22
      3. 1
        1

        1

        回复 2023-05-22 13:22
      4. 1
        1

        1

        回复 2023-05-22 13:22
      5. 1
        1

        1

        回复 2023-05-22 13:22
    2. 1
      1

      555

      回复 2023-05-19 21:32
    3. 1
      1

      1

      回复 2023-05-20 00:26
    4. 1
      1

      1

      回复 2023-05-20 00:28
    5. 1
      1

      1

      回复 2023-05-20 00:28
    6. 1
      1

      1

      回复 2023-05-20 00:28
    7. 1
      1

      1

      回复 2023-05-20 00:28
    8. 1
      1

      1

      回复 2023-05-20 00:28
    9. 1
      1

      1

      回复 2023-05-22 09:53
    10. 1
      1

      1

      回复 2023-05-22 13:17
    11. 1
      1

      1

      回复 2023-05-22 13:19
    12. 1
      1

      1

      回复 2023-05-22 13:19
    13. 1
      1

      1

      回复 2023-05-22 13:20
    14. 1
      1

      1

      回复 2023-05-22 13:20
    15. 1
      1

      1

      回复 2023-05-22 13:20
    16. 1
      1

      1

      回复 2023-05-22 13:20
    17. 1
      1

      1

      回复 2023-05-22 13:21
    18. 1
      1

      1

      回复 2023-05-22 13:21
    19. 1
      1

      1

      回复 2023-05-22 13:21
    20. 1
      1

      1

      回复 2023-05-22 13:21
    21. 1
      1

      1

      回复 2023-05-22 13:21
    22. 1
      1

      1

      回复 2023-05-22 13:29
  2. 1
    1

    1

    回复 2023-05-19 20:43
    1. 1
      1

      1

      回复 2023-05-19 21:09
  3. 1
    1

    555

    回复 2023-05-19 20:59
  4. 1
    1

    555

    回复 2023-05-19 21:55
    1. 1
      1

      1

      回复 2023-05-20 00:25
    2. 1
      1

      1

      回复 2023-05-20 00:25
    3. 1
      1

      1

      回复 2023-05-20 00:25
    4. 1
      1

      1

      回复 2023-05-20 00:25
    5. 1
      1

      555

      回复 2023-05-20 00:48
  5. 1
    1

    1

    回复 2023-05-20 00:24
  6. 1
    1

    1

    回复 2023-05-20 00:24
  7. 1
    1

    1

    回复 2023-05-20 00:24
  8. 1
    1

    1

    回复 2023-05-22 09:41
  9. 1
    1

    555

    回复 2023-05-22 10:21
  10. 1
    1

    1

    回复 2023-05-22 11:22
  11. 1
    1

    1

    回复 2023-05-22 11:22
    1. 1
      1

      1

      回复 2023-05-22 12:13
    2. 1
      1

      1

      回复 2023-05-22 12:13
    3. 1
      1

      1

      回复 2023-05-22 12:13
    4. 1
      1

      1

      回复 2023-05-22 12:15
    5. 1
      1

      1

      回复 2023-05-22 12:15
    6. 1
      1

      1

      回复 2023-05-22 12:15
    7. 1
      1

      1

      回复 2023-05-22 12:15
      1. 1
        1

        1

        回复 2023-05-22 12:19
      2. 1
        1

        1

        回复 2023-05-22 12:19
      3. 1
        1

        1

        回复 2023-05-22 12:19
      4. 1
        1

        555

        回复 2023-05-22 14:32
  12. 1
    1

    1

    回复 2023-05-22 12:18
  13. 1
    1

    1

    回复 2023-05-22 12:18
  14. 1
    1

    555

    回复 2023-05-22 14:54
  15. 1
    1

    555

    回复 2023-07-07 15:13