美文网首页
项目网络层存在问题的研究学习

项目网络层存在问题的研究学习

作者: fanxiansen | 来源:发表于2018-11-23 18:57 被阅读0次

背景

在对龙建项目的业务逻辑和代码逻辑梳理过程中,碰到了大大小小的问题一箩筐,网络层尤甚,造成了很严重的界面卡顿和数据重复操作等等问题;在此我们重点分析下面两个问题:

  • post和get请求乱用,造成的安全问题和代码阅读障碍,我们该怎么规避?
  • 大量请求循环并发开启,造成逻辑混乱和性能浪费,我们该怎么优化?

当我们捋顺这几个问题之后,会改善当前同步时大量并发请求造成的界面卡顿和崩溃问题。 同时对iOS的网络框架机制也会有更深层次的理解,方便我们更好地与服务端进行有效交互。

Method梳理

对于第一个问题我们有必要做一下拓展一下Method类型相关知识, 我们根据版本和参数的处理上进行分类。

  • 版本:
    1. HTTP1.0定义了三种请求方法: GET、POST 和 HEAD方法。
    2. HTTP1.1新增了五种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法。
    3. HTTP/2.0
  • 参数处理:
    1. "GET", @"HEAD", @"DELETE"。
    2. 其它

我们常用的get和post两种Method有什么区别?

1542970841047.jpg

众所周知,get和post最大的区别在于可见性:get的参数直接拼接在url之后,而post的参数则是放在httpbody里,安全性更高;因此,类似用户登录、注册、支付等安全性要求高的场景中,尽量使用post提交数据。

GET和POST还有一个重大区别

简单的说:

GET产生一个TCP数据包;POST产生两个TCP数据包。

长的说:

对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);
而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。

因为POST需要两步,时间上消耗的要多一点,看起来GET比POST更有效。因此Yahoo团队有推荐用GET替换POST来优化网站性能。
近来,越来越多的后端开发提供接口时,会使用第三方框架,而这些框架是默认同时支持GET和POST请求的,如果后台开发人员不注意,没有对接口做method限制的话:


1542970911178.jpg

会造成以上get和post错用的情况,引发不必要的麻烦,这种失误看起来就很低级。

因此:作为app开发者,应该严格按照pai文档执行,并随时review相关代码

并发请求乱像

并发请求听起来有点高大上,但实际很low,给大家看一张相关代码图:


1542971229179.jpg

是不是感觉哭笑不得,原来是这种情况啊。。。遍历数组-》发送请求
这种情况应该是不符合api设计规范的,正确的姿势应该是:参数以数组形式传递给服务端。
有人会问:数据量太大怎么办? 。。。 分页呀!

这时候既然已经入坑了,不能奢望后台哥们儿该逻辑跟你联调了,只能自力更生。
我们从网络请求本身分析得出了三个优化的可能性(仅供参考):

  • session单例
  • NSOperationQueue 多线程行不行
  • HTTPMaximumConnectionsPerHost:什么玩意?

session单例

单例我们太清楚了,那么session单例有什么好处嘞?

  • 性能优化 :首先我们来看一段官方解释:

     The session object keeps a strong reference to
      the delegate until your app exits or explicitly 
      invalidates the session. If you do not 
      invalidate the session, your app leaks memory
       until it exits
    

这句话对于英语过四级的我自然不是问题,给大家翻译一哈:
session对象保持对委托的强引用,直到应用程序退出或显式地使session无效。如果你没有使session失效,你的应用程序会泄露内存直到它退出。 来张图佐证一下:


1542971248764.jpg
重要事情看三遍:内存泄露!、内存泄露!、内存泄露!

既然`session`会造成内存泄露,那么当然要单例它,越少创建`session`对象,越少内存泄露。
  • 网络层协议

我们也都知道,HTTP协议是基于TCP协议的。所以在每次的HTTP请求之前,客户端和服务器端,都先需要经过TCP连接的三次握手,即每次请求之前,网络的数据都已经在客户端和服务器端之间来回了三次。那么,为了让我们的请求更快,避免每次都产生一个TCP三次握手,成了一个优化的选项。于是在HTTP 1.1中,出现了Connection: keep-alive这个选项。这个优化选项,可以使得客户端和服务器端复用一个TCP连接,从而减小每次的网络请求时间。

重点来了,现在都HTTP2.0了,看不到Connection: keep-alive这个选项就该落伍了, 现在的网络请求中这个选项默认是打开的。共享的Session将会复用TCP的连接,而每次都新建Session的操作将导致每次的网络请求都开启一个TCP的三次握手。

mRequestTest 没有共享session的10次并发请求所用总时间


1542971262675.jpg

shareSessionRequestTest共享session的10次并发请求所用总时间


1542971282324.jpg

对比总是残酷的,一个平均400ms, 一个平均90ms 。 还用考虑吗?

NSOperationQueue 行不行得通?

@property (readonly, retain) NSOperationQueue
     *delegateQueue;

我们知道NSURLSession使用NSOperationQueue管理task的,而默认的delegateQueue的maxConcurrentOperationCount是多少呢?

1542971406382.jpg
搞了半天是个串行队列,我们考虑,用多个线程同时开启task会有什么效果呢?
多线程同时开启task,我们需要一个参照点,来测试单线程和多线程的效果,最有效的点就是task开启时间的统计,那么task的开启时间从哪取出来呢? 1542971430471.jpg

从图中我们可以看到,Task开启时间对应的key:fetchStart, 下一步就是找出NSURLSessionTaskTransactionMetrics
我们可以从NSURLSessionTaskDelegate找到它

- (void)URLSession:(NSURLSession *)session 
  task:(NSURLSessionTask *)task didFinishCollecting
  Metrics:(NSURLSessionTaskMetrics *)metrics 
  API_AVAILABLE(macosx(10.12)
  , ios(10.0), watchos(3.0), tvos(10.0));

事实上,NSURLSessionTask是和NSURLSession共用一个代理的,当我们需要查看NSURLSessionTaskDelegate方法时,在NSURLSessionDelegate里实现该方法即可。

有了目标,设置:maxConcurrentOperationCount 1与5 进行对比参照 结果如下:

1542971703373.jpg

得出结论:task在队列中的开启操作,只是一瞬间的事儿,并不是我们想象中的等到NSURLReponse之后才进行下一个task operation,这也是为什么系统的shareSession和 AFN没有提供修改线程数的原因

所以:多线程结论不可行

  • HTTPMaximumConnectionsPerHost

      the maximum number of simultanous persistent 
      connections per host
    

每个主机的最大同时持久连接数,在iOS上最大链接数是4
当服务端有多个ip时,用得到它,但当我们尝试对其修改操作时,结果是失败, 我们猜想,该属性暂时是被弃置的。

参考

相关文章

  • 项目网络层存在问题的研究学习

    项目网络层存在问题的研究学习 ##背景 在对龙建项目的业务逻辑和代码逻辑梳理过程中,碰到了大大小小的问题一箩筐,网...

  • 项目网络层存在问题的研究学习

    背景 在对龙建项目的业务逻辑和代码逻辑梳理过程中,碰到了大大小小的问题一箩筐,网络层尤甚,造成了很严重的界面卡顿和...

  • 项目实践-网络层

    概述 最近上线了一个项目,姑且称为TestApp,开发过程中遇到了一些坑,决定做一点总结。网络层使用了目前比较流行...

  • 神经网络中的批量归一化Batch Normalization(B

    0.概述 深层神经网络存在的问题(从当前层的输入的分布来分析):在深层神经网络中,中间层的输入是上一层神经网络的输...

  • 浅谈Swift网络编程最佳实践

    序言 以Swift为iOS开发入门语言的新手,在网络编程时往往容易存在以下两个问题: 没有网络层,网络请求的代码散...

  • Kubernetes探索学习系列004----深入Kuberne

    深入研究学习Pod 首先需要认识到Pod才是Kubernetes项目中最小的编排单位原子单位,凡是涉及到调度,网络...

  • Resnet(残差网络)视频课学习笔记

    并不是网络层数越多,网络的效果就越好。因为存在梯度弥散问题 假设Plain Net 前6层数已经达到最优,当前7,...

  • 关于网络层的设计(一)——和业务层的对接

    前言 关于网络层的设计,最主要的是和业务层的对接问题。网络层设计得好,可以让业务层开发事半功倍;反之,若网络层设计...

  • Flannel网络原理

    overlay网络简介 覆盖网络就是应用层网络,它是面向应用层的,不考虑或很少考虑网络层,物理层的问题。 详细说来...

  • Flannel网络原理

    overlay网络简介 覆盖网络就是应用层网络,它是面向应用层的,不考虑或很少考虑网络层,物理层的问题。 详细说来...

网友评论

      本文标题:项目网络层存在问题的研究学习

      本文链接:https://www.haomeiwen.com/subject/ijksqqtx.html