首页 > Silverlight > Silverlight启用Assembly Caching之后铁通用户无法访问

Silverlight启用Assembly Caching之后铁通用户无法访问

Silverlight , ,

去年年底的时候,有客户向我们公司反映,他在自己公司内网(铁通ADSL)无法访问我们的Silverlight应用程序,而在他家里(网通ADSL)就可以正常访问。我们其他的客户并没有反映过类似的问题。

问题分析排查

由于他用的是笔记本,在家里和在公司访问时的系统环境是一样的,这样也就排除了系统环境的原因。那只能怀疑是网络环境的问题了。后来在现场使用HTTP Watch调试发现,当Silverlight在下载其中几个缓存程序集的zip包(我们的Silverlight应用程序启用了Assembly Caching)时,HTTP请求被302永久重定向到一个奇怪的IP上。

Silverlight启用Assembly Caching之后铁通用户无法访问

这样,由于zip包和Xap包地址的主机域不同,构成跨域,Silverlight会要求zip包所在的网站提供clientaccesspolicy.xml或者crossdomain.xml文件。而那个奇怪的IP所在网站下根本就没有这两个文件,所以请求失败。进而导致整个程序挂掉。

Assembly Caching程序集缓存

Assembly Caching(又称Application Library Caching)是Silverlight 3的新特性。以前Silverlight都是将所有用到的dll放到一个xap包之中,这样整个xap包会很大,下载相对比较慢。启用Assembly Caching之后,Silverlight工程用到的dll就可以在编译的时候自动打包到各自的zip包中,然后Silverlight在加载Xap包之后会自动下载这些zip包并解压出里头的dll,然后加载到应用程序域中。这样一来可以大大提高程序集下载的并行度,同时也可以使到不同Silverlight程序之间可以利用浏览器缓存而无需重复下载。

Silverlight在加载Xap包之后会去读取xap包中的appmanifest.xaml文件,然后下载该文件中指定的程序集文件。如果程序集文件Url和当前Xap包Url构造跨域(参考Silverlight SDK文档),则Silverlight会向该程序集所在网站的根目录请求跨域策略文件。

为什么会被重定向

这个问题困扰了我们很久。当时我们的第一反应是怀疑网关设置了什么规则。当用户访问特定Url的时候,触发了这个规则,导致HTTP请求被挟持。但是和客户公司网管沟通之后,对方明确表示并没有设置过类似的规则。

直到最近,客户和电信通(率属铁通)的人沟通之后,那边的技术人员说这是由于铁通的缓存加速服务器造成。据说是铁通为了让用户下载更快,就将某些HTTP请求进行重定向。后来电信通的技术人员告诉客户他们已经没问题了,但是他们并没有告知详细的问题所在,到底是由于我们的HTTP请求碰巧符合特定规则,还是怎么回事。也不知道他们是怎么解决的,是只将客户公司的IP列入禁止缓存列表,还是将我们Silverlight应用程序使用的域名加入禁止缓存列表,我们都无从知道。对于我们来说,这并没有真正解决问题。如果将来其他客户也通过铁通访问我们的产品,那么可能还是会出现类似的问题。由于我家里也是铁通的网络,所以我决定自己研究一下到底是怎么回事。

由于铁通那边没有任何可用的技术信息,Google也没有找到有价值的信息,唯一猜测的就是HTTP请求可能符合特定规则然后就被无辜重定向了。因此我只能采用最原始的人肉测试了。尝试不断的调整出问题的Url然后看是否被重定向了来发现规律。修改zip包所在目录,修改zip包文件名,修改zip包后缀,修改IIS的MIME类型,测试不同域名,等等。在历经100多次尝试之后,终于发现了当文件大小超过40K左右,并且后缀名是zip或者rar等常见的下载文件后缀,就会被铁通重定向。而且有时候第一、二次不会被重定向,刷新多几次的时候就才会被重定向。后面一点让我走了不少弯路,多少次我以为找到规律了,最后验证结论的时候还是错了。

o(︶︿︶)o

怎么解决

知道具体问题所在之后,我们几个技术人员就开始讨论如何解决这个问题。由于Silverlight对于缓存程序集打包之后的文件后缀没有要求,不管什么后缀,都会以zip文件流的格式去解析。因此可以修改打包文件的后缀来“逃过”铁通的魔掌。

修改文件后缀也有两种方法。

一种是在部署的时候,通过自动化脚本,修改所有zip文件后缀,然后修改xap包中appmanifest.xaml里头程序集的Url。这种方式的好处是一劳永逸,通用性强,以后部署的时候只需要执行一次脚本即可,其他应用程序可以共用。缺点是脚本编写比较复杂,并且部署的时候需要多加一步。

另外一种方法是将用到的Silverlight系统程序集放到工程底下,然后修改同名的xml配置文件,使其打包的文件使用其他后缀名。好处是这样编译完之后就可以直接部署了,无需执行什么操作,也不需要写脚本。坏处就是首先需要修改所有现有的工程,而且以后如果要开发新的Silverlight应用,也要记得这么做。

不管怎么样,这两种方法都不简单。后来我就想,既然客户可以和电信通联系,为什么我不可以直接和铁通联系呢。我就上网搜了一下北京铁通客户中心,找到申诉通道,填写完整的申述理由。然后第二天又打他们的客服电话去骚扰他们。结果过了两天,申述结果就下来了,“问题已解决”。对方客服还本着能自己动手决不麻烦别人的精神,帮我填写了用户满意度一栏:“非常满意”。

更深层的东西

其实最终解决问题的办法非常简单,就是投诉。我不满意你的服务,我就有权利投诉你。可是为什么一开始没有意识到这种解决办法呢?

我觉得这是和我们接触的社会环境有很大关系。我们潜意识里头已经习惯了各种中国式的流氓。运营商喜欢往你访问的网站中插播广告,访问我自己的博客偶尔还有弹窗广告;上Google搜索技术资料,一不小心点了blogspot的链接就导致Google被重置了,然后就10分钟不可用。没有明文规定告诉你什么是被禁止的,我们只能人肉测试。我们除了接受、适应并绕过这种事实之外还能做什么?也许我们还可以发出几声“中国式的抗议”吧。

言多必封,不多说了。

——Kevin Yang

本博客遵循CC协议2.5,即署名-非商业性使用-相同方式共享
写作很辛苦,转载请注明作者以及原文链接~
如果你喜欢我的文章,你可以订阅我的博客:-D点击订阅我的文章

  1. TD
    | #1

    顶~~

  1. 暂时没有trackbacks.