您的位置:首页 > 理论基础 > 计算机网络

OkHttp的性能指标拦截(首包,剩余包时间,resultCode)

2016-03-17 11:58 549 查看
最近,部门接到新的任务就是做httpClient,URLConnection,OKhttpClient,webview的网络性能指标进行监控,当然这些指标最准确的方法还是使用jni在底层建链与dns解析,发包等函数进行hook,再进行指标采集。但领导要求我们在java层尝试一下,今天主要记录下,我对OkHttp网络指标采集的调研结果和尝试。

OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).get().build();
Response response = client.newCall(request).execute();


对于httpClient我们通尝都是替换execute()方法,然后对httpClient的对像进行更改配置自己的拦截功能,查看源码,发现OkHttpClient相对不同的是execute方法并不在OkHttpClient,而是newCall方法中new 了一个call实例。

public Call newCall(Request request) {
return new Call(this, request);
}

//Call构造器中,对OkHttpClient进行了深拷备,所以对newCall之后的OkHttpClient配置都将无法生效,所以我们必须在newCall之前将拦截代码进行塞入
Call(OkHttpClient client, Request originalRequest) {
// Copy the client. Otherwise changes (socket factory, redirect policy,
// etc.) may incorrectly be reflected in the request when it is
// executed.
this.client = client.copyWithDefaults();
this.originalRequest = originalRequest;
}


发现Call类并不是final的,所以决定对其继承,因为 Call的构造器是protected的,所以子类需要在相同的包名下,而上层的拦截于是这样实现的

public static Call newCall(OkHttpClient okHttpClient, Request paramRequest)
{
return new MyCall(okHttpClient, paramRequest, okHttpClient.newCall(paramRequest));
}


MyCall类的中的public,protected方法进行重写(execute(),enqueue(Callback paramCallback),cancel(),isCanceled()),实现使用传入的call进行调用,重写getResponse方法

@Override
Response getResponse(Request request, boolean forWebSocket) throws IOException {
RequestBody body = request.body();
if (body != null) {
Request.Builder requestBuilder = request.newBuilder();

MediaType contentType = body.contentType();
if (contentType != null) {
requestBuilder.header("Content-Type", contentType.toString());
}

long contentLength = body.contentLength();
if (contentLength != -1) {
requestBuilder.header("Content-Length", Long.toString(contentLength));
requestBuilder.removeHeader("Transfer-Encoding");
} else {
requestBuilder.header("Transfer-Encoding", "chunked");
requestBuilder.removeHeader("Content-Length");
}

request = requestBuilder.build();
}

// Create the initial HTTP engine. Retries and redirects need new engine
// for each attempt.
engine = new HttpEngine(client, request, false, false, forWebSocket, null, null, null, null);

int followUpCount = 0;
while (true) {
if (canceled) {
engine.releaseConnection();
throw new IOException("Canceled");
}

try {
Timer requestTime = ThreadLocalMetricsRecorder.getInstance().getRequestTimer();
Timer responseTime = ThreadLocalMetricsRecorder.getInstance().getResponseTimer();
requestTime.start();
engine.sendRequest();
requestTime.stop();
responseTime.start();
engine.readResponse();
responseTime.stop();
} catch (RequestException e) {
// The attempt to interpret the request failed. Give up.
throw e.getCause();
} catch (RouteException e) {
// The attempt to connect via a route failed. The request will
// not have been sent.
HttpEngine retryEngine = engine.recover(e);
if (retryEngine != null) {
engine = retryEngine;
continue;
}
// Give up; recovery is not possible.
throw e.getLastConnectException();
} catch (IOException e) {
// An attempt to communicate with a server failed. The request
// may have been sent.
HttpEngine retryEngine = engine.recover(e, null);
if (retryEngine != null) {
engine = retryEngine;
continue;
}

// Give up; recovery is not possible.
throw e;
}

Response response = engine.getResponse();
Request followUp = engine.followUpRequest();

if (followUp == null) {
if (!forWebSocket) {
engine.releaseConnection();
}
return response;
}

if (++followUpCount > MAX_FOLLOW_UPS) {
throw new ProtocolException("Too many follow-up requests: " + followUpCount);
}

if (!engine.sameConnection(followUp.url())) {
engine.releaseConnection();
}

Connection connection = engine.close();
request = followUp;
engine = new HttpEngine(client, request, false, false, forWebSocket, connection, null, null, response);
}
}


算出首包,剩余包时间和拦截重定向,通过重写enqueue方法,获取清求的错误与response

@Override
public void enqueue(Callback paramCallback)
{
//          a();
this.e.enqueue(new Callback() {

@Override
public void onResponse(Response response) throws IOException {

}

@Override
public void onFailure(Request request, IOException e) {

}
});
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: