iOS9 ATS HTTP/2 NSURLSession

本文主要是看了

  • WWDC 2015 - Session 711 - Networking with NSURLSession
  • WWDC 2016 - Session 711 - NSURLSession: New Features and Best Practices

做出的翻译和总结, 文字/视频链接如下 :

  • wwdc2015/711 : Networking with NSURLSession
    • 文字
    • 视频
  • wwdc2016/711 : NSURLSession: New Features and Best Practices
    • 文字
    • 视频

App Transfer Security


iOS9新特性. 核心是防止用户的个人隐私数据被意外泄漏. 加强默认Configuration的安全性.

HTTP

以前HTTP请求是明文传输(clearText)的, 别人拦截请求之后就能获取所有信息.

HTTPS

HTTPS通过在TCP于HTTP层之间加入一层SSL/TLS层, 能做到 :

  • Encryption : 信息加密传输, 别人看不懂
  • Integrity : 保证数据完整性, 即第三方篡改后能检测出来
  • Authentication : 身份验证, 防止第三方伪造通信

HTTPS in iOS

苹果希望所有所有请求都使用HTTPS来加强安全性, 但是也有以下几种例外(以下全部可以在info.plist文件中配置) :

  • 全局HTTPS请求, 但是某个域名采用HTTP请求
    NSAppTransportSecurity
    NSAllowsArbitraryLoads = NO // 默认为NO, 这一行不要也行
    NSExceptionDomains
    "media.example.com"
    NSExceptionAllowsInsecureHTTPLoads = YES
  • 全局HTTP请求, 但是某个域名采用HTTPS请求
    NSAppTransportSecurity
    NSAllowsArbitraryLoads = YES
    NSExceptionDomains
    "secure.example.com"
    NSExceptionAllowsInsecureHTTPLoads = NO
  • 全局HTTP/HTTPS(任意)请求
    NSAppTransportSecurity
    NSAllowsArbitraryLoads = YES
iOS9 ATS HTTP/2 NSURLSession_第1张图片

使用NSAllowsArbitraryLoads可以检测app中加载失败是不是因为ATS的原因.

CFNetwork中用于网络诊断的环境变量CFNETWORK_DIAGNOStICS = 1 : 所有加载失败的URL都能被确定是URL错误还是底层TLS错误. 这样能进一步排查错误.

下面为ATS新增的属性

  • NSAllowsArbitraryLoadsInWebContent : UIWebView会无视app的其他协议, 加载HTTP的内容. 仅限于UIWebVie对象, 其他对象还是对遵循安全协议.

  • NSRequiresCertificateTransparency : 保证证书的合法性.

NSURLSession新特性


NSURLSession将全面支持HTTP/2 !

iOS9 ATS HTTP/2 NSURLSession_第2张图片

为什么需要HTTP/2

由于HTTP/1.1存在许多问题 :

  • 单路连接 请求低效

    • 每个TCP连接只能对应一个HTTP请求, 每个HTTP请求只请求一个资源, 浏览器只能通过建立多个TCP连接来解决, 但是由于文本协议开销, 缺乏头压缩, 意味着对客户端和服务器的要求更高且性能更低下
    iOS9 ATS HTTP/2 NSURLSession_第3张图片
    HTTP/1.1 without pipelining
    • 使用HTTP管道, 但是HTTP管道并不适用于所有的服务器或网络, 实际上在很多浏览器上是被禁止的. 事实上效率并不高.
    iOS9 ATS HTTP/2 NSURLSession_第4张图片
    HTTP/1.1 with pipelining
  • HTTP只允许由客户端主动发起请求
    • 意味着缺少预加载的功能
  • HTTP头冗余
    • 每次发送HTTP请求都有一堆重复的header value

了解HTTP/2

iOS9 ATS HTTP/2 NSURLSession_第5张图片
between HTTP/1.1 and HTTP/2

HTTP/2 有什么改进 :

  • 一个TCP连接能发起多个HTTP请求
  • 实现完全多路复用, 意味着一个新的请求不用等到上一个请求得到响应之后再发出
  • 有请求优先级, 所以能把重要的资源优先提供给拥有更高权限的客户端.
  • 使用二进制分帧, 使得数据的处理和解析速度更快.
  • 使用HPACK头压缩技术
    • 使用一个静态表和一个动态表
    • 静态表包含最常用的HTTP信息头, 并且不可修改
    • 包含在静态表中的信息头可以动态添加到动态表中, 动态表中的信息头通过指针引用静态表中的信息
  • HTTP/2自动支持HTTPS, 意味着HTTP/2是安全的
  • 支持服务器自推送

HTTP/2 多路复用

Q : HTTP/2多路复用是如何队首阻塞的问题的?

A : 在HTTP/1.1的时候曾试过采用HTTP pipelining (HTTP 管道/流水线 技术)能实现同一TCP连接中不用等待旧请求的响应就可以发送新请求. 但是HTTP pipelining有个致命的缺点 : HTTP响应仍然是按照请求的顺序依次收到.

HTTP/2 多路复用+请求优先级, 发送的时候还是依次发送请求, 但是与此同时我们同时得到了回复, 同时, 更高优先级的请求我们得到以及发送给客户端的速度更快, 如下图所示 :

iOS9 ATS HTTP/2 NSURLSession_第6张图片
HTTP/2 Multiplexing

服务器自推送

