概述
我正在使用以下版本的 Okhttp com.squareup.okhttp3:okhttp:4.9.3
当一笔事务发生时,我需要一次性执行多个 HttpRequest。
我采用了 Singleton OkHttpClient 来避免每次创建新客户端,因此我为所有 http 请求重用相同的 http 客户端
场景
当我使用同一个 Singleton OkHttpClient 并行执行多个 http 请求时,第一个 http 请求会发生 SSL 握手,而其他 http 请求不会发生 SSL 握手。
问题陈述
如果 2 个 http 请求之间的延迟超过 30 秒,则每次都会发生 SSL 握手..我想解决这个问题。 SSL 握手应该仅在第一个 http 请求时发生。我现在可能会发送一个http请求,然后需要一些时间,然后发送另一个http请求。我不希望第二个 httprequest 发生 SSL 握手。现在,如果延迟 30 秒,就会发生这种情况。如果我执行多个 http 请求而没有任何时间延迟,那么它工作正常。
OkttpClient 中是否有任何设置可以增加 2 个 http 请求之间的空闲时间,以便每次都不会发生 SSL 握手。
公共类 OkHttpSingleton {
private static OkHttpSingleton singletonInstance;
// No need to be static; OkHttpSingleton is unique so is this.
private OkHttpClient httpClient;
int timeoutConnect = 45000;
int timeoutSocket = 45000;
// Private so that this cannot be instantiated.
private OkHttpSingleton() {
try {
String tlsVersion = "TLSv1.2";
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
tlsVersion = "TLSv1";
}
SSLContext sslContext = SSLContext.getInstance(tlsVersion);
sslContext.init(null, null, null);
SSLSocketFactory socketFactory = sslContext.getSocketFactory();
httpClient = new OkHttpClient.Builder()
.retryOnConnectionFailure(true)
.connectTimeout(timeoutConnect, TimeUnit.SECONDS)
.writeTimeout(timeoutSocket, TimeUnit.SECONDS)
.readTimeout(timeoutSocket, TimeUnit.SECONDS)
.sslSocketFactory(socketFactory, new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
})
.build();
} catch (Exception e) {
e.printStackTrace();
}
}
public static OkHttpSingleton getInstance() {
if (singletonInstance == null) {
singletonInstance = new OkHttpSingleton();
}
return singletonInstance;
}
// In case you just need the unique OkHttpClient instance.
public OkHttpClient getClient() {
return httpClient;
}
public void closeConnections() {
httpClient.dispatcher().cancelAll();
}
}
请在下面找到 WIRESHARK 的屏幕截图。我想避免 Client Hello 和 HandShake
请查找服务器在 30 秒不活动后发送的 RST ACK
尝试 keepAliveDuration 例如:
import okhttp3.OkHttpClient;
public class MyHttpClient {
private static OkHttpClient client;
public static OkHttpClient getClient() {
if (client == null) {
client = new OkHttpClient.Builder()
.keepAliveDuration(60, TimeUnit.SECONDS)
.build();
}
return client;
}
}
在新版本中使用它:
OkHttpClient client = new OkHttpClient.Builder()
.connectionPool(new ConnectionPool(5, 30, TimeUnit.SECONDS))
.build();
您可以影响连接的空闲时间,从而间接影响 TLS 握手超时。您可以通过配置连接池的驱逐策略和保持活动持续时间来完成此操作。
// Increase the idle connection timeout to 10 minutes
ConnectionPool connectionPool = new ConnectionPool(
/* maxIdleConnections */ 5,
/* keepAliveDuration */ 10, TimeUnit.MINUTES
);
OkHttpClient client = new OkHttpClient.Builder()
.connectionPool(connectionPool)
.build();
在上面的代码中,
keepAliveDuration
构造函数中的ConnectionPool
参数指定连接在考虑驱逐和清理之前可以保持空闲状态的时间。通过增加此值,您可以间接影响 TLS 握手的超时。
希望有帮助!