Author:放翁(文初)
Date:2010/4/2
过年到现在还没有更新过blog,就和年前说的一样,到了淘宝就要真的踏实做实事了(起码Q3前)。和以前在阿软不同的是现在更加关注产品的设计和实现,对于新技术的尝试缺少了一些空间和时间。可以拿程序员对新技术的追求做个类比,就好比结婚前的浪漫,而到了你真的结婚有了家庭和小孩,那需要的是更多的责任感和务实的工作。当然如果生活成为一种生存,那么就失去了意义,如何在责任和浪漫之间找到平衡点,是一个技术人员成长的挑战。我们不可能永远是一个长不大的小孩,也不会是老气横秋的中年男人。有点废话了,言归正传,谈一下这年后短短的一个多月的工作心得,一点分享,一点记录。
系统透明化
去年就加入了淘宝的虚拟小组(稳定性小组),同时在开放平台团队内最大的一个职责也是稳定性。对于客户来说并不关心你的技术实现是如何fancy,对他来说能够快速、稳定、方便的满足他的需求就是一个好网站,一个好系统,一套好服务。因此稳定,高效成为了淘宝主站和开放平台的根本。前两天看了黄裳在infoq的一些关于淘宝技术展望的文章,就两个字“实在”,没有啥潮流的词汇,没有很炫的技术推荐,有的就是如何用最有效的手段满足用户需求。
记得在最近一次稳定小组会议上大家谈到了这些年发展带来的问题,其实我们在解决问题的同时也在不断地引入问题,同时在规模化的驱使下,不断地采用松耦合及去中心化的设计,但是带来的问题就是系统复杂度的不断增加,同时系统间的交互和依赖也变得越来越复杂和混沌。我在Q1的工作计划中,大部分的工作为了一个目标:系统透明化。
系统透明化能够为海量请求的系统带来什么?
1. 实实在在的性能优化。
2. 简单有效的问题排查和定位。
3. 系统风险预警。
4. 有效地系统健康监控和业务健康监控。
过去我们总在线下做各种压力测试,同时对于一些优化策略也都是通过线下来验证,但是实际的业务场景往往会和具体的数据相关,而线下无法做到的就是数据模拟。在开放平台系统基础框架重构以后,首先是采用了管道链的插拔模式,直接通过对当前运行数据的在线分析就可以看出系统消耗的环节,同时加上控制台对集群单台机器的配置推送,这样比对两台不同处理策略的服务器就能够很明显看出性能优化的效果以及后续的改进点。举个例子,在我们业务方需求中要求对某一部分业务数据去掉本地缓存,全部启用纯粹的集中式缓存,我们通过批次的关闭本地缓存,比对了自身系统和外部依赖系统的压力增长情况,当3/4的机群机器采用纯集中式缓存的时候,两方服务器都出现了load较高的问题,因此考虑采用更细粒度的业务数据来决定是否启用本地缓存,满足了用户请求,同时也大大降低了双方的压力情况,同时由于业务数据配置可运行期推送,因此随着压力的增大可以在线调整策略。
在新架构上线后,发现运行一段时间会有“内存泄露”的问题,64位机器最后3个G的内存都被吃光。当时就是担心新架构可能产生一些问题,因此允许系统通过控制台切换新老引擎。线上一台新引擎的服务器跑了一段时候就把内存dump出来,然后拖到线下分析,发现有大量的tomcat的Session被保存在Manager中没有被释放(1.7G),然后通过线下卸载管道做测试,最终发现是由于其中一个管道需要在运行期获取到spring的容器,去掉用了request.getsession().getContext方法,结果容器创建了有效期为30分钟的session,对于平台这么大的访问量,其实这种非内存泄露的问题,也足以使得高压力下OOM。
透明化另一方面就是需要对依赖系统及自身的健康状况有所了解。当前TOP在这方面主要做的工作被定义成为免疫系统,其主要的职责
流程管道化
这些年一直都在谈面向服务,模块化,这些概念。但是就其目标来说,就是希望能够让设计者更多的考虑流程之间的松耦合,无依赖。因为一旦服务之间没有过多的依赖,服务本身没有中间状态,那么任务就可以并行处理,一旦并行处理,那么对于流程的关键路径优化就有很大的帮助。
下面是重构前和重构后的两个流程对比:
老框架流程:
新框架流程:
具体的框架类图如下:
看了以后,可能很多同学会说,其实就那么简单一个设计么,但其实系统的设计目标就是用简单的设计来满足复杂的需求。其实对于开放平台来说,再复杂的业务都是可以抽象成管道,同时大部分情况下都是无状态的服务管道,基于业务的不同需求,管道的执行会有所不同。
这里设计的几个原则:
1. 管道之间无关联性。管道与管道之间完全没有任何关联,因为在管道看来就只有输入和输出的数据流,其他管道对于它来说是透明的。独立性降低业务耦合度,支持运行期变更。
2. 管道之间通过上下文的方式交互数据,减少数据输入带来的适配依赖。
3. 业务处理权及流程中断权交给管道,管道可以通过实现ignoreit来判断是否要处理此次请求,也可以在IPipeResult中设置isBreakPipeChain来主动中断流程。(对于资源回收最好不要交给一个管道执行,因为随时可能因为流程中断而没有被执行到)
4. 管道设计尽量为无状态,线程安全,便于扩展,防止产生资源竞争带来的处理瓶颈。
5. 监控管道执行状况,必要时自动降级卸载管道,保护系统稳定性。
早先考虑是否能够启动线程池来执行管道链,这么做的目标是能够控制超时执行的管道链,避免系统的不稳定性。但最大的问题就是线程切换代价以及线程池的容量问题,因此作罢,改为事后记录降级处理。
安全还是安全
开放平台成立之初,就要面对着安全的问题,主站有很多的约束和限制,但是开放平台成为淘宝对外的窗口,为了业务需要,作了必要的妥协,但是安全方面也是一直在抓的事情。最近就处理淘宝访客应用的问题,有些软件开发者就利用302转跳的方式,在商品或者店铺的页面上留痕迹,来获取访客信息,可谓用尽心思,封一个漏洞找一个漏洞。对于这种转跳来获取访客信息,简单的处理就这些,禁止get请求(由于都是页面图片的get请求转跳,因此无法简单的变成post请求),然后如果是post需要加上动态会话码的校验,最后在加上对于请求的refer检查,来屏蔽这类的问题。不过对于钓鱼网站,真的没有啥太好的处理方式,个人感觉最靠谱的就是写浏览器的插件。
标签化开放
开放平台现在都是数据服务开放,很多场景下会有标签化开放的需求。还是看图说话吧:
剩下的就是基于Map-Reduce的可配置分析引擎的优化,当前支持文件数据源和数据库数据源,支持增量分析和离线一次性分析,分析模型运行期可改变,提供实时的监控预警。太晚了,最后贴一个开放平台的技术当前总体架构图: