置顶随笔
摘要:
Author:文初
Email: wenchu.cenwc@alibaba-inc.com
Blog: http://blog.csdn.net/cenwenchu79/
MemCached Cache在大型网站被应用得越来越广泛,不同语言的客户端也都在官方网站上... 阅读全文
2009年5月7日
昨天在看Cache Client代码的时候,发现在从资源池中获取SocketIO部分代码在高并发情况下效率不高,因此考虑通过一些变通的方式来提高效率,下面说的内容仅仅是当前自己琢磨出来可以部分提高效率的方法,希望看了这篇文章的同学能够有更好的方式或者算法来提高效率。
情景:
Cache Client 的SocketIO资源池是一个两级的Map,具体定义为:ConcurrentMap<String, ConcurrentMap<SockIO, Integer>>。第一级Map以Host作为Key,第二级Map以SockIO本身作为Key,三种SockIO状态(可用,占用,废弃)作为value。之所以采用一个Pool来存储三种状态主要是考虑到在高并发下,多个池之间保持原子性的复杂。
每一次获取可用的SocketIO的操作需要经历:1.遍历Host所在的Map。2.逐个比较状态。3.原子方法获取可用SocketIO。(并发问题所要求的,具体代码可以下载:http://memcache-client-forjava.googlecode.com/files/alisoft-xplatform-asf-cache-2.5.1-src.jar )。
在修改过去的版本里面,首先遍历的过程是一个固定顺序的过程(keyset),这样会导致在高并发的情况下,越来越多的资源申请命中率会下降,因为压力总是落在keyset靠前的那些SockIO上(重复比较)。需要考虑通过什么手段可以提高在高并发下的申请命中率。
思考:
1. 资源申请的越早,被释放的可能性越高,因此是否可以考虑采用更新SockIO最后申请时间来作为后续申请的初步依据。(本身复杂度带来的耗时可能会超过命中率降低带来的损耗)
2. 采用随机数的方式来确定keyset的起始游标,也就不是每次都从keyset第一位开始(可以把keyset看作一个首尾相接的数组)。
3. 在每次资源回收的时候纪录下该资源为可用(当前为每一个Host就记录一个可能可用的资源,简单化操作),作为申请的首选尝试。(尝试不成功在去遍历)。
当前实现了2,3组合,发现效果明显,在500个并发下,每个线程200次操作(一系列动作),压力测试结果如下:
Cache test consume(cache测试总共耗时),average boundle consume(每个线程总耗时),average per request(每个线程每次操作总耗时)
没有作任何改动以前的测试结果:
cache test consume: 11507741, average boundle consume: 57538, average per request :115
采用了2策略以后的测试结果:
cache test consume: 10270512, average boundle consume: 51352, average per request :102
采用了2,3策略以后的测试结果:
cache test consume: 9140660, average boundle consume: 45703, average per request :91
2009年4月28日
服务集成平台5.6的性能测试进入尾声,这期的优化也算告一段落。这次主要的优化工作还是在三个方面:应用服务器(Apache,JBoss)配置,业务流程,Cache Client包(http://code.google.com/p/memcache-client-forjava/ )。这里把过去和这次优化对于Cache的使用作一个经验分享,希望大家能够用好Cache,提速你的应用。
这里还是通过一些点滴的启示来介绍优化的一些心得,很多时候还是要根据具体情况来判断如何去具体实施,因此这里所说的仅仅是在一些场景下适用,并非放之四海皆准的教条。同时也希望看此文的各位同学,如果有更好的思路可以给我反馈,技术在交流中才会有发展。
积少成多,集腋成裘
性能提不上去,多半是在一些容易成为瓶颈的“暗点”(IO,带宽,连接数,资源竞争等等)。Memcached Cache现在已经被大家广泛使用,但是千万不要认为对Cache的操作是低损耗的,要知道这类集中式Cache对Socket连接数(会牵涉到linux操作系统文件句柄可用数),带宽,网络IO都是有要求的,有要求就意味着会有损失,因此积少成多,集腋成裘。服务集成平台是一个高速的服务路由器,其大部分的业务数据,访问控制策略,安全策略以及对应的一些控制阀值被缓存在Cache服务端,因此对于Cache的依赖性很强。每一次对于客户端的性能提升,总会给服务集成平台性能带来不小的影响,但是每一次优化速度后,客户端可以优化的空间越来越小,这时候需要一些策略来配合,提升应用整体性能。当前主要采用了以下几点策略:
1. 从数据获取角度来做优化,采用本地数据缓存。(因为大家的应用需要能够线形扩展,支持集群,所以才不使用应用服务器本地缓存,但是在某些缓存数据时间性不敏感或者修改几率较小的情况下,可以采用本地缓存结合集中式缓存,减少对远端服务器访问次数,提升应用性能)。
Cache Client的IMemcachedCache 接口中的public Object get(String key,int localTTL)方法就是本地数据缓存结合远程Cache获取数据的接口。具体流程参看下图:
2. 从数据更新角度,采用异步数据更新。(即不等待数据更新结果,直接进行其他业务流程)。这类操作使用场景比较局限,首先数据不会用作判断(特别是高并发系统中的阀值),其次不需要返回结果作为后续流程处理输入(例如计数器),时时性要求比较低。(这类操作其实是采用了集群数据传播的一种策略,原先对于集群中所有节点都想即时传播到,但是这样对于性能损失很大,因此采用key对应的主Node采用即时设置数据,其他的通过后台任务数据传播来实现,由于key对应的主Node是数据第一操作和读取节点,因此这类数据传播操作时时性要求较低,适合这样处理)。具体接口参见Cache Client 使用文档。
3. 一次获取,多次使用。这点和系统设计有关,当前服务集成平台的安全流程是链状的,一次请求会经历很多安全拦截器,而在每一个安全拦截器中会根据情况获取具体的业务数据或者流程控制策略等缓存数据,每一个安全拦截器都是彼此独立的,在很早以前是每一个安全拦截器各自在需要数据的时候去远程获取,但是压力测试下来发现请求次数相当多,而且好些重复获取,因此将这些业务数据作为上下文在链式检查中传递,按需获取和设置,最大程度上复用了数据。(其实也是一种减少数据获取的方式)。
4. 规划好你的Cache区。有些同学在使用Cache的时候问我是否有什么需要注意的,我觉得在使用Cache之前,针对需要缓存的数据需要做好规划。那些数据需要放在一个Cache虚拟节点上,那些数据必须分开放。一方面是根据自己业务系统的数据耦合程度(未来系统是否需要合并或者拆分),另一方面根据数据量及读写频繁度来合理分配(毕竟网络IO还是稀缺资源)。当然有时候业务系统设计者自己也不知道未来的发展,那么最简单的方式给Key加上前缀,当前可以合并,未来也可以拆分。同时数据粒度也需要考虑,粒度设计太小,那么交互频繁度就会很高,如果粒度太大,那么网络流量就会很大,同时将来业务模块拆分就会有问题。
巧用Memcached Cache特有接口
Memcached Cache提供了计数器一整套接口和add,replace两个接口。这些特有接口可以很好的满足一些应用的高并发性处理需求。例如对于资源访问次数控制,采用Cache的计数器接口就可以实现在集群中的数量控制,原本通过Cache的get和put是无法解决并发问题的(就算是本地缓存一样),这就是一组原子操作的接口。而Add和Replace可以满足无需通过get方法获取内容,就可以对于key是否存在的不同情况作出相应处理,也是一种原子性操作。这些原子操作接口对于高并发系统在集群中的设计会很有帮助。
Cache Client Cluster
Memcached Cache是集中式Cache,它仅仅是支持将数据能够分片分区的存储到一台或者多台的Cache Server实例中,但是这些数据并没有作冗余,因此任何一个服务实例不可用,都会导致部分缓存数据丢失。当然很多人采取持久化等方式来保证数据的完整性,但是这种方式对于效率以及恢复的复杂性都会有影响。
简单的来想,为什么不把数据在多保存一份或者多份呢,当其中一份不可用的情况下,就用另外一份补上。这就是最原始的Cache Client Cluster的构想。在这里具体的设计细节就不多说了,主要说一下几个要点,也让使用Cache Client Cluster的同学有大致的一个了解。
先来看看Cache Cluster的结构图:

这张图上需要注意四个角色:Application(使用Cache的应用),Cache Cluster(Cache配置的虚拟集群),Cache Node(Cache的虚拟节点,在同一个Cluster中的Cache Node数据保持完全一致),Cache Instance(Cache虚拟节点中实际包含的Memcached Cache服务端实例)。
应用仅仅操作Cache Node,不了解具体数据存储或数据获取是操作哪一个Cache 服务端实例。(这点也就是Memcached Cache可扩展性的基础设计)。Cache Cluster又将多个Cache Node组成了虚拟的集群,通过数据冗余,保证了服务可用性和数据完整性。
当前 Cache Client Cluster主要有两种配置模式:active 和 standby。(这里是借鉴了硬件的名词,其实并不完全一样,因为还是考虑到了效率问题)
Cache Client Cluster主要的功能点:
1. 容错。当被分配到读取或者操作数据的Cache虚拟节点不可用的情况下,集群其他节点支持代替错误节点服务于客户端应用。
2. 数据冗余。当操作集群中某一个Cache虚拟节点时,数据会异步传播到其他集群节点。
3. 软负载。客户端通过对操作的key作算法(当前采用简单的key hash再取余的方式)选择集群中的节点,达到集群中节点简单的负载分担。同时也由于这种模式,可以使得key都有默认的第一操作节点,此节点的操作保持时时更新,而其他节点可以通过客户端异步更新来实现效率提升。
4. 数据恢复。当集群中某一节点失效后恢复时,其数据可能已经完全丢失,此时通过配置成为Active模式可以将其他节点上冗余的数据Lazy复制到该节点(获取一个复制一个,同时只支持一个冗余节点的数据获取(不采取遍历,防止低效))。
Active模式拥有1,2,3,4的特性。Standby模式拥用1,2,3特性。(其实本来只考虑让Standby拥有1特性)。未来不排除还会有更多需要的特性加入。Active在key不存在的情况下会有些低效,因为会判断一个冗余节点是否存在内容,然后决定是否修复当前节点。(考虑采用短期失败标示之类的,不过效率不一定高,同时增加了复杂度)
运行期动态扩容部署
Memcached cache客户端算法中比较出名的是Consistent Hashing算法,其目的也就是为了在节点增加或者减少以后,通过算法尽量减小数据重新分布的代价。采用虚拟节点,环状和二叉树等方式可以部分降低节点增加和减少对于数据分布的影响,但是始终还是有部分数据会失效,这点还是由于Memcached Cache是集中式Cache所决定的。
但如果有了Cache Cluster的话,数据有了冗余,就可以通过逐步修改集群中虚拟节点配置,达到对于单个虚拟节点的配置动态扩容。
支持动态部署前提:
配置文件动态加载。(配置文件可以在Classpath中,也可以是Http资源的方式)通过Cache Client 中Cache Manager可以停止Cache 服务,重新加载配置文件,即时生效。
当前动态部署的两种方式:
1. 修改集群配置中某一套虚拟节点的服务实例配置(socketPool配置),增加或者减少后端数据存储实例。然后动态加载新的配置文件(可以通过指定远端的http配置作为新的配置文件),通过集群的lazy的修复方式,逐渐的将数据从冗余节点复制到新的节点上来,最终实现数据迁移。
2. 修改集群配置中某一套虚拟节点的服务实例配置(socketPool配置),增加或者减少后端数据存储实例。然后动态加载新的配置文件(可以通过指定远端的http配置作为新的配置文件),在调用Cache Manager主动将数据由某一虚拟节点复制到指定的集群中,实现数据批量迁移,然后根据需要看是否需要修改其他几套虚拟节点配置。
存在的问题:
1. 当前没有做到不停止服务来动态部署。(后续考虑实现,当前将编译配置和重新启动服务器的工作节省了)
2. 不论是lazy复制还是批量数据迁移,都是会将原本有失效时间的数据变成了无失效时间的数据。(这个问题暂时还没有一种可行的高效的方式解决)
后话
性能优化这点事还是那句老话,需要了再去做也不迟。同时如果你开发的是一个每天服务访问量都是上亿,甚至更高的系统,那么有时候斤斤计较会收获不少。(当然是不影响系统本身业务流程的基础)。
Cache客户端自从作为开源放在Google上也收到了不少朋友的支持和反馈,同时自己业务系统以及其他部门同学的使用促使我不断的去优化和满足必要的一些功能扩展(但是对于Cache来说,还是那句话,简单就是美,高效是使用Cache的最原始的需求)。
当前Cache Client版本已经到了2.5版本,在Google上有详细的Demo(单元测试,压力测试,集群测试)和说明使用文档。是否速度会慢于其他Memcached客户端,这不好说的很绝对,反正大家自己拉下去比较一下看看就知道了,当然为了集群和其他的一些必要的附加功能还是做了一些性能牺牲。
项目地址在:http://code.google.com/p/memcache-client-forjava/
在首页的右侧有demo,doc,binary,src的链接,直接可以下载使用和察看。希望对需要的同学有帮助。
2009年3月11日
写blog已经快两年了,起初仅仅是为了自己“备个案”,结果慢慢演变成为了“分享成瘾”。前几天一个朋友给我的blog留言,谈到希望在新年里能够看到的不仅仅是我对技术的分享,更希望能够看到对于技术学习、职业发展的规划。因此想到了写一点什么分享一下自己这些年的一点点“收获”,周星驰的喜剧之王里面说到他是一个演员(虽然被叫做跑龙套的),我想我,就一个写代码的。
爱这行
从事任何行业都一样,只有真正的爱上了这份工作,才会投入热情,才会在顺境中自我警醒,在逆境中寻找突破。这个行业的竞争很激烈,你停下来走,别人就立刻会跑步超过你,没有对这一行业的一种热情,就很难在困境中保持一种执着的态度坚持到底。
踏踏实实“扎马步”
今天无意中看了“校长”的“程序员&司机”,其中谈到了关于程序员速成的问题。其实速成班毕业的 “系统杀手”早已在遍布大江南北,只是在互联网时代,互联网的应用型软件生命周期越来越短,业务驱动主导的情况下,这种速成方式看起来反而提高了企业生产效率。但这样的人才也就只能写几个Facebook上的插件应用或者iGoogle上的Gadget,真的要出Google,Amazon,Yahoo改变互联网世界的企业,还是需要踏踏实实先学“扎马步”的人。
很多在学校的同学或者刚刚毕业的朋友都看什么热门学什么,Spring,AJAX,Hibernate等等,又有多少人在看Spring之前把J2SE的NIO,XML,Collection等先好好学习一下,在看AJAX之前把Http协议、DTD、XML Schema好好看一下,在学习Hibernate以前先把J2EE事务规范搞清楚。Java最大的好处就是开源,能够让人们站在更高的起点来作出更多的创新,但是对于学习者来说,不了解自己站在什么上面的时候,可能摔下来会很痛。在用的时候多问一些为什么,在遇到问题的时候多找找原因,在了解以后多提出一些优化的方案,这样才会进步的更快,走的更远。
记得我前一阵子回家的时候和妈妈聊起最近的工作,虽然妈妈不太明白,但是也知道我现在做的东西技术含量比较高,嘱咐我“千万不要什么都教给自己的同事,徒弟带出就不要师傅了”(这当然是老一辈的观念了)。我和她说:“不要担心,这种学的会的不教迟早也会,学不会的教了也学不会”。其实这里说的学的会的就是技术,而学不会的就是经验和能力。这个行业的人在日积月累过程中并不会去比较掌握的知识面有多广多深,毕竟这行业更新很快,其实能力强的人在多年的学习中就积累了很多的找问题,分析问题,总结问题,提出建议,发掘创新的能力,这些才是这行业人在发展中最宝贵的财富,也是一个人成长的标志。开始的过程中,踏踏实实地“扎马步”,了解一些最基本的知识,那么上层技术的发展对于他来说仅仅只是一个短暂的学习过程,甚至可以触类旁通。因此还是要奉劝每一个新入行的同学,踏踏实实,静下心来做技术,就算工作安排得都是一些浮躁和重复的工作,用高效的方式来结束那些重复劳动,多留一些时间给自己打基础。
逆境养兵、顺境攻城掠地
普通人的工作经历通常都是起伏不定的,一个人的能力是否能够得到体现,不仅仅靠自己的努力,有时候也需要“天时”、“地利”。马云比较有名的一句话:“今天很残酷,明天更残酷,后天很美好,但是大多数人死在明天晚上,看不到后天的太阳!!!”,其实也在说明一件事,就是很多时候需要一种坚持的精神才能得到宝贵的机会。
今天是我进入阿里巴巴满3年,这3年让我感触很深的是:1.逆境不要气馁,厚积薄发。2.顺境不要懈怠,一股作气,把握机会展现自己最大的能力。3.在逆境和顺境的转换过程中,创造机会,不要坐等机会,要学会不在其位,也谋其职。最后一点就拿我自己的亲身经历来说,我原来就职于一家通信公司,因此对于互联网应用的开发和架构设计要比很多人弱,进入阿里巴巴以后工作了半年(主要作业务开发),正好阿里软件创立,当时被分配到了阿里软件第一个产品负责客户模块,当时的应用是通过MDA框架配置搭建的,开发人员很大程度上不需要自己做太多的编码,但是这个平台并没有搭建过如此复杂的大型应用,因此存在着不少问题,当然这些问题都是通过业务产品线的人反馈给平台部的人,当时平台部门人员很少,但是却要修复和完善诺大一个平台,因此常常搁置开发人员的反馈。当时在自己工作之余就琢磨和研究平台,同时跟踪调试平台,最后直接给出解决方案,逐渐的就融入到了平台开发中,最后被吸收到了平台部门,进入平台部门以后遇到了两位很好的老大,根据我的特质给我安排了研究和学习的工作。接下去就是不断地参与阿里软件各个基础平台的构建,核心技术的研究和探索,找到了兴趣和工作的最佳结合点。因此,当你困惑的时候首先不是去抱怨,而是审视一下自己是否还有作的不够的,是否还有可以提升的空间,多给自己制造一些机会,也许我们不用等到后天,也不会死在明天夜里,明天早晨我们就看到了太阳。
海纳百川、冰冻三尺
很多朋友可能听老师或者前辈也说过类似的话,就是作为一个技术人员要广也要钻。就好比现在很多人都要DB Scale out,同时也要Scale up。我从自己的角度来说一下广和钻的看法。广:1.要有容人之量。(很多时候程序员最大的毛病就是喜欢在技术上比较,未尝不是好事,但是一个人的能力总归有限,多看看别人的,多听听别人的,也许能够让自己少用时间获得更多的收获,特别是自己战友的声音)2.触类旁通,多问个为什么,多跨过界去学习。在阿里巴巴,PD、SA、DBA、UI等等职位各司其职,作为开发的我们其实也应该去了解如何去画Use Case,如何假设服务器和应用环境,如何写一些略微复杂的SQL,了解一些DB的特性,如何能够简单的作出一些基础的页面,使用简单的css来美化一下门面。这些就是需要多跨过界,多虚心的去学习。钻:1.本职工作技术一定要扎实,每作一个技术点就要把技术吃透,同时延伸开来,发掘更多的技术亮点。2.多接触新鲜事物,但是有选择的去了解,有目的的去学习和实践(目的的源泉就是工作的需求)。3.学会分享,一个人自己搞懂一个技术很容易,一个人要把他熟悉的技术写下来就会发觉原来自己还有那么多没有搞清楚,一个人如果要把写下来的东西宣讲给别人听,他就会发现,原来写下来的仅仅是那么一小块,因此学会分享,从自己了解,到记录分享,到演讲传播就是一个不断深化和广化的过程。个人觉得小公司锻炼人(啥都自己干),大公司培养人(该干的要干好),因此自己常回头看看自己在广和钻上的不足,可以让自己进步的更快,学的更全面。
学中医积累经验,学西医寻找突破
中医以对人体经络血脉了解为基础,通过望闻问切来寻找病理根源,行医年限越久,找问题解决问题的经验越强。西医以科学技术为手段,通过试验化的方式不断寻找突破,并且将成果积累并且传递给更多的人,但是否年限越久越有能力,或者是使用得器材越广越资深,这点全要看个人对于医术的理解,如果仅仅停留在对器械的使用和对成果的依赖,那么只会成为一个庸医。当然这里绝对没有对中西医的差别化或者评价,仅仅要说明的是,在手段丰富的情况下,容易忽视了本质,只看到了皮毛,积累的时候多一些追根溯源,站在别人的成果上才更踏实,因此在对经验积累上向中医多学一些,在寻找突破,传播技术上多学一点西医的风格。不过说到低,还是要看学习的人,静的下心,沉得住气,才会有积累,才会有突破.
不做一个纯粹的“技术人员”
不做一个纯粹的“技术人员”,其实也就是说要培养自己多方面的能力,我仅仅把自己想到的一些点列出来说说:
1. 项目产品化的思想。现在就算在学校里面给导师作项目都讲究一个商业价值,更不要说在企业里工作。作为一个开发或者架构师最重要的就是要有产品化的概念,这也是项目是否成功的关键。软件的目的是为人服务,如何服务的好,那就要以一个产品的思路去做项目,而不是作为实验室的实验品,为客户提供好服务就会给公司带来商业价值,对自己的工作也会有很好的肯定。这是一个良性循环,反之则是恶性循环(多赢变成多输)。如何做到产品化,首先就是需要去了解需求,而不是布置需求,其次就是设计时多听取一些不同角色的意见,最后就是在客户的反馈过程中反省。
2. 多一些设计,少砌两块砖。代码写的再好,其实也只是用砖块砌墙砌的比较好罢了,这年代已经不会为了节省两块砖而给一个优秀工作者了,同时技术的日新月异,总是摆弄技巧,学习花拳绣腿已经跟不上时代了。多了解一些行业背景,多参与一些架构设计,将业务设计用良好的架构体系来实现,那才是一个称得上有能力的技术人员。
3. 学会前瞻,学会自己找事。记得我刚进平台组,最不适应的就是我的老大基本不太给我布置太详细的任务,这就好比进入大学,老师不给作业,自己反而心里没底了,其实自己找事的过程就是一个自己学习的过程,当我一天下来感觉没干什么,没学到什么,心里就开始发虚。如何能够前瞻性的去选择一些目标,如何对现有情况提出一些创新和建议,都是一种更高能力的要求。现在SIP组也是一样,在我们这个组里虽然现在每周还是布置一定工作,但是我对其他两个同学的要求也是希望能够有前瞻性,学会发现问题,预防问题,更甚者就是提出创新。当你具备了这种环境的时候,你就需要锻炼自己的能力了。
4. 做个让老大放心的人。这点也许很多人和我一样在业务上很早就让老大觉得可以安心睡觉了,但是其实另一方面,如何在商业角度看问题,如何培养新人,如何协调部门合作等等,都会让你的老大更加安心。另一方面来看,其实在这些能力的培养过程中,你不再局限于业务水平的提升,让自己在更多方面更加成熟。
六脉神剑
今天是我进入阿里巴巴3年整。在阿里巴巴有个说法,只有在阿里巴巴工作了3年,才能算是一个真正的阿里人,因为理解阿里巴巴的文化,需要三年时间的沉淀。这里就从一个写代码的角度分享一下阿里巴巴的六脉神剑文化。
客户第一:如果你是做架构的,作平台的,作开发工具的,那么客户就是和自己一样的开发者,多学习一下开源项目的精神,多从使用者角度去考虑问题,那么你的东西才会被更多的人认可和使用,永远不要去做一个“玩具”的开发者。如果你是做产品的,那么就多听,多想,多问,永远不要急着去写代码。
拥抱变化:敏捷开发的基本原则。互联网应用尤其如此,不要害怕变化,在需求和架构之间找到平衡点(说起来比较容易^_^)。
团队合作:一个人的力量始终有限,分享,交流,合作能够让自己事半功倍,学的更多,看得更远。
诚信:说到就要做到,做了就要做好,做软件开发一样也需要有责任感,贴满狗皮膏药的代码上如果注释是你的名字未来也会给你蒙羞。踏踏实实地用心去写代码,去设计架构,不经意间得到的要远远比那么一点工资来的多。
激情:还是那句话,你如果不爱这行,乘着年轻赶快转行。
敬业:专业执着,精益求精
很感谢各位能看完这篇感受分享,以上都仅仅是个人的一点感受,能够引起共鸣那么证明我们的经历很相似,如果能够给到你一点帮助,那写这些就真的有意义了。不论你在别人眼里是一个资深架构师还是开发人员,其实如果你爱这个行业的话,你应该就是一个写代码的,但是每个人的经历都是一本“写代码的自我修养”,珍惜自己的选择,让自己在兴趣和工作中找到最佳结合点。
2009年3月4日
今天看了“Database Sharding at Netlog, with MySQL and PHP”一文,和去年我们讨论扩展的思路很类似(不过这种分布式扩展,计算,存储的思路都很类似),但是这片文章的作者是在日益爆炸式增长的用户数据下实践的分享,因此这里将文中的一些思想记录下来分享一下。
Netlog拥有4000万活跃用户,每个月有超过5000万的独立用户访问网站,每个月有5亿多的PV。数据量应该算是比较大的。作者是Jurriaan Persyn,他从一个开发者角度而非DBA或者SA角度来谈Netlog是如何通过数据切分来提高网站性能,横向扩展数据层的。原文在:http://www.jurriaanpersyn.com/archives/2009/02/12/database-sharding-at-netlog-with-mysql-and-php/
首先,还是先谈到关于数据库在数据日益庞大的情况下一个演变过程。
第一阶段:读写同在一台数据库服务器

第二阶段:读写分离(可以解决读写比例均衡或者读居多的情况,但是带入了数据复制同步的问题)

第三阶段:部分数据独立部署结合读写分离。(部分数据根据其业务独立性情况,可以将所有的数据独立存储到数据库服务器,分担数据读写压力,前提是要求数据具有较高的业务独立性)

第四阶段:数据分拆结合读写分离(三阶段的增强)

第五阶段:问题出现,分拆也无法解决数据爆炸性增长,同时读写处于同等比例。

解决问题两种方式:DB Scale up ,DB Scale out。前者投入以及后期扩展有限,因此需要进行数据切分。

上图就是将photo的数据切分到了10台数据库服务器上。
切分数据的两个关键点:
1. 如何根据存储的数据内容判断数据的存储归属,也就是什么是内容的分区主键。
2. 采用什么算法可以根据不同的主键将内容存储到不同的分区中。
分区主键的选择还是要根据自身的业务场景来决定,Netblog选择的是用户ID。
采用什么方式将分区主键映射到对应的分区可以通过以下四种方式:
1. 根据数据表来切分。(前提就是数据独立性较强,和前面提到的三阶段类似)
2. 基于内容区间范围的分区。(就好比前1000个用户的信息存储在A服务器,1000-2000存储在B服务器)
3. 采用Hash算法结合虚拟节点的方式。(这类在memcached等等分布式场景中最常见,其实也是一个难点),缺点就是在于动态增加存储节点会导致数据部分或者全部失效。
4. 目录式的分区。最简单也是最直接的方式,key和分区的对应关系被保存,通过查找目录可以得到分区信息。适合扩展,就是增加查询损耗。
如何将数据分布的尽量均匀,如何平衡各个服务器之间的负载,如何在新增存储机器和删除存储机器的时候不影响原有数据,同时能够将数据均摊,都是算法的关键。在分布式系统中DHT(Distribute Hash Table)被很多人研究,并且有很多的论文是关于它的。
数据的横向切分给应用带来的问题:
1. 跨区的数据查询变得很困难。(对于复杂的关联性数据查询无法在一个请求中完成)
2. 数据一致性和引用完整性较难保证。(多物理存储的情况下很难保证兼顾效率、可用性、一致性)
3. 数据分区之间的负载均衡问题。(数据本身的不均衡性,访问和读写的不均衡性都会给数据分区的负载均衡带来困难)
4. 网络配置的复杂性。(需要保证服务器之间的大数据量频繁的交互和同步)
5. 数据备份策略将会变得十分复杂。
解决这些问题当前已经有的一些开源项目:
1. MySql Cluster,解决读写分离问题已经十分成熟。
2. MySql Partitioning,可以将一个大表拆分为很多小表,提高访问速度,但是限制与这些小表必须在同一台服务器上。
3. HSCALE和Spock Proxy都是建立与MySql Proxy基础上的开源项目,MySql Proxy采用LUA脚本来进行数据分区。
4. HiveDB是MySql分区框架的java实现。
5. 另外还有HyperTable,HBase,BigTable等等。
Netblog几个需求:
1. 需要灵活的可扩展性。对于存储增加减少需要能够动态的及时实施,因为数据量增长很快,如果策略会导致数据失效或者部署需要重新启动,则就不能满足需求。
2. 不想引入全新的数据层和与原有系统不匹配的抽象层,因为并不是所有数据都需要切分,仅仅在需要的情况下通过API的方式来透明切分数据。
3. 分区的主键需要可配置。
4. 需要封装API,对开发人员透明数据切分的工作。
Netblog Sharding的实现

上图就是Netblog的Sharding的结构图,主要分成了三部分:Shard,Sharddb,Sharddbhost。Shard就是一个表,里面存放了部分用户数据。Sharddb是一个表的组合就像一个虚拟的DB。Sharddbhost是具体的存储分区。Shard,Sharddb可以根据负载的情况被移动到不同的host中去。
对于Shard的管理,Netblog采用的是目录查询的管理方式。目录信息也存储在MySql中,同时会通过互备,Memcache,集群来确保安全性和高效性。
Shard Table API采用了多一层的映射模式来适合各种不同属性的查询情况。数据和记录在数据库中存储除了UserID以外还有对应的ItemID,ItemID的作用就是定义了具体获取数据的字段信息,例如关联照片表时,ItemID就是PhotoId,关联视频表时,ItemID就是videoID。
一个获取用户id为26博客信息的范例:
1.Where is user 26?
User 26 is on shard 5.
2.On shard 5; Give me all the $blogIDs ($itemIDs) of user 26.
That user's $blogIDs are: array(10,12,30);
3.On shard 5; Give me all details about the items array(10,12,30) of user 26.
Those items are: array(array('title' => "foo", 'message' => "bar"), array('title' => "milk", 'message' => "cow"));
对于Shard的管理Netblog采取的措施主要有这些:
1. 服务器之间的负载均衡根据用户数,数据库文件大小,读写次数,cpu load等等作为参数来监控和维护。根据最后的结果来迁移数据和分流数据。
2. 移动数据时会监控用户是否在操作数据,防止不一致性。
3. 对于数据库的可用性,采用集群,master-master,master-slave复制等手段。
最后通过三种技术来解决三个问题:
1. Memcached解决shard多次查询的效率问题。
根据上面的范例可以看到,一次查询现在被分割成为了三部分:shard查询,item查询,最终结果查询。通过memcached可以缓存三部分内容,由前到后数据的稳定性以及命中率逐渐降低,同时通过结合有效期(内容存储时效)和修改更新机制(add,update,delete触发缓存更新),可以极大地解决效率问题。甚至通过缓存足够信息减少大量的数据库交互。
2. 并行计算处理。
由于数据的分拆,有时候需要得到对于多Shard数据处理的结果汇总,因此就会将一个请求分拆为多个请求,分别交由多个服务器处理,最后将结果汇总。(类似于Map-reduce)
3. 采用Sphinx全文搜索引擎解决多数据分区数据汇总查询,例如察看网站用户的最新更新情况或者最热门日至。这个采用单独系统部署,通过建立全局信息索引,来查询数据情况。
以上是技术上的全部内容,作者在最后的几个观点十分值得学习,同时也不仅仅限于数据切分,任何框架设计都可以参考。
“Don't do it, if you don't need to!" (37signals.com)
"Shard early and often!" (startuplessonslearned.blogspot.com)
看起来矛盾的两句话,却是说出了对于数据切分的一些考虑。
首先在没有必要的情况下就不要考虑数据切分,切分带来的复杂性直接影响可用性,可维护性和一致性。在能够采用Scale up的情况下,可以选择Scale up降低框架复杂度。
另一方面,如果发现了业务增长情况出现必须要扩展的趋势,那么就要尽早着手去实施和规划扩展的工作,并且在切分和扩展过程中要不断地去优化和重构。
后话:
其实任何架构设计首要就是简单直接,不过度设计,不滥竽充数。其实就是要平衡好:可用性、高效性、一致性、可扩展性这四者之间的关系。良性循环、应时应事作出取舍和折中。用的好要比学会用更重要,更关键。
2009年3月3日
目标:
根据四方面的配置调整,观察SIP5.5在高并发下的性能情况。
由于SIP接收的请求都是服务型处理请求,因此认为Apache+Jboss只会带来多余的转发损耗,所以正好这次也作一个验证,看看Apache+JBoss是否不适合于这种纯动态服务请求的情况。
四方面环境比较:
1. JBoss APR模式与Http1.1模式性能差异。(确切来说应该是JBoss内置Tomcat采用APR的情况)。
2. 是否采用Apache+JBoss和Apache不同的转发模块带来的性能差异。
3. Memcached Client版本优化后对性能影响。
4. ISP有不同延时对于SIP的性能影响。
前置条件:
SIP版本5.5,并发用户600,ISP默认耗时20ms,Apache配置和JBoss WebContainer配置,一些优化配置参见附加信息。
最终结果:
SIP采用Apache(Mod_jk)+JBoss(APR)+Cache2.4.2,具体配置参见附加信息。
测试结果表格:
详细的测试报告可以参看:http://spreadsheets.google.com/pub?key=pcsQ9Wm01cIEjjQcistPNDg
JBoss配置差异测试比较:
|
Apache(2.0.52)配置
|
JBoss(4.2.1)配置
|
Cache Client Version
|
TPS
|
TPS区间
|
|
无
|
APR
|
2.4.2
|
1705
|
1600-1900
|
|
无
|
HTTP1.1
|
2.4.2
|
1615
|
1550-1700
|
|
Mod_jk(1.2.27)
|
HTTP1.1
|
2.4.2
|
2090
|
1800-2800
|
|
Mod_jk(1.2.27)
|
APR
|
2.4.2
|
3223
|
3200-3400
|
补充:
配置成为Http1.1模式的两种情况下,测试结果TPS波动频率很高,在Mod_jk模式下波动幅度也很大。
1. 可以证实在非APR模式和高并发的情况下Web容器处理请求能力不稳定,同时也直接影响到了SIP的性能。
2. 在测试中发现不采用APR模式的情况下,Web容器会消耗大量的socket连接通道。
Apache模块差异测试比较:
|
Apache(2.0.52)配置
|
JBoss(4.2.1)配置
|
Cache Client Version
|
TPS
|
TPS区间
|
|
无
|
APR
|
2.4.2
|
1705
|
1600-1900
|
|
Mod_jk(1.2.27)
|
APR
|
2.4.2
|
3223
|
3200-3400
|
|
Weblogic.so
|
APR
|
2.4.2
|
1033
|
350-1400
|
补充:
Weblogic.so模块是以前系统遗留的http请求转发模块。在测试过程中Weblogic模块的测试中波动频率和幅度都很大。根据测试结果可以看出:
1. 在APR模式下,Apache+JBoss对于SIP这种无静态资源访问,纯API性质的服务来说依旧会有比较好的优化效果,特别是在接受请求环节。(不论是TPS还是TPS波动区间和频率都有很好的表现)
2. Weblogic.so这个模块性能绝对不行,稳定性极差。
Cache客户端版本差异测试比较:
|
Apache(2.0.52)配置
|
JBoss(4.2.1)配置
|
Cache Client Version
|
TPS
|
TPS区间
|
|
无
|
APR
|
2.4.2
|
1705
|
1600-1900
|
|
无
|
APR
|
2.4
|
1615
|
1550-1700
|
|
Mod_jk(1.2.27)
|
APR
|
2.4.2
|
3223
|
3200-3400
|
|
Mod_jk(1.2.27)
|
APR
|
2.4
|
2485
|
2650-2800
|
补充:
2.4.2和2.4版本在单独测试的环境下:500并发用户,每个并发用户1000次get和set,性能相差40%左右。
上面测试结果可以看出:
1. 在无apache时,性能有所提升,但不明显,而在有apache时,性能大幅提升,证明在无apache的情况下,memcache客户端已经不是性能瓶颈,因此替换版本效果不大,在http请求处理性能大幅提升的情况下,memcache客户端性能优化的优势就得到了体现。
2. 在测试中也发现Apache + JBoss波动频率和区间都小于其他几个测试情况,图形十分平稳,证明处理请求不是系统瓶颈。
ISP响应时间差异测试比较:
|
Apache(2.0.52)配置
|
JBoss(4.2.1)配置
|
Cache Client Version
|
ISP响应时间(ms)
|
TPS
|
TPS区间
|
|
Mod_jk(1.2.27)
|
APR
|
2.4.2
|
20
|
3223
|
3200-3400
|
|
Mod_jk(1.2.27)
|
APR
|
2.4.2
|
110
|
|
|
|
Mod_jk(1.2.27)
|
APR
|
2.4.2
|
900
|
|
|
测试优化总结:
1. 不要认为内存使用无关性能。现在很对开发者认为内存申请分配是由gvm来管理,但是内存是否合理使用很可能会影响互联网应用的高并发下性能。GC带来的系统短暂停滞会在高并发下影响性能。
2. 使用java的方法需要有足够的“理由”和“度”。Java在1.5以后对concurrent方面做了很不错的支持,但是这些并发处理毕竟会消耗资源,因此在能够避免频繁使用的情况下尽量优化流程。在一些简单的场景下,是否有必要使用一些比较耗时的方法,例如split,用起来很方便,但是在设计底层通信操作的时候还是分秒必争(JProfiler看看消耗的时间占用的比例以及调用的次数),用一些自己简单的方式替换。
3. 眼见未必为实,测试才得真知。在SIP5.5中考虑连接后端ISP方式由HttpURLConnection替换成为HttpClient,感觉HttpClient的开发模式更加容易认为是共享传输通道(Get,Post都单独作为包来交由HttpClient单个实例),虽然看到HttpURLConnection说明中提到会共享通道。结果一压,HttpClient根本上不去,原因是构建这些Get,Post本身也很耗时,同时HttpURLConnection底层共享优化的也很不错。HttpClient的优势还是在于去构建简单的客户端,能够处理附加cookies等额外需求。
4. 链式处理的情况下,上下文中共享信息减少数据频繁访问缓存。
5. 操作系统配置以及Web容器的配置会直接影响应用的性能,特别是一些Socket交互比较频繁,会有很大并发的应用。具体的配置可以参见最后的说明。
6. APR模式对于服务器处理能力有很大的影响,Epoll和Unix socket都会来带很大的性能提高(降低资源消耗)。
7. 在过去谈过异步Servlet的方式(Servlet3.0的特性之一),但是JBoss5测试下来看,稳定性并不好,并且可能会有一些并发问题。
8. 先列出性能瓶颈可能点,然后分别对已经优化的模块进行单独测试,最后整合并且通过多场景测试来验证优化结果。
附加信息:
JBoss Web Container配置:
<Connector port="8128" address="${jboss.bind.address}"
maxThreads="1024" maxHttpHeaderSize="8192"
emptySessionPath="true" protocol="HTTP/1.1"
enableLookups="false" redirectPort="8443" acceptCount="1024"
connectionTimeout="20000" disableUploadTimeout="true" useBodyEncodingForURI="true"/>
Apache work的配置:
Keep alive off
<IfModule worker.c>
ServerLimit 80
ThreadLimit 128
StartServers 10
MaxClients 8000
MinSpareThreads 64
MaxSpareThreads 800
ThreadsPerChild 100
MaxRequestsPerChild 10000
</IfModule>
Linux配置信息:
执行:vi /etc/sysctl.conf
添加一行:net.ipv4.ip_local_port_range = 1024 65535
再执行:sysctl -p
更改ulimit –n属性,可用端口数,还有ip_conntrack_max
APR:
Tomcat优化了IO(sendfile,epoll,OpenSSL)。操作系统的一些函数(随机数的产生,系统状态的获取等),本地进程优化(共享内存,NT的管道,Unix的Socket)。Tomcat有配置监听器直接会检测APR模块是否存在,在bin目录下建立native目录,并且放置对应的so或则dll即可。
2009年2月12日
在大型网站中常常会遇到大流量的数据输出问题,过于频繁的输出到DB、文件、第三方系统都会带来不稳定性和低效率。因此需要采用一定的方式来解决这个问题,其实这部分内容的简单处理框架早就用在实际项目中,不过今天正好有外部的朋友问起我,我就整理了一下作为google的开源代码放上去了,这里也简单介绍一下,有兴趣的朋友可以去看看,最好是能够给一些建议。
场景:
应用频繁访问接口服务器,需要控制每个应用在可配置时间段内(例如一分钟)对于某一服务的访问次数,同时需要记录每一次访问内容到数据库中。
几个点:
1. 高并发情况下,集群服务器需要全局计数。(需要将更新和判断作为原子操作,而非两阶段操作,保证高并发事务)
2. 异步日志批量输出。防止高频率访问第三方系统(DB,本地IO),提高性能。
3. 采用黑名单简化计数器判断。
1,3通过memcache就可以实现,如果需要使用客户端可以看看google code上的:http://code.google.com/p/memcache-client-forjava/
这里主要在说一下2,在很多场景中都会有这样的需求,一些需要输出到DB或者文件的内容需要缓存起来异步批量操作,提高性能也降低对于第三方系统的压力。大致设计结构图如下:
自上而下来看,ThreadA,B,C都是程序中其他模块的线程,他们需要输出记录到数据库或者DB中。当有数据到达需要输出时,仅仅只是将数据放入阻塞队列中,而有一个消费者线程池中的线程发现队列中有数据就将数据写入其中某一个线程的数据分页中(每一个线程维护一个自己的内存分页,当页满或者到达了配置的输出间隔时间以后就将页内数据交给输出线程池中的输出线程完成批量数据输出)。
下面是三个类图,囊括了这个小工具框架的所有类:
上图是对外提供的异步输出模板,其他模块可以直接使用模板来输出数据。

上图是异步输出器包,是异步输出模板的内置逻辑实现,其他线程直接使用异步输出模板来输出记录。

上图是消费者和输出线程的接口和默认实现类,可以替换及扩展。
整个框架基本都可以通过配置文件扩展每一个角色(异步输出类,消费者,写出者),扩展方式就是通过在classpath下增加目录META-INF/services/然后将需要扩展的接口作为文件名称,内容就是接口的实现类,这样既可扩展和替换任何一个角色的具体实现。
具体的代码和测试用例可以去http://code.google.com/p/asynwriter/ 下载。
2009年1月13日
摘要: Author:文初
Email:wenchu.cenwc@alibaba-inc.com
Blog:http://blog.csdn.net/cenwenchu79
什么是Dynamo? Dynamo是Amazon的高效Key-Value存储基础组件(类似于现在被广泛应用的Mem... 阅读全文
2009年1月11日
该文前半部分在程序员1月刊上,由于杂志篇幅有限,因此后半部分没有被刊登,这里就在blog上增加一下:
三. 服务集成平台
经过前面的介绍和实践两部分,在Open API在概念和实际操作上都有了一定的理解和认识,这里就再谈谈服务集成平台的作用、角色和定位。这里大致描述一下集成平台当前的实现点,这些实现点也就是服务集成平台的价值所在。
服务集成平台(SIP)的角色和作用

图 3 SIP Role
ISV(独立软件开发商)最关心什么?
1. 服务资源是否丰富。这关系着是否能够创新。
2. 服务质量是否有保证。这关系着是否能够满足用户最基本的需求。
3. 开发集成是否便利。这关系着开发成本。
ISP(独立服务提供商)最关心什么?
1. 服务安全性是否可靠。如果损害到自身或者用户利益,则就失去了原来开放的初衷。
2. 是否有足够多的应用开发者使用服务。
3. 服务的非业务性需求是否可以满足。(服务监控告警,计费,统计分析等)
SIP是连接ISV和ISP的“桥梁”。它能解决什么双方最关心的什么问题?
1. 丰富的ISV资源以及丰富的ISP资源。这其实是一个良性循环的过程,就好比一个建材市场,买家和卖家数量远远要比在单独一家实体店中多,从淘宝的B2C模式就可以看出,市场大了以后传统的“大鳄”都要聚集人气。
2. 统一安全标准和多种控制策略,即保证了ISP的安全,又能够让ISV开发起来方便。在前面实践过程中可以很明显的看到,众多的应用id,各自的安全流程,让开发者Mash up无形中增加了很大的开发成本和维护成本。
3. SIP目的就是让ISP专注于业务服务的开发,而将非业务性的需求,如安全,服务监控预警,日志分析统计,计费,社区等都一揽子解决。这样既解决了ISP的第三个问题,同时也为ISV关心的服务质量无形中作了促进。
在年初的时候,分析和研究国外的Open API时,感觉类似于SIP形态的产品在国外还没有,大家都是各做各的,但这阵子回过头来看,YouTube和Google开放平台,Flickr和Yahoo开放平台,这些平台都属于SIP形态的产品,而且Google要比当前我们做的SIP还要更进一步,那就是数据格式规范化(GData),而SIP当前仅仅只是做到流程规范化。
那是否任何公司都适合去做SIP这类形态的平台呢,这不仅仅是技术问题,还是一个资源的问题。阿里巴巴每一家子公司都有实力去做一个这样的开放平台,但各自独做一套的结果就是资源浪费,同时技术没有得到积累(SIP技术积累是在ISV和不同形态的ISP接入中逐渐产生的),最重要的是这些子公司其实真正需要关注的是如何将业务和数据开放给开发者,吸引更多的开发者来构建出围绕Open API的创新应用,最大化数据和服务的商业价值。
服务集成平台功能特性
服务路由
服务集成平台就好比硬件里面的“路由器”,服务调用者只需要提供服务注册的名称,就可以调用到某一个服务提供商提供的服务,对于调用者来说无需关心此服务的地址以及提供者。
根据现阶段的服务集成来看,主要分成四类的服务路由,同步服务路由,异步服务路由,订阅服务路由,大数据量上传服务。同步服务路由就是普通的Http无状态单次请求和响应。异步服务路由应用于服务提供商提供的服务无法在当时处理完毕,先返回一个请求响应,当服务处理结束以后再将服务处理结果返回给服务调用者(短信业务就是一种异步服务)。订阅服务和互联网上RSS之类的订阅十分相似,服务调用者只需要订阅服务即可获得服务提供商推送的服务内容。大数据量上传服务其实也是属于同步服务,但是由于消耗资源和性能压力不同,因此被单独作优化处理。
对于服务形态不同,服务路由需要支持REST风格的服务路由和类REST风格服务的路由,但对于开发者来说,调用的方式都是用服务名称来路由。
正式环境和测试环境的隔离和切换
对于服务开发者来说,在应用开发期间需要有外部测试环境的支持,在商用以后需要有正式环境支持,同时两个环境的切换需要尽量的简单。
服务集成平台支持服务提供商提供测试环境和正式环境的不同服务路由,同时两套环境切换成本低。当服务提供商只有一套环境的时候可以根据策略配置的不同,对调用者访问的范围,频度,次数作限制,保证测试服务不影响正式服务。
安全
提供对应用身份认证以及服务提供商身份认证的支持,采用多种数字签名算法实现基本的身份认证,支持IP白名单和动态算法更新后端插件提供更高级别的服务安全保证。
细化了用户授权流程。对于用户Token细分为请求级别和会话级别,同时对于会话级别的权限操作,失效时间可根据服务提供商的配置自定义。同时平台托管维护每个应用每个用户的多身份绑定Token,降低服务提供商开发维护成本。
服务提供商可配置服务访问量控制和频率控制(所有应用或者单个应用)。也支持配置需要订购才可以使用的服务(有限次数订购,无限次数订购)。
支持多级服务安全策略配置,为服务配置(无授权,应用授权,用户授权,可选用户授权)等多种级别的安全策略。注:可选用户授权是指如果没有被用户授权的情况下使用接口将返回部分公开数据,而在用户授权情况下使用则返回全部的私有和公开数据。
对服务提供商多级分类,提供不同的安全策略组合。
监控与告警
服务使用者服务使用出错监控和告警。
服务提供商提供的服务可用性,超时状况的监控和告警。
服务集成平台服务处理状况,内部模块运行状况监控和告警。
日志采集与统计分析
高并发下日志采集异步处理,采集服务正常访问和异常访问日志,采集用户绑定类,异步服务类,平台内部服务类等特殊日志。
每日,每周,每月访问日志统计分析,基础报表和趋势分析图的创建。
支持分析结果预警配置。
历史统计数据管理和归档。
平台内置服务
平台为服务提供商以及服务调用者提供了平台级别的服务,为开发商和服务提供者获取平台业务数据以及运行期配置安全策略提供方便。
平台提供一系列平台模块监控、配置、重置服务,支持在线问题查找、定位、解决的一套机制。
非功能性需求(当前情况)
性能:压力测试单机500并发用户1600+的tps,多机处理能力线性增长。
模块化:内部处理模块化结构,支持运行期配置、装载、卸载。
容错:服务集成平台核心数据都缓存在Memcache中,因此Memcache集群以及容错策略的扩展都为平台稳定和容错作了基础保证。
配套支持
通过ISV,ISP,Admin三个Portal,使开发者,服务提供商以及后台维护人员能够自主维护基本信息和查看相关数据。
为开发者提供社区,测试区的支持,并且提供开发工具包和文档,方便开发。
扩展集成
支持不同平台的服务集成。支持Google,Flickr,Yahoo等等不同的服务平台的服务集成,当前还没有完全将安全体系集成,只能够支持安全流程透传,消息数据完整过滤。
服务集成平台的一些发展趋势
1. 数据集成和流程集成
当前很多服务都是基础的数据型服务,使用者通过数据筛选获取相应的数据,然后展现给用户,这些服务的集成相对来说功能比较单一,流程也不复杂。但随着服务提供商的发展,数据类型服务将会作为基础服务的一部分,而越来越多业务处理型服务会成为使用者的首选,此时,如何让服务和服务之间数据互通,服务可以通过一定的描述编排,就会变得越来越有价值,就如前面提到的,Google采用GData作为数据规范格式,同时对于安全流程的统一制定,为第二阶段的集成打下了基础。
2. 服务基础平台间的互通
最近Open ID也再次由于各大网站的支持而被人们广泛关注,在未来Open API体系中,伴随着Open ID的发展,服务基础平台之间的服务互通也将会变得越来越容易,但是数据的安全性也会对每个服务平台要求更高。
3. 服务集成平台的层次化
在这篇文章的介绍中仅仅介绍的是最基础的Open API的Mash up,其实当前已经有更高层次的Mash up被广为使用,JavaScript、ActionScript、Flash/Flex这些技术使得展现更为灵活和丰富。因此未来的服务集成平台将会层次化,从数据集成到流程集成到UI集成,会成为一套自下而上的解决方案,适合各种场景的裁剪选择。
四. 对Open API的一些思索和感触
不同角色,不同收获
平台开发者:
这是我的本职工作和角色。当淘宝等服务提供商的服务接上来以后我就要为它的安全和稳定负责。当SIP一旦出现问题,那么服务提供商和软件开发商将都无法再正常工作,套用蜘蛛侠的一句话:“能力越大,责任越大”。作平台的尤为如此。
服务提供商:
服务提供商接触的最多的就是淘宝的同学,首先看到的就是做一个服务提供商很不容易,要把原有系统中复杂的逻辑抽象出来并不是抽象一个公用函数那么简单,同时对于模块化,边界性,容错性方面的要求要远远高于封闭系统开发本身,因为你现在要面对的是倍于原有访问量上百甚至上千的调用者,对任何一个小疏漏都可能带来灾难性的影响。
软件开发商:
在写这个文档以前,最多也就是写几个测试的Demo来测试SIP环境中的服务,在淘宝API讨论群中会看到很多新的或者老的ISV在抱怨或者询问一些自己觉得很简单的问题(例如签名等等),同时在监控中也看到很多及其简单错误统计数都会有很高的比例。但是经历过这次对于各种各样国内国外的API的开发,让我深刻体会到了开发者的一些痛苦(当然我没有去使用各个开发社区的第三方语言开发包,这也增加部分的开发难度),我也曾因为签名问题在豆瓣API测试的时候折腾了半天,在调试Google Calendar的时候不得不跟踪开发包代码才找到了一些隐晦的设置通过测试。其实Open API在国内国外都没有完全可以称得上成熟,因此开发者其实是最容易受到影响的。同时他们面对着最难应付的客户,平台或者服务提供商出现问题,客户最先抱怨的也是服务开发商,因此作为平台开发者和ISP其实都要给与一定的支持和帮助,这样才会走向更好的良性循环。
其实上面说的那些无非都是大家最长说的换位思考,一个新兴的开发模式需要各方合作才会走向良好的发展方向。
创意就是财富
记得前一阵子支付宝能够在上海交水电费引起了很多人关注,杭州本地论坛中都有很多人在问:“什么时候杭州能够也用支付宝交水电费就好了”。其实如果开放了支付服务和水电缴费服务,这种Mash up的应用又有什么难的呢?你都可以直接每个自然月通过Google Calendar设置好日程安排,自动缴完所有的费用,然后短信提示一下即可。未来当各行各业发现了自身资源的潜在价值以后,以服务的方式通过平台互通,那么创意就是财富。
摘要: Author:文初
Email:wenchu.cenwc@alibaba-inc.com
Blog:http://blog.csdn.net/cenwenchu79
问题凸现:
年关到了,商家忙着促销,网站忙着推广,阿里软件的服务集成平台也面临第一次多方大规模的压力考验,根据5.3版本的压力测试结果,估算了一下现有的... 阅读全文
2008年12月17日
应该是去年的年初,我受到普元公司的邀请去参加了一次SCA、SOA的技术交流会,当时也是自己第一次去和那么多陌生的朋友交流技术心得,同时也被普元公司的这种纯技术性的交流方式所打动,也在想哪一天阿里巴巴也能够举办一次这样的小规模有针对性地技术交流会那会让我们这些技术人员收益菲浅。一年后的今天,当老大问我有个这样的会议是否要参加的时候,自己毫不犹豫地报了名,虽然看起来和自己专注的工作不是很相关,但是还是那个想法:首先不了解是无法知道是否和自己相关与否,其次就算不相关,多学多听,触类旁通的技术延展只会给自己带来更多的想象空间和创新思维。
按照会议安排,早晨有两个讲座,下午有四个讲座,每个讲座1个小时左右。第一个出场的是腾讯的安全中心总监杨勇,整个演讲很轻松,首先是对腾讯的整体产品结构和背景作了一下阐述,然后就从安全中心这个整体来讲述安全对于腾讯的意义,如何实施以及一些流程的制定。没有过多的牵涉安全问题的细节,着重是讲述了安全中心面临的四个方面的问题,以及通过什么手段去解决。这其实和他本身所处的工作职责来说相符合,如果仅仅只是来讲某一个安全技术应用,那么就有些太过狭隘了。不过在提问的时候一个问题的回答让我还是留有一些印象的,主持人收集到一个问题:“腾迅安全中心的建设初期遇到的最迫切需要解决的问题是什么?”,他回答道:“其实腾讯安全中心从建设初期到现在一直面临各种迫切的问题,只是随着时间的不同而不同的演变,最早的协议安全到客户端安全到奥运期间的信息安全都是一个发展的阶段”(因为没有ppt以及记录,因此描述的可能不太准确)。但是这个思想任何技术行业都是一样的,时代不同关注不同,需要解决的问题也是在发展的。
第二个议题是Discuz的剑心带来的“web应用程序中的字符集攻击”,这个演讲就相对来说比较注重专业细节方面的阐述。作为互联网应用开发者,使用Java的人第一堂课就是中文乱码,很多人只看到如何去配置或者写一点转换语句就可以解决,但是对于编码方式就不求甚解,ISO-8859-1,GB2312,UTF-8,UTF-16区别是什么,为什么会引起乱码。其实了解了编码的原理就很能够解释如何会产生乱码,同时产生乱码的时候也可以根据乱码的情况了解可能是因为什么编码转化造成的(阿里巴巴的宝宝写了一篇很详细的文章说了这个问题,进入公司以后我也是看了那片文章才系统地对编码方式做了完整的了解,以前都是碎片)。不过今天听了这个演讲,到让我知道了原来编码方式也被人用来攻击。其实基本的思想主要就是一点:由于信息转发中对于不同编码解析的方式不同或者是过滤不同,导致出现一些漏洞。通俗的比喻就是刺杀秦始皇的图穷匕见,侍卫就好比第一层把关的信息转发者认为着幅图没有威胁,但是真的按照刺客的处理方式那么就是一个最好的攻击性工具。记得我在和同事探讨REST对于Http协议的使用时说最重要的就是REST不再使用Http协议作为传输承载协议而是作为业务协议,那么解析业务的时候究竟是分析协议中指定的编码方式还是内容中的编码方式,结果会大不一样,同时作为安全人员的角度来看,这也会存在一种安全隐患。所以其实任何一种错误都可以被利用作为攻击的手段。
下午的议题一共有四个,虽然时间比较长一直连续讲到6点多,但是就像主持人讲的,每一个人都“坚持”下来了,呵呵,当然坚持并不是因为不好听,而是做在那儿听比写代码要累很多,当然讲课的同学们也是十分辛苦的。下午第一个演讲的是team509的创始人吴石,讲的主题是“部分软件安全的思考”,内容专业化很强,对很多比较底层的安全问题(操作系统等)作了一些介绍,当然对于我这个门外汉只能听懂个大概意思,不过还是有所了解那些名词的意思到底是什么。第二个是微软的大牛蛙同学,也是安全领域专家讲述了一下微软的SDL(Security Development Lifecycle),望名生意,安全实施的流程化。第三个演讲是两位同学做的,也是我下午听得比较有感触地,先是网名余弦(钟晨鸣)北京知道创宇信息技术公司的安全研究员,讲的是CSRF蠕虫技术,从一个黑客的角度来阐述CSRF的原理以及危害性。这部分比较技术化一些,但是由于和我关注的Web安全也比较相关一些,所以听起来也不是比较迷糊。虽然听着他讲CSRF,但是其实我脑子里面已经在考虑关于Open API的一些安全问题。其实在阿里软件承载淘宝的API过程中,对于客户端的安全问题就一直都在谈,但是对于SIP来说总是鞭长莫及,因为服务集成平台只会保障ISV和ISP之间的信息交互的真实性,但是用户是否由于ISV的技术问题导致信息伪造提交,那么就不得而知,但是最后表现出来的结果就是ISP的Open API计划为ISP带来了更多的安全隐患,也就是说原来淘宝一家漏洞,以后可能会是千千万万家ISV的漏洞,其实这也是上面几个演讲提到的合作风险问题,第三方的技术能力不得而知,同时产生的风险也会很难控制。其实从这里也多多少少看出来为什么FaceBook,myspace,最早对于用户安全隐私数据的开放不仅仅是开放了数据API,同时也会有整一套上层框架支持,其实也是出于开发者能力不足引起隐私数据被恶意修改而作的防护措施。那么现在Open 用户的数据特别是以后涉及到金额的api如何保证isv不欺诈,isv不被欺骗,这可能是后续需要更加重视的问题。同时,在听了CSRF的攻击中谈到的对于资源定位猜测以及操作的时候,让我对REST的风格又打了一个冷颤,REST对于资源的规划和定位十分容易,但是这也为这类攻击提供了便利,同时对于资源操作依赖于Http协议,也会让资源的安全性打了折扣,这需要对Open API开发人员做更多的安全工作指导,或者提供安全框架来防范Open API可能会产生的安全漏洞。紧接着后面的演讲是北京知道创宇信息技术公司的创始人赵伟,应该是业界比较资深的专家了,本来的议题是“恶意网站检测”,不过他还是讲了他这些年来的一些经历以及安全领域的黑色产业链的问题。平时这方面关注的不多,不过今天这一番交流,让我对安全领域的发展以及现况有所了解,甚至有时候就觉得现在上网就算装了一大堆东西还是感觉在“裸奔”。最后一个议题是51.com的郑歆炜讲的“运维安全经验谈”,总结了运维所面对的问题以及解决方案,协调,沟通,总结,知识库,其实这些对于开发人员来说何尝不是呢。最后小黑作了一个简短的总结,同时预报了明天他会做一次附加的构建安全Web架构的讲座,期待明天半天的研讨会和附加讲座。
好久没有踏踏实实地坐着好好听课了,这次一天半的学习对于自己来说也算是一次新知识的扫盲,同时也为自己后续的工作可能存在的问题或者可以借鉴的知识作一个铺垫。