首页 > 解决方案 > 改造自定义超时无法正常工作

问题描述

我有一个客户端执行 n 次特定超时重试,当我在模拟器中执行测试时,每次重试总是需要 40 秒,甚至更多,我配置的时间是 5 秒。

我通过评论以下三行进行了测试:

 .connectTimeout(TIMEOUT, TimeUnit.SECONDS)
 .writeTimeout(TIMEOUT, TimeUnit.SECONDS)
 .readTimeout(TIMEOUT, TimeUnit.SECONDS)

期望它采用默认超时(10 秒)有时结果是正确的(10 秒),在几次执行后时间不再匹配。

还在物理设备上执行测试,同样的事情也会发生。

知道发生了什么吗?

object Client {

private const val PATTERN = "0000"
private const val S_TAG = "{SN}"
private const val C_TAG = "{CC}"

/**
 * Retrofit Builder is created
 * @param sNbr
 * @param cCode
 * @return Retrofit
 */
private fun createRetrofitBuilder(
    sNbr: String,
    cCode: String
): Retrofit {
    val builder = Retrofit.Builder().baseUrl(
        getServer(
            sNbr,
            cCode))
        .client(CertificateValidation.getUnsafeOkHttpClient())
        .addConverterFactory(SimpleXmlConverterFactory.create())

    return builder.build()
}

/**
 * Gets URL of request.
 * @param sNbr
 * @param cCode
 * @return server
 */
private fun getServer(sNbr: String, cCode: String): String {
    var server = Constants.URL_SERVICE
    server = server.replace(S_TAG,
        getStString(
            storeNbr
        )
    )
    server = server.replace(C_TAG, countryCode)
    return server
}

/**
 * 
 */
private fun getStString(sNbr: String): String {
    val decimalFormat = DecimalFormat(PATTERN)
    return decimalFormat.format(sNbr.toInt())
}

/**
 * @param serviceType
 * @return T
 */
fun <T> buildService(
    serviceType: Class<T>,
    sNbr: String,
    cCode: String
): T {
    return createRetrofitBuilder(
        sNbr,
        cCode
    ).create(serviceType)
}}

证书验证.kt

class CertificateValidation {
companion object {


    private const val TIMEOUT: Long = 5

    /**
     * Method that validates the SSL certificate sent from the Service.
     */
    fun getUnsafeOkHttpClient(): OkHttpClient {

        // Create a trust manager that does not validate certificate chains
        val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {
            @SuppressLint("TrustAllX509TrustManager")
            @Throws(CertificateException::class)
            override fun checkClientTrusted(
                chain: Array<java.security.cert.X509Certificate>,
                authType: String
            ) {
            }

            @SuppressLint("TrustAllX509TrustManager")
            @Throws(CertificateException::class)
            override fun checkServerTrusted(
                chain: Array<java.security.cert.X509Certificate>,
                authType: String
            ) {
            }

            override fun getAcceptedIssuers(): Array<java.security.cert.X509Certificate> {
                return arrayOf()
            }
        })

        // Install the all-trusting trust manager
        val sslContext = SSLContext.getInstance("SSL")
        sslContext.init(null, trustAllCerts, java.security.SecureRandom())
        // Create an ssl socket factory with our all-trusting manager
        val sslSocketFactory = sslContext.socketFactory

        val builder = OkHttpClient.Builder()
           .connectTimeout(TIMEOUT, TimeUnit.SECONDS)
            .writeTimeout(TIMEOUT, TimeUnit.SECONDS)
            .readTimeout(TIMEOUT, TimeUnit.SECONDS)
            .addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
            .connectionSpecs(
                listOf(
                    ConnectionSpec.COMPATIBLE_TLS,
                    ConnectionSpec.CLEARTEXT
                )
            )

        builder.sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager)

        return builder.build()

    }


}}

标签: androidkotlinretrofitretrofit2okhttp

解决方案


您应该阅读https://www.baeldung.com/okhttp-timeouts

您很可能希望使用 callTimeout 来控制整个呼叫的单个超时。通过连接重用,连接、读取和写入超时通常不会因为同一底层 IO 套接字上的其他请求而触发。

    OkHttpClient client = new OkHttpClient.Builder()
      .callTimeout(10, TimeUnit.SECONDS)
      .build();

此外,事件监听器通常会让您更​​好地理解请求拦截器https://square.github.io/okhttp/events/


推荐阅读