HTTP 流量工具它包含在Xcode的instruments的Network模版中,可以帮助我们理解API和请求生命周期的关系
It just Work
- 它适用于所有苹果设备
- 整个穿过URL 加载系统的流量都会曝光、甚至是HTTP/3或者是VPN
- 以framework级别集成在系统中
○ 过程以属性方式表达
○ 磁盘缓存请求
○ 揭示网络错误
○ 熟悉的高层API
工具介绍
导航是围绕轨迹堆栈构建的
红色区域:HTTP流量工具在最顶层,展示任意时间APP中有多少任务,非常适合在应用程序生命周期中检测HTTP流量活动增加的点。
绿色区域:显示了按进程划分的活动。 不仅有所有可调试的过程产生的流量,还有由它们初始化的后台流量
每个进程下面都包含它使用的所有URLSession。这些对应于在代码中创建的URLSession对象。
橙色区域:是每个session会话和它们的独立任务,为了更好的将代码和可视化结合起来,允许我们查看每个独立的任务间隔,可以在代码中将session实例命名,可以通过如下的代码来实现
let session = URLSession(configuration: .default)
session.sessionDescription = "Main session”
蓝色区域:是按照域名分类的任务信息,这里会展示任务的状态,就是一些task 从选中的域名在加载数据
工具使用分析
1. 专注于Task任务描述
在这里我们只需点击我们想要的任务,特别是如果我们已经设置了描述名称,我们可以点击它。
Task 是由一个或者多个事务组成的 每个事务是由 一对HTTP请求和响应组成的
任务API与UI对应:
let task = session.dataTask(with: url) {
2 /* handle result */ // 👈🏻 Complete event triggers here
3}
4
5task.resume() // 👈🏻 Resume event triggers here
Task 是代表了你的代码如何与URL加载系统API进行交互 当我们创建一个task 并调用它的resume方法,这个task 间隔就开始了而当你的completion Block被调用的时候这个间隔就结束了
每个task都可以给一个semantic语义名称,通过使用taskDescription属性,这个属性会在工具中来标记任务间隔
任务标识符
let task = session.dataTask(with: url) {
2 /* handle result */
3}
4task.taskDescription = "Load Thumbnail"
5task.resume()
6task.taskIdentifier // 👈🏻 this identifier will be shown in instruments
每个task都可以给一个semantic语义名称通过使用taskDescription属性 这个属性会在工具中来标记任务间隔
任务错误:
当任务失败的时候,错误的提示会打印在间隔的label上 这使得我们更容易调试 下面我们来看 一个任务包含多个事务的情况
2. 展开Task任务描述
我们可以扩展特定任务描述以获得有关该特定任务的更多详细信息。我们还可以将指针拖到特定的时间线以显示更紧凑的版本。
具体任务表示了URL加载系统处理的请求 + 响应对
其中包含了所有的HTTP层的信息:
URL, HTTP版本,连接,缓存信息
请求 + 响应头
请求 + 响应体
事务是仪器如何分解整个任务时间的一部分。默认情况下,请求和响应对由 URL 加载系统处理。交易包含的所有HTTP层信息,例如URL,HTTP Version,Connection和cache info。他们也有关于信息Request and Response header一起用Request and Response body。
3. 按连接过滤
另一个很棒的实用程序是我们如何能够通过连接而不是任务来过滤任务。
4. 识别 http 任务问题(例如:楼梯问题)
我们还可以通过查看每个事务的连接模式轻松识别任务问题。举个例子,楼梯问题。
5. 识别请求(例如:cookie 的过期日期错误)
一旦我们能够识别问题,我们就可以开始识别我们想要查看的请求。点击请求,然后在左下过滤器中按交易列表过滤,然后您将在右下角看到请求信息(扩展详细视图),我们可以开始阅读每个信息。在这种情况下,我们发现了错误的 cookie 到期日期。
6. 识别回溯(例如:缓存响应)
我们还可以检查问题的回溯。与之前相同的步骤,但是将列表改回 URLSession 任务,在右下角您将看到回溯并开始识别每个跟踪。
7. 过滤会话(例如:发现发送到服务器的数据有问题)
正如我在第 5 步和第 6 步中所描述的,我们可以通过 URLSession 任务、事务列表或摘要事务持续时间过滤掉会话。
将报告导出为 .har 扩展名
最后一件独特的事情是我们可以将报告导出到.har扩展程序。首先,我们需要通过单击 保存我们的跟踪File -> Save As -> Save。然后我们可以使用命令行将其导出为.har扩展名。
xctrace export --input YourTrace.trace --har
保存并导出报告.har以分析问题。.har是 JSON 结构,因此非常方便阅读报告的结构。
{
"log": {
"version": "1.2",
"creator": {
"name": "xctrace",
"version": "13.0"
},
"entries": [
{
"_transactionUUID": "BBSA-XXX",
"_taskUUID: "0293-2093",
"serverIPAddress": "182.19.40.111",
"startedDateTime": "2021-05-27T09",
// and more
}
// This JSON contains most of the trace report
]
}
}
实例:
想象我们有一个专门展示图片的类似社交媒体的APP,用户可以上传图片,并且获得一连串最近的上传图片 当加载一系列图片的时候,我们会注意到等全部加载完会花费一些时间,为了分析这个问题我们打开HTTP Traffic面板
在这张图片上 左侧的第一个是请求服务器最近图片列表的任务,当这个任务完成后 我们会创建一个新的任务,加载列表中每个用户看到的(thumbnail)缩略图 现在在它所占用的时间帧区域上点击拖动来获取图像列表 这后边会跟着许多请求来获取每个图片
如图当我们拖动的时候会显示选择的时间范围总共多长时间, 可以看到整个过程占用了超过7秒钟来完成加载初始化的屏幕
前面的一些图片加载比较快,但当我向下滚动,后面启动的任务完成所需的时间会更长
这从图中增长的紫色blocked状态条可以看出。
看起来像是因为竞争问题,我们这里有太多的并行的请求,我们不妨探究一下后边的某个任务 鼠标悬停在上边就可以看到工具的关于任务和它任何子环节的时间间隔提示 可以看到这个任务大部分时间都被阻塞了
为了理解为什么被阻塞了,我们可以查看左侧域名下的向下展开的箭头
如图所示,可以看到当前选择的是绘制任务, 我们切换到 HTTP Transactions by Connection
这个视图将事务按照它们使用的连接而不是按照任务来将它们分类 我们可以找出它们被调度到哪个连接 总体上,这里有6个连接可以处理这些事务,我们来分析connection1上的事务问题,并进一步探索一些缩略图的加载
从上而下事务完成的时间越来越长, 每个成功的事务的紫色阻塞状态都在增加 事实上,这里有一个很清晰的阶梯部分在这里
每一个任务都会在同一个连接的之前的事务完成之前等待。只有这样才能发送它自己的请求,也就是图中每一个事务的灰色部分的开始和上一个的灰色部分的结束是对齐的,这个模式会在每一个后续的事务上重复, 这也就是我们说的线路阻塞,这也是使用HTTP1的问题。令人沮丧的是,这些事务大部分时间都不做任何事情,它们大部分时间都在阻塞和等待服务器的响应,我们可以在事务等待同一个连接的上一个事务的请求响应的时候发送新的请求 ,但是HTTP1并不支持这些,线路阻塞是http的主要问题之一,http的主要提升就是一个连接上向服务器发送多个请求。