Android妙用SPDY协议提高移动端网络请求性能

Android妙用SPDY协议提高移动端网络请求性能

2023年6月28日发(作者:)

Android妙⽤SPDY协议提⾼移动端⽹络请求性能 本⽂旨在提出⼀种提⾼移动端⽹络性能的可⾏⽅案。我们知道⽬前移动端使⽤的⽹络请求协议基本上都是http。⽤的最多的是http/1.1,http/2.0正在逐渐壮⼤,实际上http/2.0是基于google提出的SPDY协议改进⽽来。废话不多说,马上进⼊正题。 关于SPDY协议的详细介绍,请参看 OkHttp完全解析(七)SPDY协议详细介绍 。

关于OkHttp的使⽤及源码分析⽹上相关的资料很多,推荐OkHttp完全解析(⼋)源码解析⼀ 系列⽂章。写的很不错。

从速度上来讲,Http/1.1⽤明⽂传输,⽆需加密验证,速度快;SPDY加⼊了SSL加密握⼿,但是SPDY协议允许⼀个TCP连接复⽤,可以⼀个域名只提供⼀个TCP连接即可完成通信,虽然由于TCP连接复⽤,但是SSL加密握⼿协商过程⼜耗费了⼀定的时间;Http/2.0是Http的加密版本,也是SPDY的升级版本,如果追求⾼安全性,可以选⽤Http/2.0,速度上Http/2.0⽐Http/1.1稍慢。实验证明单纯的将Http/1.1升级到SPDY,速度提升并不明显,原因在于SSL加密层的添加,⼀定程度上拖慢了SPDY协议的效率。本⽂在基于OkHttp开源库的基础上,使⽤SPDY协议,但是强制忽略了SSL握⼿验证过程,强制使⽤SPDY/3.1协议,这样就将SPDY的速度优势发挥出来了。Okhttp的源码量⽐较⼤,逻辑⽐较复杂,我费了不少时间,看懂了⼤致的思路。请在阅读本⽂之前阅读前⾯的OkHttp源码系列⽂章。

针对某个公司的产品,服务器端可以针对域名进⾏配置SPDY协议的使⽤。针对⾃家产品完全可以免去SSL协商过程,直接默认使⽤SPDY协议。关于服务器怎么配置,在此不过多赘述,⾃⾏查阅相关⽂章。

客户端具体实现过程:

下载okHttp源码并进⾏修改,只需修改⼀处即可完成。直接上代码:

中的connect()函数: //当新建连接或者可⽤连接⽆效的时候进⼊此函数 if (connected) throw new IllegalStateException("already connected"); SocketConnector socketConnector = new SocketConnector(this, pool); tedSocket connectedSocket; if (SocketFactory() != null) { // communication } else { // communication. if (!ns(EXT)) { throw new RouteException(new UnknownServiceException( "CLEARTEXT communication not supported: " + connectionSpecs)); } connectedSocket = tCleartext(connectTimeout, readTimeout, route); } socket = ; handshake = ake; //此处已完成协议的协商,protocol变量的值则决定了下⾯所⾛的协议。 protocol = otocol == null ? _1_1 : otocol; /***********加⼊代码**************/ String hostName = l().host(); if ("".equals(hostName) { protocol = _3; } /***********加⼊的代码结束**************/ try { if (protocol == _3 || protocol == _2) { imeout(0); // SPDY timeouts are set per-stream. spdyConnection = new r(t, true, socket).protocol(protocol).build(); nnectionPreface(); } else { httpConnection = new HttpConnection(pool, this, socket); } } catch (IOException e) { throw new RouteException(e); } connected = true; } void connect(int connectTimeout, int readTimeout, int writeTimeout,Request request, List connectionSpecs,boolean connectionRetryEn connectedSocket = tTls(connectTimeout, readTimeout, writeTimeout, request, route, connectionSpecs, connectionRetryEnable由于时间有限,加上第⼀次正式写博客,很多地⽅语法⽤的不是太好,凑合看哈,connect()函数中加⼊的代码: String hostName = l().host(); if ("".equals(hostName) { protocol = _3; } 只是通过很简单的逻辑即可实现,代表的是服务器端⽀持SPDY的域名,此段代码的含义即为强制客户端针对域名选⽤SPDY协议。值得注意的是,在OkHttp框架中,若为https则默认会进⾏handshake过程,此时相当于会进⾏TLS握⼿过程,此时,这样添加实际上⽆法提⾼效率,且既然⽤了https加密协议,那TLS握⼿肯定是不能去掉的,否则https变的毫⽆意义。

