iOS 网络监控

1.背景

随着业务的发展,用户对于网络的依赖场景会越来越多,随之而来遇到的各种异常网络场景也越来越多。

  • 1、为了保证网络的接口的持续健康、及时发现问题,为网络性能优化提供数据基础。
  • 2、同时以报表的形式直观的去展现现有网络问题。
  • 3、也为了更好的支撑后续业务的发展,就需要我们去搭建起网络监控体系。

2.目标

提供一套完整的网络采集、监控和预警的可视化机制,用于线上接口可用性和健康度观察,并提供一系列排查问题的辅助信息。

通过仪表盘将接口健康度可视化,包括但不限于以下能力:

  • 总体请求成功率
  • 过滤单个请求成功率、失败错误码
  • 查看接口请求详情
  • 接口访问平均耗时、时长分布
  • 通过对接后端的链路追踪,实现从客户端请求的发起到最终具体服务器的处理返回全链路追踪。

3.整体架构概览

网络接口监控架构.png

不管是 iOS 还是 Android ,两者最终要做的目标方案如上图。这里从下到上分别阐述每个部分的功能:
网络基础库:针对平台特性,这里有 iOS 的 AFnetworking、Alamofire 和 Android 的 okhttp3、okhttp4 ,其实现原理应该都差不多,都是针对底层的网络api进行进一步的封装,提高接口的易用性。

拦截器:主要是针对各个基础网络库进行接口拦截。根据平台不同,具体的拦截方案在下文中阐述~

网络封装库:一般开发过程都会针对基础的网络库再做二次封装,加入一些策略、缓存、安全校验等管理,使其更加贴合业务和快速接入使用。

插件/功能模块:以插件化的形式提供额外的网络功能

统计模块:将从业务开始调用到回调给业务方的各个环节的耗时及状态值,变成统计数据汇报到APM。
网络诊断模块:对关键业务进行诊断,包括dns解析、ping、弱网检测等,输出诊断报告并上报到APM。
重试模块:根据策略进行重试,包括 ip 重试、https 降级重试、原 url 重试等。
httpdns模块:提供 httpdns 能力,解决域名劫持问题。
上传模块:提供上传能力,包括断点续传、分片上传以及包体大小、上传耗时等信息监控。
下载模块:提供下载能力,包括大文件下载、断点续传以及包体大小、下载耗时等信息监控。
mock 模块:提供 mock 能力,主要用于测试和后台接口还没有准备好的情况下使用。
对外接口层:这一层直接对接上层业务。

4.数据采集

第一期方案主要是做数据采集,然后上报阿里云,
web 可视化界面和插件/功能模块由于人力问题暂时不纳入第一期,后续再继续做。
  • 1数据采集重点落在架构概览图的“拦截器”这一部分,采集的数据主要有以下字段:
    connect.jpeg
参数 key 类型 参数意义 备注
请求数据 traceId string 单次请求的唯一标识 id
id string 节点 用于以树状图的形式分析和呈现调用链路
pid string 父级节点 用于以树状图的形式分析和呈现调用链路
url string 请求 url 取 host 后面那一段 url
scheme string 协议 http or https
clientHost string host 域名
queryParam string 请求参数
method string 请求方式 POST、GET、DELETE 等
ttt double 请求总耗时,单位:毫秒 responseEnd -fetchStart
dnst double dns 解析耗时,单位:毫秒 domainLookupStart-domainLookupEnd
cnt double 连接耗时,单位:毫秒 connectStart-connectEnd
tls double tls 耗时,单位:毫秒 secureConnectionStart-secureConnectionEnd
reqt double request 耗时,单位:毫秒 requestStart-requestEnd
rest double response 耗时,单位:毫秒 responseStart-responseEnd
beginTime double 请求开始时间 取值 fetchStart
endTime double 请求结束时间 取值 responseEnd
handleTime double 请求处理时间,单位:毫秒 responseEnd - fetchStart
responseCode int 响应状态码 这里取的是NSHTTPURLResponse的 error code,该 error code 只记录了 client-side 的 error,不包含服务端的,详细见苹果官方文档:Life Cycle of a URL Session with System-Provided Delegates
resd string 响应描述 成功为空,失败为 error.description
reqhsize int64_t 请求包header大小,单位:byte
reqbsize int64_t 请求包body大小,单位:byte
reshsize int64_t 响应包header大小,单位:byte
resbsize int64_t 响应包body大小,单位:byte
uhttpdns bool 是否有使用httpdns
设备相关 deviceId string 设备唯一标识 根据设备标识后面可以查询整个设备的网络请求情况
appVer string app 版本
appName string app bundle identifier com.ad61v1.drawLiveStore
os string 系统版本 14.2
platform string 平台类型 iOS/Android
deviceType string 设备类型 iPhone/华为/vivo
网络相关 ope string 运营商 非wifi 下统计使用的是哪个运营商
ns int 网络类型 4G/5G/wifi,取值typedef NS_ENUM(NSUInteger, DLNetType) { DLNetTypeBreakdown = 0, DLNetTypeWiFi, DLNetType5G,DLNetType4G,NetType3G,DLNetType2G, DLNetTypeUnknow};
地域相关 latitude double 维度 (可选)有开启位置权限下获取,不主动要求位置权限
longitude double 经度 (可选)有开启位置权限下获取,不主动要求位置权限
android 特有 okHttpVer string OKHttp 版本号 不同版本对数据收集可能有影响
okHttpExceptionRetryCount int okHttp 内部异常重试次数 okHttp 请求异常情况下,内部可能会进行重试,该重试不会经过 start
  • 2.针对平台特性不同,以下分别阐述拦截器这部分的实现方案:
  • iOS:NSProtocol + hook 方式


    netwrokTrack.jpeg
  • 要 hook 的接口:


    networkTrace.jpeg
  • Android:OkHttp+Retrofit+AOP+EventListener(Aspectj v2.0.10 方式)(推荐)
  • hook层 描述


    androidHook1.png
