如何保证页面卸载时的上报数据完整性
监控系统重要的一环是数据上报。
为了减少请求的次数,我们把一些细粒度的收集信息压入到内存中,等待触发一定规则后上报后台。
一般的规则是, 等待20s 或者 队列中的数据达到一定条数(如10条) 或者页面 unload时!
定时和定量的操作是没有问题的, 可以使用xhr或者其它任何交互方式,都可以轻松完成, 并保证数据的完整性!
然而,页面unload时,坑就多了,
1. 使用异步xhr
这是最先使用的方式, 在chrome测试一切ok。 但是线上运行一段时间,发现数据丢失的现象。基本可以确定是浏览器行为导致的unload未成功执行异步xhr,
解决方案: 在unload时加一个循环等待, 或者创建一个img并指定src, 通过资源加载的方式延迟关闭以保证异步请求正常发送
2. 异步不好使,试试同步xhr
同步xhr,在现代浏览器已经不提倡使用, 同时同步的操作也会阻塞浏览器的关闭, 如果是reload,会造成用户体验问题, 并不是一个合适的解决方案, 但是可以作为备用
3. 杀手锏 sendBeacon
使用 sendBeacon()
方法会使用户代理在有机会时异步地向服务器发送数据,同时不会延迟页面的卸载或影响下一导航的载入性能。这就解决了提交分析数据时的所有的问题:数据可靠,传输异步并且不会影响下一页面的加载。
BUT! 杀手锏毕竟是新玩意,对老古董还是没效的
注意点
chrome最新版本已不支持发送application/json格式的blob数据,会出现如下错误
Failed to execute 'sendBeacon' on 'Navigator': sendBeacon() with a Blob whose type is not any of the CORS-safelisted values for the Content-Type request header is disabled temporarily. See http://crbug.com/490015 for details.
可以改成使用以下三种
- application/x-www-form-urlencoded- multipart/form-data- text/plain
4. 如果不追求时效性, 自然是使用缓存+延时发送的策略最优雅, 同时丢失数据的问题也可以大大改善
在unload或者beforeunload中,将数据写入localstorage (caniuse), 下次加载之前检查下是否有需要发送的数据, 有的话拿出来发送并清除数据
使用beacon demo如下:
if(navigator && navigator.sendBeacon) { var blob = new Blob([stringify(data)], {type : 'text/plain'}); navigator.sendBeacon(this.endpoint, blob); } else { if(_window.XMLHttpRequest) { var xhr = new XMLHttpRequest(); xhr.open("POST", this.endpoint, false); xhr.setRequestHeader("content-type", "application/json") xhr.send(stringify(data)) } }
=========================
19.08.05 测试
方式: 定时2min + 动态条数发送记录;sendBeacon+同步ajax兼容处理; unload超过2s,放入到localstorage;load时加载localstorage补发
验证测试数据, 数据丢失率高达6%
可能原因:
1. 由于合规问题,prod会前端重定向域名,导致补发可能未成功
2. 可能出现人为强制刷新,导致失败
3. 原先认为该数据只做补充,未在发送出加返回校验
解决方式:
加请求强校验,后端加冗余数据过滤
待测试效果验证~
======
标题:如何保证页面卸载时的上报数据完整性
作者:hugh0524
地址:https://blog.uproject.cn/articles/2019/03/12/1552404978819.html
0 0