1. 背景
2. 介绍
2.1 为什么okhttp性能好
- 支持http2,对一台机器的所有请求共享同一个socket
- 内置连接池,支持连接复用,减少延迟(连接池复用)
- 支持透明的gzip压缩响应体(请求头Content-Encoding:gzip,body有内容)
- 通过缓存避免重复的请求(缓存)
- 请求失败时自动重试主机的其他ip,自动重定向(重试)
2.2 okhttp工作流程
3. 源码
3.1 socket连接池复用
okhttp3.internal.connection.RealConnectionPool#transmitterAcquirePooledConnection。这是入口okhttp3.internal.connection.Transmitter#newExchange$okhttp
fun transmitterAcquirePooledConnection(
address: Address,
transmitter: Transmitter,
routes: List<Route>?,
requireMultiplexed: Boolean
): Boolean {
assert(Thread.holdsLock(this))
for (connection in connections) {
if (requireMultiplexed && !connection.isMultiplexed) continue
if (!connection.isEligible(address, routes)) continue
// 复用连接
transmitter.acquireConnectionNoEvents(connection)
return true
}
return false
}
3.2 支持透明的gzip压缩响应体(请求头Content-Encoding:gzip,body有内容)
okhttp源码中执行请求时,会进行synchronized限制(对象锁)。不允许重复请求。
override fun execute(): Response {
synchronized(this) {
check(!executed) { "Already Executed" }
executed = true
}
transmitter.timeoutEnter()
transmitter.callStart()
try {
client.dispatcher.executed(this)
return getResponseWithInterceptorChain()
} finally {
client.dispatcher.finished(this)
}
}
4. 实战
4.1 如何使用OkhttpClient
public static void main(String[] args) throws IOException {
String url = "http://wwww.baidu.com";
OkHttpClient okHttpClient = new OkHttpClient();
final Request request = new Request.Builder()
.url(url)
.get()//默认就是GET请求,可以不写
.build();
Call call = okHttpClient.newCall(request);
// 异步
// call.enqueue(new Callback() {
// @Override
// public void onFailure(Call call, IOException e) {
// System.out.println("onFailure");
// }
//
// @Override
// public void onResponse(Call call, Response response) throws IOException {
// System.out.println("onResponse");
// }
// });
// 同步
Response execute = call.execute();
System.out.println(execute);
}
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.2.2</version>
</dependency>
5. FAQ
5.1 弱网
按照移动的特性来说,一般应用低于2G速率的都属于弱网,也可以将3G划分为弱网。除此之外,弱信号的Wifi通常也会被纳入到弱网测试场景中。
5.2 Thread.holdsLock()
检测一个线程是否有对象锁
5.3 同步方法调用时似乎只看到执行前入队,执行后出队
6. 参考资料
【扔掉okhttp、httpClient,来试试这款轻量级HTTP客户端神器?】