androidHook2.png
androidHook3.png

hook 层主要包含两个东西:NetworkInterceptor & EventListener

1:利用AspectJ hook OKHttp的build 函数。
2:在build 函数执行之前,注入hook 内容,NetworkInterceptor & EventListener。
3:NetworkInterceptor 主要用于request & response的拦截处理,可以管理整条链条。
4:EventListener 主要收集网络各个阶段的耗时收集。
附:OkHttp3的架构图 & AOP 插桩原理 图

androidHook4.png
androidHook5.png
  • 3.采集策略

对拦截到的所有网络请求,该如何抉择是否需要保留,是全部采集还是部分采集,这里需要跟进后台下发的配置进行采集,因为网络请求数据量比较大,所有必须进行抽样上报,抽样规则以设备为纬度(去除业务耦合),抽中的设备所有请求接口都需要上报,不在对设备的接口进行再采样的目的是为了能够从各种网络环境下收集单个设备的所有请求数据,才能完整地表现出该用户在网络请求健康度。罗列出来则为以下几点:

后台以设备为纬度进行采样,这里采用对采样率取模,然后下发配置
收到后台下发的采样配置的设备全量采集数据上报

app 启动的时候会上报deviceId,deviceId 的作用在于过滤特殊设备的特定请求。在获取到配置之前的网络请求又该如何处理?目前采用的方案是在SDK内置域名白名单,只有通过白名单检测的请求才记录上报,拿到配置之后更新本地配置。同时,该机制也可以过滤掉第三方的冗余数据,专注在我们想要收集的数据上~

设备绑定,这里除了deviceId外还需要以下这些信息

deviceId          设备唯一标识
platform          平台(iOS、Android、PC、web)
appCode           哪个项目的     
appVersion        app 版本,后续有可能会根据版本做兼容策略

配置信息

{
    whiteList: { //针对域名
        domain: ["xxxx","xxxx"]
    },
    blackList: { //针对接口
        api:["host/v1/student/device/registerDevice","xxxx"]
    },
    batchUploadCount: 100 //批量上传条数
}

接口说明:

白名单是针对域名的,里面的 domain 字段是为了过滤第三方的网络请求。

黑名单是针对接口的,api 字段记录着完整的请求url,主要是为了防止特定用户的一些特定接口高频次失败影响了整体的数据。

batchUploadCount 为批量上传数目,达到设置的条数时再压缩上传。

第一次启动默认所有符合内置规则的请求都会上传,配置接口返回数据(为空这data为{})后更新本地默认规则,后续按照更新后的配置进行过滤。

接口文档地址:这里

如下:黑白名单配置---采集流程图:

网络监控流程图.png

获取配置时机

app启动时候,异步,延迟1.5秒再加载,防止影响启动速度和正常业务请求。失败则原url进行重试3次,根据域名白名单规则,该获取配置接口也同样会纳入监控。

  • 4.对接通用平台链路追踪

客户端:

为了能够跟通用平台的链路追踪串联起来,实现请求从“客户端-路由器-服务器-具体响应服务器”一整条链路的完整监控,客户端这边需要 hook 每个请求,然后在请求头里面加上 requestId、linkWayId、linkWayPid。

requestId 用于标识唯一请求,生成规则:bunderIdentifier_uuid_threadId_timestamp 。

linkWayId、linkWayPid 用于以树状图的形式分析和呈现调用链路,linkWayId 取值为 1,linkWayPid 取值为 0。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容

  • 目标 TCP建立连接时间 DNS时间 SSL/TLS时间 响应总时间 请求头、请求body、响应头、响应body大...
    mtry阅读 3,118评论 1 5
  • iOS 网络监控 前言 最近公司业务需要,对网络进行监控,本文主要记录下在网络流量监控实现过程中遇到的一些问题的解...
    Zsj_Sky阅读 1,758评论 1 2
  • Reachability 项目是 Apple 提供的一个官方 Demo, 用于演示如何使用 System Conf...
    要上班的斌哥阅读 2,243评论 0 12
  • 我是黑夜里大雨纷飞的人啊 1 “又到一年六月,有人笑有人哭,有人欢乐有人忧愁,有人惊喜有人失落,有的觉得收获满满有...
    陌忘宇阅读 8,520评论 28 53
  • 信任包括信任自己和信任他人 很多时候,很多事情,失败、遗憾、错过,源于不自信,不信任他人 觉得自己做不成,别人做不...
    吴氵晃阅读 6,178评论 4 8