大多数浏览器和
Developer App 均支持流媒体播放。
-
在 Instruments 中分析 HTTP 流量
了解如何使用 Instruments 网络模板来记录您 app 的 HTTP 流量,并加以分析。我们将向您展示如何探索会话、任务和单个 HTTP 请求的行为,以及如何对这些行为进行可视化,以确保高效传输数据并尊重人们的隐私。
资源
相关视频
WWDC23
WWDC21
WWDC19
-
下载
欢迎收看 我叫卡斯帕 是Apple的一名表现工具工程师 今天会与塞尔吉奥与您聊一下 Instruments 13中的网页流量工具 HTTP Traffic Instrument 这个工具包含在Network模板中 使你可以经由 Apple的Networking stack 检视来自你App的HTTP流量
这种方法有多种好处 所有的Apple设备都支持它 经过URL加载系统的整个流量 被彻底展示出来 甚至包括新HTTP/3协议 或虚拟专用网络(VPN)发送的那些 由于系统集成 它会将流量都归于其上运行的进程 而由于它 作为Apple Networking frameworks工具 甚至还展示了 抵达磁盘缓存的请求或者网络报错 所有这些 都在更高等级的API定义之下被显露 这些API定义都是你所熟悉的 例如URLSessions 和URLSessionTasks 这个工具会帮助你理解 你的API使用 是如何翻译成网络请求的生存期的 在本次手把手教程中 我们会先带您熟悉一下 Instruments UI如何反应出 您正使用的API定义
快速的介绍之后 我们会展示四个例子 展示一下您要如何使用这个工具 来检测是否存在表现和正确性问题 即使您的App似乎可以完美的运行 您也可以通过审核源自App的流量 来验证其是否按您所想的方式在工作 首先我们来了解下 Networking API 是如何映射到本工具可视化视图的 当我用Network模板录制下系统流量时 HTTP流量追踪就是这样 在instruments中展示的 导航是基于轨道层级构建的 这也是我们细讲中最先谈到的部分 位于顶层的 HTTP Traffic Instruments 总体地展示出在任意时间点 该追踪中运行的URLSession任务有多少 非常适合检测在App生命期中 具有较高HTTP流量活动的时间点 下一层级 依据进程将活动进行分解 除了来自可调试的进程的流量外 还允许你 检视其引发的背景流量 下涵的各个进程都是 其使用的URLSession 这些一一对应于 你代码中创建的URLSession对象 这一层的图像使你能够检视 每一个任务间隔 为了获得对象和可视化视图之间 更好的映射对应 您可以在代码的会话实例中 通过设置sessionDescription属性 为它们命名
最后一层级 流量被按照请求的域进行分解 此层图像展示了更多任务的细节 包括组成了任务的单个事务 和其当前状态
要更好理解任务和事务是什么 我们先来分析一个实例
这里是几个正在从选定的域 加载数据的任务 挑一个仔细看看 分析一下任务的结构
单单这一个任务间隔包含了大量的信息 我们可以用一种较抽象的方式来理解 Instruments的可视化视图 是如何映射到使用的API的
在顶层的是一个任务对象 一个任务由一个或多个事务组成
一个事务由一个HTTP请求 和对应的应答组成
任务层级展示了你的代码 是如何与URL加载系统的API进行交互 当你创建一个任务 并调用resume函数 任务间隔就开始了 一直执行到 completion block被调用之前才结束
每个任务都可以通过 taskDescription属性 获得一个说明性名字 Instruments会用其 为该间隔生成标签 task identifier也是 任务标签的一部分 您可以用它 将该任务与其他数据进行交叉引用 若您的任务以报错形式结束 该错误的描述 会在间隔标签上显示出来 更便于的调试 如我们之前提到过的 一个任务可以由多组事务组成 咱们现在就聊一聊这些 这里有一个任务 内容是加载apple.com这个页面 但这条URL不是标准格式 任务请求的是apple.com 但其更完整的形式 应该是www.apple.com 当我们创建这个任务 URL加载系统 最开始是向apple.com发送请求 随后它很快收到来自服务器的 重定向应答 表示更完善的URL是www.apple.com.
默认情况下 我们会遵循重定向要求 所以这里不会返回301代码 URL加载系统会创建一个新事务 开始加载更完善的URL 而对第二个事务的成功的应答 就是返回给任务的结果
前面提到过 一个事务包含一项HTTP请求和应答 它与URLSession处理 你的任务进行的操作 是一致的 且包含了HTTP层所有的信息 例如请求的URL 被传输数据的信息 以及更多别的内容
与任务的标签一样 事务的标签也向你展示了事务的总概 一般我们主要去获取 请求和应答的相关信息
轨道层级可以告诉你请求的域名是什么 标签本身就有 路径和查询请求
除此之外 间隔标签显示了HTTP的版本 HTTP方法 以及改请求是否发送了授权 或者Cookie标头 这些信息可以帮您一眼扫过去 就了解一个身份验证流的概况
应答中则可以获得状态代码 应答是否包含了一份cookie 以及应答的内容类型 请求和应答花费的时长 以及事务中其他工作的 详细的计时信息 都由事务状态进行捕捉 咱们在这个任务中 具体分析一下 这个事务的开始时间点 是当URL加载系统 创建一个事务来发出这个请求 它首先会检测我们是否已经 有一份有效的高速缓存应答 如果没有 它就会尝试在连接上规划请求
接着该事务可能需要 在Blocked状态下等待一小会儿 等待一个可用的连接
当事务终于获得一个连接 发送请求(Sending Request)阶段 就开始了 当请求的最后一个比特 都发送到网络上之后 该环节结束 接着 事务进入等待状态 等待应答 随后就是接收应答 其会从接收第一个比特一路追踪 直到最后一个比特接收完成
最后一比特接收完成后 URL加载系统很快判定 这是否是一个成功的应答 然后整个事务就算完成了 在实践中 缓存查询 和发送GET请求阶段都非常迅速 通常是图中这样的
这里为您展示一些实例 这里有请我的同事塞尔吉奥 他通过一个最近开发的App 向您演示HTTP Instrument 是如何帮助您 修正表现和正确性问题的 谢谢 卡斯帕 大家好 我叫塞尔吉奥·洛佩兹 目前正在开发一款 服务于爱狗人士的App 可以理解为一款 专门为狗狗照片开发的社交媒体 狗狗照片独享哦 人们可以发布狗狗的照片 可从上面获取最新上传的图片 当我启动App 它会加载若干新的狗狗照片 但是我留意到 完成加载需要相当长的时间
现在我们用新的HTTP Traffic Instruments来配置这个App 从而设法改善这个情况 在“Product”菜单下 选择“Profile”选项 对我的App在软件中进行配置
这样就会根据发布的参数 来构建这个App 以确保我的App与用户的配置一致 所有的优化选项都打开 当构建完成之后 软件会自动启动 启动后 软件的标准模板选择器 会展示在屏幕上
这个案例中 我想选择左下方的Network模板 可以给我们更多 此App生成的总体网络连接的信息 同时还兼具HTTP追踪功能
轨道区域现在包含2项 各对应一个工具 下面这条就是已有的 Network Connections工具 上面这一条是新的 HTTP Traffic Instruments 今天我们主要讨论新工具 现在我只需要点击“record” 软件就会启动我的App并开始录制
在学会使用这个工具之前 你需要确保自己理解 Network流量采集的可能结果 其采集力非常强大 尤其当你录制下所有进程的话 采集到的数据包含所有发送出去的信息 这些信息有可能是私人或者敏感信息 甚至可能是用户认证信息 因此 所获得的追踪文件 必须要谨慎处理 请大家一定要意识到这一点 这里我们点击“确定”继续录制
App启动了 图片缓缓地加载出来
现在我停止录制
将刚才录制的数据放大查看 方法是同时按下Option和鼠标 拖拽鼠标框选HTTP流量区域
点击在界面左上角的 “HTTP Traffic”旁边的下拉箭头 就可以看到卡斯帕之前描述的 完整的轨道层级
我还增加了轨道高度来显示所有的间隔
最上面一条是第一个任务 它向服务器发送了查询图片列表的请求 即在App“最新(Latest)”标签页的那些
当这条任务完成后 我们创建下一条任务 为接收到的列表中每张图片 都创建一个缩略图
现在我框选 请求图片列表所用的时间区域 其下涵盖了 检索每张图片的一连串请求
框选了这个区域后 屏幕上会出现一条工具提示文本 告诉你框选的区域的持续时长 这里App一共用了7秒的时间 完成初始界面的加载
开头的若干图片加载的非常快 但往下滚动 后面开始的那些任务 需更长的时间来完成 图中代表Blokced状态的 紫色时间条越来越长 这看起来是发生了拥堵 就是说同时提交了太多请求 我们选一条排在后面的任务详细检视
鼠标悬停在任务上 工具提示条会显示 任务的时长 悬停在任何子间隔上也能查看其时长
这条任务的大部分时间 都处于Blocked状态
要理解为何这里会被阻拦(Blocked) 我们切换一下轨道显示方式 切换成“HTTP Transactions by Connection”视图
在轨道的左侧边栏中 域名下面有一个向下的箭头 点击这里来切换轨道显示方式
当前选取的是“Tasks”视图 我们把它切换成“HTTP Transactions by Connection”
这个视图只显示事务 现在不再按照任务对事务分组 我们可以查看每个事务 被规划到了哪个连接
事务现在根据各自使用的连接进行分组 这里一共得到了6个连接 来处理这些事务 这里我们分析一下 Connection 1上发布的事务 随后详细检查一些 加载缩略图的事务的细节 从上往下 很明显 越往下的事务花费的时间越长 越往下 代表Blocked状态的紫色时间条就越长 实际上 很明显这里呈现出阶梯状
直到同一个连接上的前一条事务完成 后一条事务才会结束Blocked状态 才能发送自己的请求 这个模式会依此延续到下一条事务
这被称为“线端阻塞” 是使用HTTP/1的问题之一
令人沮丧的事情就是 这些事务在大部分时间什么事都不能做 它们大部分时间都蹲在阻塞状态 或者等待服务器的应答 我们其实可以 在前一条事务正在等待应答时 将处于同连接中的 下一条事务的请求发送过去 但是HTTP/1不支持这样做 线端阻塞是HTTP/1的主要限制之一 HTTP/2的主要进步就是 通过将若干请求向同一服务器多重发讯 来避免这个现象
HTTP/2中 我们可以 在第一个等待应答时发送第二个的请求 而你的App不需 要做任何修改来支持这个 所有的Apple平台都支持HTTP/2 而且从iOS 15 以及macOS Monterey之后 HTTP/3也都支持得很好 客户会选择服务器支持的 最新的HTTP版本 若你想了解更多HTTP/1和2版本 之间的区别 以及HTTP/3提供的额外好处 请前往“用HTTP/3 和OUIC实现网络加速”章节 了解更多 我拿着这里的追踪文件 给我们的服务器团队看 终于说服他们 我们真的应该支持HTTP/2 现在我们在加强之后的新服务器上 运行App
天哪 这次快了很多 我们再到软件里验证一下 这里展示的是 启用了HTTP/2的 服务器支持后的追踪图 在域这一栏的轨道中 再也没有任何缩略图加载任务 的Blocked时长持续很久 非常好 我们再切换到HTTP Transactions by Connection 这种视图
首先会注意到 这里只有一个连接 这是因为我们不再需要 多条连接来发送并发请求 这同样意味着 我们只需要付一次连接设置成本 现在把目光投到单个缩略图加载事务上 回发现它们在Blocked状态 几乎没有耗费什么时间 实际上 由于这部分时间太短 在这样的视窗放大程度下 几乎看不到紫条 最后 所有的事务都完成了请求的发送 留在原地等待各自的应答 随着我往下滚动 可以看到这些应答都在同时进行
总体算下来 所有的请求都在3秒之内完成了 这比之前快了2倍有余 在我与负责服务器的人谈过之后 将其从HTTP/1.1 切换到HTTP/2 然后我们App的图片加载变得快多了 现在我们再次启动App 告诉您我们还能做点什么 当我点击一张图片 App会将完整分辨率的图片加载出来 并显示此照片是在离我多远的地方拍摄 右上角还有一个心形图标 如果你喜欢这张照片 就可点它为其点赞 要进行这样的操作 我需要先登录账户 我允许用户直接使用App来浏览图片 但是要保存你点赞的图片 在设备之间进行同步 还有上传新图片的时候 你就需要一个账户 那么我们现在登录账户
很好 我再点赞一张照片 这只小狗看起来真可爱 我把他加入点赞列表 等一下 我刚才已经登录了 为什么现在又要登陆一次 这里有问题 我的App应该知道我已经登录过了 以前没有这样的问题 所以我要取消这个登录页面 因为我不想再次登录
之前在重复这个问题的时候 我已经录制好了一个追踪文件 咱们用这软件打开并分析这份记录 最左边的这个任务 对应我第一次点击“点赞”按钮
它右边这个任务 对应的是我回到最新标签页 然后图片流得到刷新这件事
下一个任务对应我点击另一张狗狗图片 来加载其全分辨率原图的操作
最右边的任务 对应我第二次点击“点赞”图标这件事
第一个任务间隔实际上包含了2个事务
第一个事务接收到一份401状态代码 这是预料之中的事 因为我们当时没有登录 该事务用橙色长条表示 意味着其在HTTP层级未成功
然后任务经过了一段较长的空白时间段 这对应的就是 我输入用户名和密码那段时间
当我完成输入这些验证信息之后 该事务被再次进行 此处绿色的间隔时间条 和201状态代码 说明这次执行成功了 这个身份验证质疑的交互 即“输入密码后重试该事务”这个过程 是URL加载系统 为我们处理的另一件事 因此这两个事务属于同一个任务对象
缩小一点看 第二次尝试点赞图片的任务出现在右边 这个任务对象显示为灰色 因为我取消了登陆页面 从而使任务也被取消 此情况在其标签上也写明了 事务区间则显示为橙色 因为我们又从服务器 得到了一份401应答 该任务发生在 我试图点赞另一张狗狗图片之后 登录页面第二次被触发 我们使用非常基础的登录系统 当用户第一次发送验证信息之后 一旦服务器验证完这份用户信息 就会设置一份cookie来识别该用户 这样之后的请求就不用再次验证 所以我原以为这个任务 会发送完善的cookie文件 我们来看一看是不是真是这样 如卡斯帕之前提到过的 HTTP方法旁边 应该有个cookie小图标 使这个事务发送一份cookie标头 但这里却并没有这样的图标 说明未发送cookie 这部分工作未成功执行 那么问题来了 这是因为服务器没有提供cookie 还是虽然有了cookie 但是用户没有发送 要解开谜题 我们需要去检查前一个事务 看看是否从服务器获取了一份cookie 这就是前一个事务 即第一次的成功登录 其在应答环节时间条上 确实有cookie图标 所以服务器的确是发送了cookie的 这就有意思了 为何在下一次事务中 我们没有发送这份cookie呢 为了获取关于这个事务的更多信息 调查cookie的细节 我要切换到“Transactions”列表 它位于下面的详情视图中
由于轨道视图中光标 位该事务的时间条区域内 所以下面视图里该事务处于选中状态
下面一栏右侧的详情视图中 显示着当前选中的事务的 所有请求和应答的标头
这一部分就是 我们要找的Set-Cookie标头 第一眼看去 这份cookie似乎没问题 但是等等 看到这里的有效时间了吗 是2020年3月 早就过去了 所以 服务器确实发送了cookie 但这是一份过期的cookie 没人喜欢过期的东西 这会导致URLSession 不再发送这份cookie 因为它只发送有效cookie
所以这是服务器方面的问题 我可以将追踪文件发给服务器方面的人 他们依此来调查问题并设法解决 解决了cookie问题之后 现在我可已点赞多张图片 而不需要重复登录 除了“最新”标签页 App还有个“已点赞”标签页 内列所有用户点赞过的狗狗图片 我们切换到这个标签页
很好 这里有一些是我昨天点赞的 但出于某些原因 我最近点赞的照片却没有出现 我们再来试试 我们看看这张图 这小狗似乎很喜欢洗澡的样子 我们给它点个赞 然后回到点赞列表 看看显不显示它
哎呀 没有显示 我们再到软件中看一看问题出在哪里 我事先准备好了追踪文件 在轨道视图中 我应该能找到加载点赞列表的任务 但是第一眼看去 好像没有找到 那这里我们选中服务器域轨道 只显示发送到域的请求 然后在下方的详情视图中 会列出这个域的所有任务
请求的数量还真不少 我们可以使用下方左侧的详情过滤器 查找与“点赞(Favorites)” 相关的所有请求 来验证我们是否发起了请求
过滤之后 查找结果显示 我们发送了若干加载点赞列表的请求 我们将目标聚焦于轨道视图
我在详情视图中选中的一个任务后 轨道视图中光标 会定位到该任务的开始点 所以在轨道视图中很容易找到它 我们放大一下细细查看
这是刚启动App后 我们第一次加载点赞列表这件事 这里没问题
这里 我点赞了一张新图片 然后我们再次加载点赞列表
这里确实有任务间隔 但是非常短
这条GET请求仅仅花费了几毫秒 对于服务器应答来说 这太短了 我们切换到“HTTP transactions by connection”视图 获取更多的细节信息
首先我们会注意到 这个事务并不是在连接上执行的 而是基于“本地缓存” 这说明这项请求根本没有发送到网上 而是直接从本地缓存加载的 这也解释了 为何这里没有“等待应答”阶段 因为该事务根本没有等待任何服务器
问题搞清楚了 即我们的请求直接被缓存了 并未真的发送给服务器 每次得到的都是缓存给予的应答 解决方法之一是告诉服务器 设置一份cache-control标头 要求永远不要缓存这份应答 我们期望的用户每次来到点赞标签页时 重新加载图片 以此使新点赞的图片也可以显示出来 我们不希望的是 如果没有变化时依旧加载整个列表 比较合理的折中方案是 我们询问服务器 这次有什么变动吗 如果有 那请告诉我 我们可以 通过在请求中设定缓存策略来实现
要更新代码 我们回到任务视图中 选中有问题的任务
这里执行的 每一个URLSession任务
其回溯跟踪(backtrace) 都显示在右侧 该任务中出现了“恢复(resume)”
出现在方法同步这一步 类是ImageCollection 我们在Xcode中打开 做一些修改
这里是我的URLRequest 现在我想设定缓存策略
我想要的缓存策略是 reloadRevalidatingCacheData 就是说忽略本地缓存 并向服务器发送请求 检查我们的缓存是否有效 如果有效 服务器会返回304应答代码 告诉我们用本地缓存就好 如果无效 它就发送新的数据回来 咱们来试一试
这些是我现在点赞过的图片 洗澡的小狗照片现在已经添加进来了 我们再点赞一张
好的 去“已点赞”标签页看看 我刚才点赞的图片现在正常显示了 好的 很不错 这个问题也解决了 现在将镜头交还给我的同事卡斯帕 他为您讲解如何检测App 或非独立行为是否如你预期般工作 如塞尔吉奥刚才展示的 当我在未登录状态下 点击“已点赞”标签页 登录页面就跳出来了 我们已经添加了 “Sign In with Apple”选项 让登录体验更加顺滑 但是我们公司 有若干个宠物主题的App 另一个团队正在致力于研发一个 共享登录的软件开发程序包(SDK) 使用户可以在不同App上 用同一个账户登录 该SDK还处于研发中 另一个团队问我们可不可以 用它代替原来的经典登录页面 我拿到了SDK代码 命名为Pets 是以xcframework形式发布的 这样所有的平台都可以使用它 把它整合到我的Xcode项目中非常简单 直接拖拽到嵌入framework的区域即可 余下要做的就是 在已有的页面添加按钮了 我们现在定位到登陆页面的源代码
首先导入framework 然后在Sign In with Apple语句下 将按钮添加到 我们的SwiftUI的VStack
现在刷新一下Swift UI预览
按钮出现了 一如我所期望的 标着“Sign In with Pets” 的按钮出现了 这是一种非常便捷的整合 我很好奇这种新的登录方法会有多快 为了测量这个 我将用Instrument配置App 点击“Product”菜单下 “ Profile ”选项
这里选择Network模板 点击工具条上的“record”按钮 启动App
我的App现在完成启动了 现在切换到登录页面 Instruments现在为我们展示 所有实时发生的网络流量 我这里将其展开 检查App的URL会话
就是这里 但是等一下 我原本认为这里只有App的主URL会话 但是似乎刚才整合进来的 名为Pets的framework 正在从自己的会话发出请求 而我并未点击登录按钮 这倒是出乎意料 我们现在停止录制来看看是怎么回事
我们将前面这几个请求放大一点看 按下Option 用鼠标框选
这里有很多个分析型端口请求 若想获得更多细节 可以点击这个 “Pets Sign On Network”会话 在详情视图中全部列出来
这些都是POST请求 当我点击其中一个 右侧会显示其回溯详情 帮我们厘清这个请求来自哪部份代码
所以 看起来这个请求 来自CFNetwork 由Pets发起 一如我们所料 但是随着我们往下继续抽丝剥茧 似乎还牵涉到CoreLocation 这就很可疑了 尤其因为我根本没有执行 任何触发它的操作 我怀疑我的坐标被发回给了服务器 所以CoreLocation和CFNetwork 才会在同一条回溯详情里
为了验证这一点 我要去检查这些任务对应的HTTP事务 我们要先将详情视图 从任务列表切换成事务列表 选中其中一个
下面右侧的扩展的详情中 很明显 这条请求包含了 一些非常标准的标头 没什么异常 但是等一下 看看请求体这里 其中包含了我的位置坐标 这就很不好了 发送这种信息是违反用户隐私政策的 我们不想 在未经许可 没有合理理由的前提下收集用户位置 目前 我们的App仅仅在 提高用户体验这个合法目的下 才会请求获取这类信息 现在 我不会对这套SDK 做更深一步的整合 我会提交一份错误报告 给另一个团队 提醒他们在这里发现了 这种不能接受的行为 我甚至还可以 用Instruments的回溯详情 直接生成错误报告所需的必要信息 我们先存在桌面上
命名为“隐私侵犯” 然后点击“保存”
xctrace是 Instruments中 的命令行工具 可以用来将这份回溯详情 导出成HAR格式的文件 这是一种行业标准格式 用于交换关于HTTP流量的信息 这里我直接运行 xctrace export命令 将我的回溯详情打包进去 导出成HAR格式
我们现在运行一下
这条命令生成了一个文件 作为错误报告的附件 收件人可以用它检看记录下的信息 即使他们没有安装Instruments 任何支持HAR的工具都能查看此附件
HAR文件本身是以JSON为基础的 所以记事本也可以打开它 或者用脚本方便地处理 尽管这里不包含 Instruments的特有详细信息 例如URLSessions或者回溯详情 但是也足够帮另一个团队检查这个问题
这就是如何通过 HTTP Traffic Instrument 对来自你的App的流量的源和内容 进行诊断的方法 可以帮助你实时掌控App在做什么 现在大家对新的HTTP Traffic Instrument已经熟悉了 请亲手用自己的App试试 像今天我们示范的一样 检查它是否有问题 为了调试更简单 以及在过程中有更多提示信息 可以对您的URLSession 和任务对象命名
永远看齐到最新的网络协议 即使您并不想检查 App的表现和正确性问题 也请动手验证一下 你发送了多少数据 以删减不必要的流量 感谢您的观看 我们希望您能在追踪App 的HTTP流量过程中有很大收获 [欢乐的音乐]
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。