Android中OkHttp复用连接避免重复SSL握手的配置方法
问题描述
概述
使用的OkHttp版本为com.squareup.okhttp3:okhttp:4.9.3,交易发生时需一次性执行多个HttpRequest,采用单例OkHttpClient复用客户端,避免重复创建。
场景
同一单例OkHttpClient并行执行多个HTTP请求时,仅第一个请求触发SSL握手,其余请求不会。
问题核心
若两个请求间隔超过30秒,每次都会触发SSL握手。希望仅第一次请求执行SSL握手,即使间隔一段时间后再发请求,也不触发握手。当前无延迟并行请求正常,间隔30秒以上则触发。询问是否可通过OkHttpClient设置增加请求间的空闲超时,避免重复SSL握手。
现有代码
public class 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(); } }
相关截图
- 需避免的SSL握手(Client Hello阶段):

- 服务器30秒无活动后发送的RST ACK:

解决方案
OkHttp默认连接池的空闲连接超时时间为30秒,这正是你遇到问题的原因。要解决这个问题,需要通过ConnectionPool配置延长空闲连接的存活时间,具体操作如下:
配置自定义连接池
在OkHttpClient构建时,添加connectionPool()配置,设置更长的空闲超时时间(建议大于服务器端的连接超时时间,比如5分钟),同时可根据业务需求调整最大空闲连接数。修改现有代码
在OkHttpSingleton构造函数中,为OkHttpClient.Builder添加自定义ConnectionPool:
// 添加到Builder配置前 ConnectionPool connectionPool = new ConnectionPool( 5, // 最大空闲连接数,可根据并发量调整 5, // 空闲连接存活时间,单位:分钟 TimeUnit.MINUTES); httpClient = new OkHttpClient.Builder() // 保留原有所有配置 .connectionPool(connectionPool) // 新增连接池配置 .build();
关键说明
- 客户端设置的空闲超时时间必须大于等于服务器端的连接超时时间,否则服务器主动断开连接后,客户端无法复用连接。从截图看服务器30秒无活动就发送RST ACK,所以客户端空闲时间建议设为1分钟以上。
- 最大空闲连接数根据实际并发请求量调整,避免过多空闲连接占用资源。
额外注意
如果调整客户端连接池后仍出现重复握手,需要确认服务器端是否有强制的连接超时策略,此时需与服务器运维人员沟通,延长服务器端的连接空闲超时时间,才能彻底解决问题。
内容的提问来源于stack exchange,提问作者KK_07k11A0585
相关产品推荐
相关产品推荐

