一、背景
经过 10 多年发展、沉淀,阿里巴巴中文站从最初的单个应用系统发展超过 100 个应用系统,500 个以上域名。
早期有不少域名切换案例,但这次切换跟之前项目规模、复杂度要大许多, 且要求严格,需要一次性全部干干净净的切换。
二、挑战
协调超过 100 个应用系统、几百个域名同时切换,各个应用之间往往有各种依赖关系,一个地方出错很容易引起连锁效应,造成大面故障。所以,在这种情况下,我们必须保证中文站以及各个兄弟部门的业务正常的情况下,完成这个域名切换乾坤大挪移。
同时在商业上,需要保障客户的权益,防止 SEO 流量下降,防止 P4P、外投广告的收益保持稳定,等等,项目组感到压力重大。
三、切换方案
1、切换域名面临的技术挑战
1)一次性整体切换
如果按照应用维度逐一切换到 1688 域,需要考虑 cookie 双域读写和跨域请求问题。cookie 分三类:
a、永久 cookie,保存在用户本地电脑上,比如用户标识,访问行为跟踪,识别是否新用户等。
b、登录状态 cookie(session cookie),全站共享,在主域名下。
c、业务 cookie,各个业务应用读写的 cookie,在子域名或者主域名下。
Web 标准无法实现 cookie 的双域直接读写,只能通过 302 跳转或者内嵌 url 的方式间接实现。但是这种方案对应用浸入性比较大,非常复杂,难以大面积的实施;且即使使用,首 pv 的 cookie 丢失问题同样难以接受。所以,考虑到用户体验和切换效果及实施成本,项目组决定选择一次性整体切换。
2)各应用需要独立修改实施
目前有 150 个左右 web 应用,大约 600 个域名,还有部分数据库保持有模板信息,应用之间的相互依赖关系复杂,很难在同一时刻完成所有应用和数据库内容的修改且一次性发布。所以,必须采取策略保证各应用能够独立发布修改,解除应用之间的改造耦合。
2、方案策略
1)保护罩。给整个中文站所有与外界(用户)交互的应用系统(在系统边界)套上一个保护罩,这个保护罩对内部应用系统的修改实施过程进行保护,使应用的修改发布对外界不影响,这样各个应用之间的依赖关系解耦,各个应用可以逐个独立修改发布,在整个过程屏蔽外界用户的感知,保证在实施过程用户保持在同一个主域名及其子域名(*.alibaba.com)下访问,在实施过程中现有功能不会受到任何影响,网站所有功能照常提供服务。
2)为了保证全套环境——包括应用服务器、数据库、配置服务器、文件系统——在保护罩保护之下,线上(生产)环境支持双模式运行:一个是正式模式(对应域名 _.alibaba.com),正常用户在正式模式下访问;另外一个是测试模式(对应域名 _.1688.com),在测试模式下,保护罩不起作用,测试人员看到的效果跟实际代码一致,这样就可以利用线上全套真实环境进行全站联测,线上系统、配置服务器和数据库可以随时进行修改并订正。
3)待所有应用修改完成,全站线上新域名联测,完成联测之后去除保护罩,实现一次性切换。
3、方案实现
1)全站实施支持双域 cookie 工作改造,支持多套域配置,老域名采用老 cookie 配置,新域名采用新 cookie 配置。
2)web 内容输出增加保护罩,在 web 内容完成渲染输出时对内容以及 http head location 替换(考虑到静态内容替换,在 apache 层替换,需要开发一个 apache replace module)。这个模块支持双模式工作,在正式模式下,对输出的 web 内容(已经修的内容),扫描分析并反向替换回老域名模式,即把内容里面发现新域名的替换回到老域名,因此对用户屏蔽了改变,在实施过程用户不会影响现有功能;在测试模式下不做替换,测试模式下访问返回的内容和已经修改的代码保持一致,这样就可以提供线上全套测试解决方案,且可以逐个应用发布上线,应用之间的依赖完全解耦。
3)双模式支持,除了 AliSession 和 apache replace module 对双模式工作支持之外,apache 配置也需要增加虚拟主机配置来支持双域名访问,保证外部用户用老域名访问,内部测试人员和实施过程中 apache 反向代理、httpclient 方式,新域名能访问。
一次性切换,完成所有联测之后,把 apache 替换模块一次性下线(也可以做成开关模式,但最终需要下线),去除系统和用户之间的感知屏蔽层,实现全站一次性切换。
4)切换之后,所有老域名的访问 301 跳转至新域名。
总体方案设计图
替换工作原理图解
4、补偿方案
无论方案多么完美,难免会有些内容(不包含 url)绕过保护罩泄露出去,比如邮件内容,这些内容不经过 web 服务器 request/reponse 模式出去,因此 apache 替换模块不起作用。如果逐一去封闭各个出口,成本会比较大,而且这类途径泄露出去的内容占比很小,所以采用泛域名方式来解决。如保护罩设计图中的路径 2,所有新域名(新增的 *.1688.com 域名)会泛解析到 static 集群,这个集群做 302 跳转到相应的 alibaba.com 的 url,从而保障了可用性。但是对于先前已经提供了 1688 域名的应用,如路径 3,需要单独采取类似的方案。
5、服务器间的访问保护方案
服务器之间通常存在反向代理,或者通过 httpclient、rmi 等调用方式的数据服务访问,一旦这些访问的域名修改为了对应的 1688 域名,没有提前支持,肯定是有问题故障的(因为域名没开发,服务不可达)。我们采取的方案是,对内部环境新域名提前开放,保证服务器之间通过新域名访问可达。
6、测试模式识别
线下环境直接提供两种模式:正式模式和测试模式。为了把测试模式和正式模式区分开,我们采用在 cookie 下记录一个标志来区分。为了方面使用,开发一个简单页面,测试人员在进入测试模式之前,点击这个页面按钮切换模式,这个页面功能在双域下记录一个测试标记 cookie,apache 根据这个来判断是否属于测试模式。在测试模式下,apache replace module 不做替换,apache rewrite rule 不会外部重定向至 alibaba 域的域名。
四、其他问题解决方案
1、基于 cookie 数据统计跟踪断层问题解决
采取的方案是将老域名的永久 cookie 迁移至新域名。实现很简单,成本也很低,在通用 js(覆盖大部分页面)埋入迁移 js 即可。注意在迁移 cookie 的过程中,有可能改变 cookie 的值,因为 cookie 标准的不一样,对于有些值会加引号,使用方没有兼容的话,很容易产生故障。
2、SEO 流量影响的解决
- 各重要应用重新在百度站长平台,google,bing 的 webmaster 重新验证新的域名权限。
- 重要应用都在百度站长平台网站改版功能中,提交域名切换规则,同时,调整各大搜索引擎爬虫的抓取压力。
- 修改 sitemap 文件生成规则,将 sitemap 文件中的 URL 全部替换成新的 URL,同时实施 sitemap 地址安全化。
- 修改百度开发适配协议,重新调整 URL 的映射关系。
- 对于各应用暴露出去的 RPC 服务,或者 URL 服务,添加到 robots 禁止策略中,禁止各搜索引擎抓取,提升爬虫抓取效率。
- 寻求百度,360,sogou,soso 等搜索引擎帮助,请求搜索引擎算法部门实施域名切换,进行数据归一化,索引更新。(依赖新老域名映射清单,便于搜索引擎算法部门实施域名切换)
3、代码替换工具
首先建立核心映射关系表,梳理域名切换转换关系表格,老 <–> 新域名关系,包含一对一和一对多的关系,包括三级域名升级为二级域名,域名换名称等,后续所有工作都围绕这个表格进行。整个梳理过程相当繁琐,对几百个域名逐一沟通确认。
开发代码替换工具,同时可以提供给替换数据库,这个工具依赖的核心是域名映射列表。
五、总结
通过三大利器(保护罩、替换工具、补充模式)解决了切换存在的各种技术难题和大大降低了切换实施成本,并通过 SEO 优化策略确保切换之后影响尽可能小。
1688 域名切换项目正式上线一周全站业务系统非常稳定,未产生任何重大故障,客户反应也比较平滑,项目非常成功,达到了我们的预期目的,同时还顺带解决了一些历史包袱:
1、静态资源(图片、js、css 等)彻底独立于主域名,迁移至无 cookie 环境,解决了历史包袱,节省大量网络带宽消耗。
2、域名优化改善,包括域名合并,不合理域名清理,域名升级等。
作者简介
冯凌圣,阿里巴巴应用架构师,2004 年底加入阿里巴巴,主导过中文站许多重点项目及应用架构、性能优化,独自研制开发 json 安全解决方案、jmemory(java 版嵌入式堆外内存使用,类似简单 memcached 的嵌入式版本),目前主导阿里巴巴中文站应用架构。
感谢丁雪丰对本文的审校。
给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ )或者腾讯微博( @InfoQ )关注我们,并与我们的编辑和其他读者朋友交流。
评论