当前位置: 首页 > 技术与资源 > 技术分享 > 正文

业务服务质量监控方案:拦截和跟踪浏览器中的HTTP请求

2016-02-19 10:23:31

作者:周春仪新炬网络高级技术专家。


1
 
总体描述
 

 

随着各个企业精细化运营管理的不断深入,业务支撑能力和服务质量也得到持续改进,如何有效提高业务服务质量成为大家关注的重点。业务服务质量的提高,是客户与企业应用之间的直接桥梁。

 

2
 
应用性能监控
 

 

应用服务端监控,即使用apm监控软件,通过监测和分析应用的表现去保证软件应用的良好运行,定位服务端应用的性能质量。一个企业的关键业务应用的性能强大,可以提高竞争力,并取得商业成功,因此,加强应用性能管理(APM)可以产生巨大商业利益。      

 

3
 
主动拨测监控
 

 

使用类似HttpWatch工具,录制业务操作流程,执行定时任务,主动触发url访问,记录业务过程的响应时间,分析网页数据。包括网页摘要、Cookies管理缓存管理、消息头发送/接受、字符查询、POST 数据和目录管理功能、报告输出。

 


   

4
 
使用客户端脚本技术拦截和跟踪浏览器中的HTTP请求
 

 

apm监控软件监控的是服务端中间件应用的性能情况。没有真实反映客户端的响应情况,不同网络的情况也会影响客户使用系统软件的体验。

 

主动拨测访问业务,可以真实反映业务流程的使用质量,定位性能瓶颈。需要模拟用户的操作流程,配置复杂。

 

是否能够监控用户操作游览器的过程记录操作响应的时间?

 

