iOS网络监控的实现- for APM System
| Name | Explain |
|---|---|
| NSURLConnection | 已经废弃,使用简单 |
| NSURLSession | iOS7.0+,很强大 |
| CFNetwork | NSURL的底层 ,纯C实现 |
iOS网络库层级结构如下图:
当前iOS 网络库由四层组成:底层的 BSD Sockets和SecureTransport; 基础的CFNetwork, NSURLSession, NSURLConnection 和 WebView 是调用CFNetwork用Objective-C实现的; 应用层的网络库AFNetworking是基于NSURLSession and NSURLConnection实现的。
目前,行业使用网络监控的方式一共两种: 一种是通过NSURLProtocol 监控, 另一种是通过Hook 监控. 这里有几种方式监控网络请求,各有利弊。 1,NSURLProtocol 监控app网络请求 这种方式网上博客介绍的比较多,并且ios10以后有一个特定的代理回调
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));
这种方案有俩缺陷:
- 对webview是不起作用的,有个文章说的很清楚,需要用苹果私有api
- 会导致ketp-alive为NO,对网络性能有影响
- DNS 开始和解析时间获取不到
2,ios有两种hook技术, 一个是NSProxy,另一个是 method swizzling (isa swizzling) 这两种方式可以参考:programmer.group/teach-you-t…
终极解决方案
AFN已经通过 method swizzling 方式做了网络收集对外接口,有通知也有回调,如果工程已经使用了AFN作为网络库,使用NSURLProtocol方式完全画蛇添足,反而会导致性能问题. 在自如客中,对AFN中介封装的类是ZRNetWorkAgent,里面用到了AFHTTPSessionManager,可以直接从这个对象中拿到想要的数据和事件,从而完整网络收集的需求。