在HTTP/1.1时代, 我们没有服务器自推送, 只能发一个请求, 得到响应之后再发第二个请求... 延迟可想而知 :

iOS9 ATS HTTP/2 NSURLSession_第7张图片
HTTP/1.1 without Server Push

而在HTTP/2时代, 我们有了服务器自推送, 服务器会把相关联的数据全部push给我们 :

iOS9 ATS HTTP/2 NSURLSession_第8张图片
HTTP/2 with Server Push

性能马上强了一大截, 我们再也不用像以前那样苦苦等待了.

并且这功能已经内嵌在NSURLSession中, 我们不需要写任何一行代码来支持其实现.

iOS中适配HTTP/2

NSURLSession已经自动支持HTTP/2, 客户端不需要额外写任何代码. 只需要一台支持HTTP/2通信的服务器即可. 哎呀, 要是没有怎么办, 也没关系, 看下面 :

  • 服务器支持HTTP/2
    • NSURLSession自动使用HTTP/2进行通信
  • 服务器不支持HTTP/2
    • NSURLSession自动使用HTTP/1.1或其他更优的协议

我们一句代码, 判断都不用写, 省事又省心.

SPDY

这里说句题外话, 虽然SPDY并不在该Session中提及, 但是与HTTP/2有异曲同工之处, SPDY在之前被认为是未来的HTTP/2, 所以这里说一下.

SPDY是Google开发的基于TCP的应用层协议, 通过头部压缩, 多路复用和优先级来缩短网页的加载时间和提高安全性. 可以说是HTTP/1.1的一个优化版.

  • 多路复用, 请求优化
  • 支持服务器推送技术
  • SPDY压缩了HTTP头
  • 强制使用SSL传输协议

更多有关SPDY的详情请见这里


惊 ! iOS9开始苹果弃用NSURLConnection, 不再维护NSURLConnection, 所有有关Networking的新API只会在NSURLSession上更新.

iOS9 ATS HTTP/2 NSURLSession_第9张图片
NSURLSession replace NSURLConnection

NSURLSession的新功能


cookie 共享

增加sessionCookieGroup以实现app与其扩展(例如通知中心等等)之间cookie的共享.

let ident = "group.mycompany.mygroupname" 
let cookieStorage = NSHTTPCookieStorage.sharedCookieStorageForGroupContainerIdentifier(
    identifier: ident)
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
config.HTTPCookieStorage = cookieStorage
let session = NSURLSession(configuration: config)

NSURLSessionStreamTask

以前我们使用NSInputStream/NSOutputStream来进行一些非HTTP的连接, 例如利用TCP连接一台远程的服务器等等, 现在我们有了NSURLSessionStreamTask让我们更简单地实现以上功能.

NSURLSessionStreamTask的特性 :

  • 更轻松地使用TCP进行通信
  • 替代NSInputStream/NSOutputStream, 提供更优的API
    • 异步读写API
    • 内置强大的支持功能, 能自动通过HTTP代理, 连接一个远程服务器.
    • 轻松转换成NSStream

NSURLSessionTaskMetrics

对发送请求/DNS查询/TLS握手/请求响应等各种环节时间上的统计. 更易于我们检测, 分析我们的请求缓慢到底是发生在哪个环节, 并对此进行优化提升我们APP的性能.

下面开始介绍NSURLSessionTaskMetrics的属性

Property

  • taskInterval : 任务从开始到结束总共用的时间

  • redirectCount : 任务重定向的次数

  • transactionMetrics : 在任务执行期间产生的每个请求/响应事务, 它是一个装着许多NSURLSessionTaskTransactionMetrics对象的数组

NSURLSessionTaskTransactionMetrics

property

  • request and response : 请求和响应

  • networkProtocolName : 网络协议名称

    • http/1.1
    • http/2
    • spdy/3, spdy/3.1
  • isProxyConnection : 是否连接代理服务器

  • isReusedConnection : 是否允许重连

  • resourceFetchType : 描述本次加载的类型, 枚举类型

    • networkLoad : 网络加载
    • localCache : 本地缓存
    • serverPush : 服务器自推送
  • Connection Establishment and Transmission

    transmissions
    • fetchStart : 开始发起请求.

    • domainLookupStart : 发送DNS请求, 域名->IP地址

    • domainLookupEnd : DNS请求完成, 拿到IP地址

    • connectStart : 与远程服务器开始建立TCP连接

      • secureConnectionStart : HTTPS的TLS握手开始
      • secureConnectionEnd : HTTPS的TLS握手完成
    • connectEnd : 与服务器建立起了TCP连接

    • requestStart : 开始传输HTTP header第一个字节的时间(远程/缓存)

    • requestEnd : HTTP最后一个字节传输完成的时间(远程/缓存)

    • responseStart : 从服务器得到数据(远程/缓存)

    • responseEnd : 从服务器接受完最后一个字节的数据(远程/缓存)

另外, 需要注意的是, 如果请求命中了cache, 上述很多值会为nil.

API

NSURLSessionTaskDelegate代理中新增一个方法- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics, 当收集完成的时候就会调用该方法.

我们只需要实现代理的这个方法就能在这里做统计, 输出等等操作.

Something else

苹果不再支持RC4加密.


以上图片均来自官方WWDC中的PDF.

参考资料 :
HTTP/2
NSURLSession
NSURLSessionTaskMetrics

你可能感兴趣的:(iOS9 ATS HTTP/2 NSURLSession)