我们项目是一个B端工作台系统,用户每天大约8小时工作在我们系统中。近期时有用户反馈工作台在下午使用时候,经常在打开一个新浏览器标签时候,浏览器抛出ERR_INSUFFICIENT_RESOURCES网络错误。此错误导致新打开的页面无法查看,严重影响用户正常工作,因此需要对其进行排查,争取解决掉这个问题。其表现截图如下:
一:问题分析
- 我先翻译了下INSUFFICIENT,是不足的意思,看起来错误描述应该是:资源不足。
- 以ERR_INSUFFICIENT_RESOURCES为关键词谷歌搜索了下,虽然相关文章不多,但是综合分析了下,这个资源不足应该是指网络连接资源不足。
- 网络连接资源不足?可是看我们系统使用正常啊,只是新打开的这个tab报此错误而已。看来应该抓一下包,这时候可以使用chrome自带的抓包工具 chrome://net-export/ 进行抓包(比如在用户电脑),也可以使用whistle或者fiddle之类的抓包工具。为什么不使用devTools的netWork,是因为有些后台请求netWork是看不到的。我这边打开我们系统,然后使用whistle进行抓包,经过一段观察,果然发现大量本不应该属于我们业务范围的请求:content-autofill.googleapis.com/v1/pages/ ,看这个域名大体也能猜到是googleapi的请求,然后跟autofill自动填充有关,联想到我们工作台有大量表单填写的操作,大概率跟此有关。
4. 以content-autofill.googleapis.com为关键词再进行了一下google搜索,结合ERR_INSUFFICIENT_RESOURCES为关键词进行的搜索,大体得出一个结论:表单项的input输入框,因为自动填充功能,会发出content-autofill.googleapis.com请求,如果此请求超时失败(客户电脑没有装vpn),会将此记录下来后续空闲时间会retry重新尝试继续发请求。随着系统的使用,表单又特别多,这种失败请求会越累积越多,直到达到一个阈值2700。达到一个阈值后,对于本进程的渲染tab没有影响,而是在打开新tab时候,有一段对此阈值的检测,如果检测到此类请求达到阈值后,则会报ERR_INSUFFICIENT_RESOURCES错误。 5. 基于大体猜测到的原因,我在chromium的源码网站进行了搜索,确实从代码层面得到了验证。源码搜索地址。源码中有一个阈值 kMaxOutstandingRequestsPerProcess = 2700,在浏览器创建新的tab时候,有一段代码会检测是否已达到阈值,如果达到阈值则抛出ERR_INSUFFICIENT_RESOURCES错误。可以在chromium的源码search通过搜索max_loaders_per_process_ 逐步定位到此段逻辑。然后以content-autofill.googleapis.com为关键词也会在源码中搜到有一个开关标志位开标志kAutofillServerCommunicatio,是否允许后台发送autofii请求。我挑了几张截图如下:
二:问题验证
既然问题原因大体猜测到了,剩下的就是验证了。我们要验证以下几点,首先要验证content-autofill.googleapis.com请求是跟自动填充有关,其次要验证如果content-autofill.googleapis.com超时请求超过阈值,在新打开tab时就会抛出ERR_INSUFFICIENT_RESOURCES错误,或者反向验证如果content-autofill.googleapis.com请求没有超时或者直接不发,在新打开tab时就不会触发ERR_INSUFFICIENT_RESOURCES错误。
- 验证content-autofill.googleapis.com域名的请求是否跟自动填充功能有关:将浏览器的自动填充功能关掉,通过抓包工具观察是否还有content-autofill.googleapis.com域名的请求。此条我已经确认,关掉浏览器自动填充功能后确实不再发出content-autofill.googleapis.com域名的请求。
- 验证content-autofill.googleapis.com域名的请求一旦超时,后续会继续尝试请求:修改本地host文件,将content-autofill.googleapis.com域名解析到一个不能访问的域名,我本地实验时随便试了一个:234.56.2.1。然后在我们系统打开几个表单,通过抓包工具查看到已经发出数次content-autofill.googleapis.com请求,但是全都返回502。然后离开我们系统tab,不再进行任何操作,继续观察后续是否会有content-autofill.googleapis.com超时请求的retry。此条我本地已经复现,得到确认。
- 验证如果content-autofill.googleapis.com请求非5xx错误,是否后续还有retry请求:修改电脑host文件,将content-autofill.googleapis.com域名dns解析到127.0.0.1,本地起一个nginx(修改config监听端口为80),或者解析到百度的ip:110.242.68.4。然后观察一段时间(注意:windows的host文件必须管理员权限才能进行修改)。此条我也得到确认,如果返回200或者404或者403,后续都不会再尝试继续发起content-autofill.googleapis.com请求
- 验证超时请求超过一定阈值,新打开浏览器tab时候报ERR_INSUFFICIENT_RESOURCES错误:下载并修改chrome源码然后重新编译,将max_loaders_per_process_阈值设置为一个小的数字50/100,然后编译,配合第2条,造出阈值条数的502请求,本地验证。
- 验证如果将kAutofillServerCommunicatio标志位设置为false,是否还会发出content-autofill.googleapis.com请求:下载并修改chrome源码然后重新编译,将kAutofillServerCommunicatio标志位设置为false,然后编译,本地验证。此条我也得到确认,已经下载了chromium源码,并修改了下此值,重新编译出chromium浏览器程序。
三:问题解决办法
- 通过浏览器设置,让用户自行禁用自动填充功能。
- 如果能在网络层面,比如路由器/交换机/dns服务器之类的,能通过dns将content-autofill.googleapis.com域名解析到一个指定的ip就好了。
四:chrominum源码的搜索、下载、编译
- 其实chrominum提供了类似web-ide的网站,可以对源码进行搜索,也可以实现一些函数跳转,变量跳转扥功能。搜点代码还是很方便的:chromium源码
- 如果想将源码下载下来自行编译,其实也很方便,按照官方提供的文档逐步走下来就可以了:mac下chromium下载以及编译官方文档
- 我在行下载编译的过程中,下载代码大约花了1个小时,注意下载时候带上--no-history参数。然后编译环境需要xcode,从AppStore下载安装xcode用了半个多小时,然后解决编译前的一些小问题大约半个小时,最后编译大约六万左右文件,花了三个多小时(苹果m2,16核32g内存,全场cpu接近打满,如果是intel的可能会需要10个小时左右)