随着互联网应用及 B/S 架构的软件系统的风行,越来越多的基于浏览器的应用得以开发和部署对,已经上线的应用系统进行拦截和跟踪可以方便、快捷地实现很多功能。

 

  • 基于逆向代理服务器的原理实现,逆向代理服务器的实现必须要对既有页面中的一些 URL 进行拦截和改写。

     

  • 现今一些有趣的匿名代理服务器也是根据逆向代理服务器的原理实现的(如 http://www.youhide.com/),这类网站也有 URL改写的需求。 

 

不仅仅是 URL 改写,通过拦截和跟踪技术可以在极小修改或者使用反向代理不修改原网页的前提下为基于 BS 的 Web 应用提供更复杂的页面改写,脚本改写等功能。

 

1、 基本原理

 

如图 1 所示,传统的 Web 访问模型通过浏览器向 HTTP 服务器获取 Web 数据,浏览器将获取的数据进行解释渲染,得到用户的客户端界面。

 

 传统 Web 访问模型

 

而在带有服务器端和浏览器端跟踪和拦截的访问模型中,传统的访问方式发生了变化。服务器端和浏览器端的跟踪和拦截将页面中的拦截对象,在适当的拦截时机进行了拦截变化,导致用户面前的浏览器的解释渲染结果和 HTTP 服务器上的内容存在了逻辑上的差异,而这种差异恰巧是 HTTP Server 所需要的结果,而不方便将差异部署在 HTTP Server 上。 Server trace 可以作为反向代理服务器的一项逻辑功能存在,Browser trace 是通过脚本完成在客户端拦截和跟踪行为。

 

2、服务器端实现和客户端浏览器实现的比较

 

拦截根据位置可以分为服务器端和客户端两大类,客户端拦截借助 JavaScript 脚本技术可以方便地和浏览器的解释器和用户的操作进行交互,能够实现一些服务器端拦截不容易实现的功能。如果将服务器端和客户端拦截融合在一起,可以很好地处理拦截和跟踪问题。

 

服务器端拦截和客户端拦截的功能比较

 

从表 1 可以看出服务器端拦截和客户端拦截具有很强的互补性,服务器端拦截擅长服务器 - 浏览器的通信控制、资源的访问以及批量页面的操作。浏览器端拦截可以依靠 Script 解释器的环境,擅长个体页面的逻辑拦截和跟踪。下面介绍一下客户端拦截的技术实现方案。

 

3、拦截和跟踪的主要方法及其实现

 

(1)主要方法

 

在浏览器端的拦截和跟踪主要是利用 JavaScript 的脚本环境完成,根据笔者的经验,主要寻找并总结了如下的方法。这些方法的使用效果和支持平台可以互相弥补。

 

 

(2)主要方法的实现

 

利用浏览器的 Event

 

 

浏览器的事件也可以很好地用来拦截和跟踪页面。 鼠标和键盘的交互事件这里暂不介绍。比较常用的是 onload,onunload 事件和 Mutation Events 事件。 onload 和 onunload 事件可以作用在 window,frame,img 和 object 等对象上,利用 onload 可以在对象载入前执行一些操作 ,onunload 事件可以跟踪浏览器关闭前执行操作。

 

在浏览器的 Event 中,Mutation Eventsii 是更加重要的跟踪工具之一。 Mutation Events 是 DOM2.0 标准的一部分,目前 Firefox2.x 已经开始支持 Mutation Events, IE6.0 目前尚不支持。 在 IE6.0 中可以是通过使用 onpropertychange 事件及覆盖节点的方法弥补部分的不足。这里重点介绍一下 Mutation Events 。

 

Mutation Event 主要包括了七种事件,如下所示。

 

DOMAttrModified:跟踪 DOM 节点属性的变化。

DOMCharacterDataModified:DOM 节点字符数据的变化。

DOMNodeInserted:DOM 新节点被插入到给定的父节点。

DOMNodeInsertedIntoDocument:DOM 节点被直接或随着祖先节点而插入。

DOMNodeRemoved:DOM 节点被从父节点删除。

DOMNodeRemovedFromDocument:DOM 节点被直接或跟随祖先节点被删除。

DOMSubtreeModified:DOM 元素或文档变化。

 

可以说利用 Onload 事件的拦截,我们基本上解决了静态 HTML 内容的拦截,而对于脚本操作的 HTML 变化,我们就可以通过 Mutation Event 来进行解决。

 

下面类似的实现框架可以用来跟踪 src、action、href 等属性的变化。

 

 

通过 DOMAttrModified、DOMNodeInserted 等事件可以很好地跟踪和拦截 HTML 的变化。只可惜在 IE6.0 平台上还不能支持 Mutation Event,导致在 IE6.0 上进行拦截和跟踪的效果大打折扣。针对此平台,通过覆盖 document.write/DomNode.appendChild/DomNode.insertBefore 等方法和利用 onpropertychange 事件可以有限度地支持拦截和跟踪 HTML。

 

通过 AOP 技术拦截

 

 

针对对象方法调用的拦截,比较成熟的方案是使用 JavaScript 平台下的 AOP 技术。

 

目前,JavaScript 平台上的 AOP 方案主要有 Ajaxpectiii、jQuery AOPiv、Dojo AOPv 等。这些代码库主要功能是给指定对象的指定方法添加 Before, After,Around 等通知,从而达到拦截对象方法调用的目的 , 并且支持正则搜索方法名称。

 

无论 AOP 还是方法覆盖, 都存在一个问题, 就是拦截代码的插入点不能做到很简捷,因为拦截代码的存在位置直接影响了代码的执行效果,因此在使用上还有一定的不方便。另外,针对 IE 平台的 ActiveX 对象,代码库不能很好的发挥功效,这是一些不足的地方。

 

覆盖系统类 / 方法进行拦截

 

 

覆盖已定义的函数是一种比 AOP 更直接的拦截和跟踪脚本调用的方式。

 

其原理是在原函数定义后,调用前通过定义同名函数,达到拦截和跟踪的目的。

 

函数覆盖的适用范围较广,不但可以模拟 AOP 的实现,还可以对非对象函数进行操作。函数覆盖可以根据使用的差异分成若干情况 :

 

覆盖系统定义的函数、对象的方法:覆盖系统定义的函数或方法可以不用顾及代码插入点的问题,大可以将函数覆盖的代码放置在页面的最前边,并参照上面的形式进行操作。但是特别注意在 IE 平台下对 ActiveX 的对象的方法无效。

 

覆盖用户自定义的函数、对象的方法:覆盖用户自定义的函数,对象的方法需要考虑代码插入点的问题。正确的代码插入点的位置应该是在原函数定义之后,调用之前。

 

覆盖构造函数:覆盖构造函数是满足上面两种情况的一种特殊使用形式,跟踪对象创建之后,可以有效地针对对象的需要作出各种特殊的设置。

 

通过动态代理进行拦截

 

 

当在 IE6.0 平台遭遇 ActiveX 对象的时候,如果直接的函数覆盖不能奏效,我们可以考虑通过另外一种办法,即动态代理 ActiveX 对象的方式实现拦截和跟踪。

 

首先我们通过覆盖构造函数的方法,将创建 XMLHttpRequest 对象的过程进行改造。

 

 

我们将构造过程拦截下来后,进行自己的改造,主要操作是创建对象,对象中设置与 ActiveX 对象相同的属性和方法,并且还需要同步属性方法。

 

 

从上面的代码可以看出来,代理对象通过自身的方法模拟了原来 ActiveX 对象的方法。而更关键的属性问题,是通过在函数调用前后的属性同步函数实现的。即:在调用代理内核方法之前,将属性从代理对象同步给内核对象;在内核方法调用之后,将属性从内核对象同步给代理对象。

 

因为 AJAX 对象的属性几乎不被用户写入,故上面的实现只需要单向属性同步,即将内核属性同步给代理属性。对于复杂的应用,可以通过双向属性同步函数来解决属性的代理问题。

 

这种动态代理的方法将 ActiveX 对象像果核一样包裹起来,通过代理对象自身的同名属性和方法给外界提供访问,从而达到跟踪和拦截的目的。

 

通过自代理和 HTML 解析进行拦截

 

 

当代码拦截点需要简单可靠的时候,上面的方法无法很好的满足需求。于是我们需要新的思路来解决代码的拦截点问题。

 

自代理和 HTML 解析是通过拦截原有的 HTTP 通信,通过重新通信获得内容后,在浏览器解析前通过我们自己的代码进行简单解析过滤的方式进行代码处理的方案。

 

首先是拦截原有的解析,重新加载新的内容:

 

 

如果将上面的代码写在一个 js 文件里,然后通过 <script> 标签插入到页面的最开始位置(<HTML> 后面)。

 

在 IE6.0 的浏览器下面,上面的代码因为使用了 XMLHTTP 的同步通信机制,因此代码会阻塞在 comm.send(null) 处,当通信结束得到完整的页面之后,会触发 stop 导致浏览器停止解析,转而执行我们的 processContent. removeMe 的意义在于重新获得的片面中去除这段代码自身,防止无穷迭代。

 

在 Firefox 下,我们需要使用 window.stop 代替上面的 execCommand.

 

当我们抢在浏览器之前拿到 HTML 内容后,我们下面的任务就是分析 HTML。目前尚没有成熟的 JS 分析 HTML 的框架。因此我们可以选择将 HTML 转换成 XML, 然后借助 DOM 进行分析,这样也可以实现我们自己的 HTML 分析方案 。

 

我们可以将 HTML 的页面分析成节点如下的一颗树:

 

节点 { 

     父节点 ;      

     属性个数 ;  

     属性集合 ; 

     子节点个数 ;  

     子节点集合  

 }

 

 HTML 文本分析状态图

 

上图是个简单的 HTML 文本分析状态图,不支持 HTML 的 & 字符串拼接功能。可以反复调用这个模块用来从 HTML 文档中提取字符块生成相应的节点,然后可以利用 JavaScript 的正则表达式提取节点的属性。

 

通过 HTML 文本分析状态图可以得到 HTML 解析的代码,然后得到一个根为 root 的节点。后面对树进行进一步的处理,就可以实现很多拦截功能。比如 function 覆盖。前面讲到的用户自定义函数覆盖会受到代码插入点复杂的影响。如果在这种方法的拦截下,就可以实现分析出 <script> 节点的内容中含有特定的 function 定义,进而替换或者在其后插入新的函数定义,不会造成插入点复杂的结果。

 

4. 小结

 

通过上面的介绍,可以看出发挥 JavaScript 的优势,我们能够很好的控制页面的加载过程。在不需要二进制浏览器插件的情况下,仅仅通过脚本对 Web 内面的逻辑拦截是可行的。这种方法在反向代理、网站的改版重构、以及不方便对原有内容进行直接改动的场合是十分有益的。它能从真实用户使用的角度,监测业务性能质量。

 

上一篇:Oracle 12C InMemory使用
下一篇:优化一致性算法,从学会Raft开始?