具体的实现则需要追踪源码。这⾥给出简单的说明。中的connectAndSetOwner函数是每次请求都会进来的函数,注意此处会进⾏判断,当第⼀次建⽴连接时,isConnected返回false,此时会进⼊connect函数,建⽴连接,选择协议,完成连接后,会进⾏isSpdy判断,如果是Spdy协议,那么会将此connnection放⼊连接池中进⾏共享,下次相同域名下的请求到来时,isConnected判断就会为true,则不需要进⾏重复创建连接,实现了连接的共享。⽽若是http/1.1,⼀般不会进⾏连接共享,每次都需要重建连接,效率较低。 void connectAndSetOwner(OkHttpClient client, Object owner, Request request)throws RouteException { setOwner(owner); if (!isConnected()) { List connectionSpecs = nectionSpecs(); connect(nectTimeout(), dTimeout(), teTimeout(), request, connectionSpecs, ryOnConnectionFailure()); if (isSpdy()) { nectionPool().share(this); } atabase().connected(getRoute()); } setTimeouts(dTimeout(), teTimeout()); }下⾯给出⼀个简单的代码进⾏验证:public class MainActivity extends Activity { private Button myButton; private String[] urls = { "/lottery_?mobileType=android&ver=4.13&channel=netease&apiVer=1.1&apiLevel=19", "/clientHall_?mobileType=android&ver=4.13&channel=netease&apiVer=1.1&apiLevel=19", "/?mobileType=android&ver=4.13&channel=netease&apiVer=1.1&apiLevel=19", "/?mobileType=android&ver=4.13&channel=netease&apiVer=1.1&apiLevel=19" }; @Override public void onCreate(Bundle savedInstanceState) { te(savedInstanceState); setContentView(ty_main); myButton = (Button) findViewById(); lickListener(new kListener() { @Override public void onClick(View v) { new Thread() { @Override public void run() { long start = tTimeMillis(); for (int i = 0; i < * 4; i++) { OkHttpClient okHttpClient = new OkHttpClient(); Request request = new r().url( urls[i % ]).build(); try { Response okHttpResponse = l( request).execute(); Log.i("SpdyTest", "i:" + i + " protocol:" + ol().name() + "code:" + ()); } catch (IOException e) { tackTrace(); } } long end = tTimeMillis(); Log.i("aTest", "total time: " + (end - start) + "ms"); } }.start(); } }); }} "/clientCommonConfig_?mobileType=android&ver=4.13&channel=netease&apiVer=1.1&apiLevel=代码很简单,利⽤已配置好服务器端的url进⾏测试,每进⾏20次请求, 进⾏⼀次时间计算。http协议:Spdy协议: 测试环境为家⾥wifi信号,⼏乎同时进⾏测试,也切换过其他⽹络,同等环境下,去掉TLS握⼿的SPDY协议要⽐Http快⼤概40%。

当然了对于⼤多数应⽤来说,⼀般情况下不会产⽣明显的卡顿,但是效果总不怕好嘛,这⾥只给⼤家提供⼀个⽐较可⾏的思路⽽已。

最近在家⾥闲来⽆事,在看okhttp的源码,确实学到了很多东西,本来想写⼏篇源码分析的⽂章,发现写起来真是繁琐,且⽹上有很多博客解释的很清晰,这⾥就不做重复性⼯作了。

本⽂提供的思路⼏乎只⽤⼀⾏代码就能实现,不过很遗憾,okhttp框架并不能直接设置想要使⽤的协议,没有暴露接⼝给我们,所以我们只能把源码下载下来,在进⾏打jar包啦。

这是我第⼀次写博客,很多地⽅没注意到,看到的请见谅,关于OkHttp这个开源库,我强烈推荐,亲⾃实践了它失败重连等功能,有任何相关问题,欢迎留⾔交流。

发布者:admin,转转请注明出处:http://www.yc00.com/news/1687954699a60551.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信