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