放翁(文初)的一亩三分地

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  210 随笔 :: 1 文章 :: 320 评论 :: 0 Trackbacks

#

   今天是转岗到淘宝的第七天,也算是一周吧,期待来这个团队已经有快大半年了,这次阿软的重组给了一个机会,过去的就过去吧,不再回首有任何的抱怨和遗憾,需要面对的是新的将来。

    很奇怪,来到淘宝,都是熟人,Boss是早就相识的菲青,TOP团队的自雪,凤先,秀芳及我不认识但是认识我的其他同学都很热情,运营,PD,OST都是以前阿软的老同学,还有其他几个团队的朋友,感觉回到了家,而不是离开了家。

    原先来淘宝是比较坚决的,同时也得到王博士的支持,心里还是比较有底的,不过就是担心过来以后和淘宝已有的团队合作可能会有磨合期,因为担心有“小圈子”。结果却是很出乎我的意料,TOP的人就和做的事情一样,是一批开放的人,自雪,凤先,张三各个都很放的开的和我聊,对于架构,对于技术,对于未来的发展,这些人坐在一起什么都可以说,自己觉得自己早先是用老思维来看待这个团队了。这个团队很年轻,很有活力和创造力,缺少的只是一些经验,而我经验是有一些,但是那些斗志已经在去年一年被磨砺的差不多了,正好是我回炉好好再热一热的时候了。来之前就和黑羽有过接触,也看过他对于TOP的一些构想,在我的计划中就有和他交流的部分,上周找了一个时间碰了一下,果然有很多和我一致的想法,同时还有一些比我更加深入的idea,特别是对于大淘宝未来的一个构想。其实来到TOP我所要做的就是在技术的架构上找到商业的感觉,让商业驱动技术,技术沉淀积累来支持商业的畅想。

    这七天过的很快,全身心投入的工作,时间总是过的很快,而且过去那种沉闷的心情和处事的态度在这里得到了改变。明天基本上就看完了TOP的大部分代码,整理了一些review的建议,同时昨天还花了一些时间去看了看google appengine,写了几个小应用,看了看源码(部分反编译),因为要给boss对于小应用hosting方面的一些想法。

   总的来说还是和我原先的计划一样,商业上和PD运营交流,了解未来TOP商业发展方向,以及对技术架构的一些需求。架构上从代码和文档看起,文档不是很多,所以就只好每个工程看过来,也不错,看到自雪同学写的代码还是不错的,同时也看到了淘宝的基础组件的推广力度之大,这比在阿里软件强的多,其实也是我一直希望看到的,人人都是技术牛人,都在做重复的事情,但是却没有技术沉淀,其实大家完全可以吧自己的构想增强在别人的基础之上,而不是什么都自己搞一套,淘宝的技术应该来说在政策上得到了支持,技术积累效果还是不错的,这里还不得不提到我的淘宝同学毕玄同学的服务基础框架HSF,虽然现在还没有接触,但是应该已经发展的挺好的。

   有两个能够用人,担得起起技术团队发展的Boss,有这么一些年轻有冲劲的小同学,有这么一些乐于倾听分享协作的老同学,有这么一些很有商业feeling的非技术团队同学,要做好TOP,我想只有三个字:“没问题”。这是我在入职七天写的随记,一年后再来回看我今天说的这些话,在来看看这个团队创造的价值。

   附:在淘宝申请好了花名:放翁。陆游的字,武侠小说的人就连扫地的都没有了,历史名人也没有了,不过诗人倒是没有人用,指不定还开创了淘宝同学入职的花名新取法。

   好好工作,天天向上,为了TOP,为了家里的BB,为了自己的一点理想,踏踏实实的走自己的路,让别人开车去吧,^_^

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/cenwenchu79/archive/2009/08/12/4440248.aspx

posted @ 2009-08-12 23:16 岑文初 阅读(1147) | 评论 (1)编辑 收藏

   昨天是去淘宝工作的第一天,最近最头痛的就是花名,在我儿子出生的时候我就知道起名字是最麻烦的事情,而起花名更是痛苦,因为你的选择余地更小,同时还不能和前人重复,好不容易找到两个还不错的,结果一个给其他部门的老大保留了,一个因为拼音和一个同学相似而无法使用。想用文初,结果还给一个淘宝的活跃用户使用了,问了HR不取花名是否可以,回答说,不可以,太折腾了。

   昨天开了一整天的会,主要还是协调两个平台之间将来的合作模式,同时也梳理了双方的现有功能,将未来双方的边界做了初步定夺,同时也对将来的一些需求做了初步的规划,系统的模块化也提上了最近的日程。

  今天会化一些时间看看已有的代码熟悉一下Top的情况,同时也看看一些流程性的文档,希望能够尽快的对Top全方位的了解,这样便于从细节实现到整体架构设计都能给出自己的意见。

  初来乍到不容易,很多需要从新开始的,不过对我来说合作的人,做的事情还是有一定的基础,因此只是需要一周左右的过渡期,后续应该会走的更加顺畅。

 

 
posted @ 2009-08-06 05:12 岑文初 阅读(1014) | 评论 (0)编辑 收藏

     摘要: Author : 岑文初 Email: wenchu.cenwc@alibaba-inc.com Blog: http://blog.csdn.net/cenwenchu79 Date: 2009-5-26 目录 需求转而学习 “软”负载均衡 LVS (Linux Virtual Server) Virtual Server三种模式介绍 Virtual...  阅读全文
posted @ 2009-08-04 22:32 岑文初 阅读(2258) | 评论 (1)编辑 收藏

     摘要: “软”负载均衡学习点滴  阅读全文
posted @ 2009-08-04 22:30 岑文初 阅读(2069) | 评论 (0)编辑 收藏

Author : 岑文初

Email: wenchu.cenwc@alibaba-inc.com

Blog: http://blog.csdn.net/cenwenchu79

Date: 2009-5-26

目录

需求转而学习

“软”负载均衡

LVS Linux Virtual Server

Virtual Server三种模式介绍

Virtual Server三种模式的比较

Virtual Server三种模式实践

三种模式下的简单压力测试

HA-Proxy

HA-Proxy安装和使用

HA-Proxy的压力测试结果

负载学习心得

需求转而学习

         很多时候不少做开发的同学都认为技术更新的快,新技术、新概念层出不穷,大家乐此不疲的去跟随着所谓的“技术趋势”走在风头浪尖上,但其实往往忘记了一个最重要的问题“满足客户需求”。其实技术就是为满足需求服务的,用最小的代价来满足用户的需求,以最简单高效的方式来达到目标,就是每个开发者应该追求的。(不要因为自己的架构很简单就脸红拿不出手,只要你在满足用户当前需求的基础上对未来有所考虑,那么化繁为简就是一种能力的表现)

         SIP(服务集成平台)5.7版本中对于未来多个服务提供商,多种类型的服务,在每日几亿的调用压力下,需要找到一个解决方案:可以分流不同服务提供商的服务,分流不同类型的服务,服务隔离化来减少服务相互之间影响以及服务提供商之间的影响。

         当前SIP的前端是通过硬件F5作负载均衡,因此是无状态无差别的服务负载,这也使得无法区分不同的服务提供商的服务请求和不同类型的服务请求,导致服务提供商之间的服务会产生相互影响(旺旺即时通信类API在峰值占用了大部分的服务处理资源,淘宝宝贝上传类API占用了大量的带宽)。近期还有更大的两类API将会接入,因此寻找一个服务可分流的方案势在必行。(当然过去也考虑通过三级域名配置在负载均衡上来解决这些问题,但是这样首先对于开发者来说不透明,其次也是一种比较僵化的设计方案,扩展和维护也有一定的难度)

         在过去也尝试过ApacheWeb容器自己的一些load balance特性,当然效果不是很好,和硬件基本无法比拟,而一些专有的“软”负载均衡方案和开源项目也没有深入的去了解,因此借着这次机会,好好深入的挖一挖“软”负载均衡。

“软”负载均衡

         作为互联网应用,随时都需要做好用户量突然增大,访问量突然上升的准备。今年热门的词汇“云”我就不多说了,这里就简单说说服务器的横向扩展。其实和DB,文件系统等一样,当资源成为瓶颈的时候,就需要考虑如何通过扩展或者提升资源能力来满足用户的需求,这就是我们常说的横向扩展和纵向扩展。(对于横向扩展和纵向扩展的优劣大家应该都很清楚了,这里也不做赘述)横向扩展中就会要求使用负载均衡的能力,如何根据资源能力不同以及资源在运行期负荷动态变化将负载合理分配是判断负载均衡优劣的标准。

         软件负载均衡一般通过两种方式来实现:基于操作系统的软负载实现和基于第三方应用的软负载实现。LVS就是基于Linux操作系统实现的一种软负载,HA Proxy就是基于第三应用实现的软负载。(后面会详细介绍这两种方式的使用)

         最早期也是最原始的软负载均衡:“Round Robin DNS”,通过轮询方式在DNS绑定多个IP的情况下,将用户对于同一个域名的请求分配到后端不同的服务节点。这种方案的优点:配置简单,负载分配效率高。缺点:无法知晓后端服务节点服务情况(是否已经停止服务),无法保证在一个Session中多次请求由一个服务节点服务,每一个节点都要求有一个外网IP

         另一种较为常见的就是基于分发器的Load balance。服务使用者通过向分发器发起请求获得服务,分发器将请求分发给后端实际服务处理的节点,给客户提供服务,最常说的反向代理模式就是典型的分发器Load Balance。这类负载均衡处理可以基于应用级转发,也可以基于IP级别转发,当然基于应用转发效率和损耗比较大,同时分发器本身也会成为瓶颈。

LVS Linux Virtual Server

         LVS是在Linux操作系统基础上建立虚拟服务器,实现服务节点之间的负载均衡。LVS主要是处理OSI模型中的4层消息包,根据一定的规则将请求直接转发到后端的服务处理节点,有较高转发效率。

         Virtual ServerLoad Balancer和一组服务器的逻辑组合统称,使用服务者只需要与Virtual Server进行交互就可以获得高效的服务。真实服务器和Load Balancer通过高速LAN进行交互。Load Balancer能够将请求分发到不同的服务端,在一个虚拟IP下并行处理多个请求。

Virtual Server三种模式介绍

Virtual Server有三种基于IP级别的负载均衡实现方式:IP address translationNAT)、Direct routingIP Tunneling

         NAT(Network address translation)由于IPV4的某些缺陷和安全原因,某些网段例如(10.0.0.0/255.0.0.0, 172.16.0.0/255.240.0.0 and 192.168.0.0/255.255.0.0)不能被用于互联网,因此常常被用作内部局域网,通过网络地址翻译的方式可以让这些网段的服务器访问互联网或者被互联网访问。网络地址翻译主要作用就是将一组ip地址映射到其他的一组ip地址,当映射比例为1:1的时候通常称作静态映射,而当映射地址为M:N(M>N)的时候(M为被映射地址数量,通常是内部ip),则成为动态映射。而对于Virtual ServerNAT模式来说,就是利用了NAT的特性,将内部的一组服务器通过映射到一个虚拟的IP,然后以一个外网虚拟服务节点的身份对外提供服务。

         上图是一个实际的NAT范例,对外的服务IP202.103.106.5,内部建立了虚拟IP172.16.0.1,然后将内部其他两台实际服务的服务器172.16.0.2172.16.0.3映射到172.16.0.1这个虚拟IP。客户端向202.103.106.5发起请求服务,Load Balancer查看请求数据包,如果是请求目标地址是注册的虚拟IP及监听端口的时候,那么通过NAT按照一定算法选择某一台实体服务器,再重写报文目标地址,转发请求到实际的目标服务器,当目标服务器处理完毕以后,将处理结果返回给Load Balancer,由Load Balancer修改源地址,返回给客户端。

         IP TunnelingIP管道技术是在IP报文上再次封装IP报文协议的一种技术。允许将一个目标为AIP数据报文封装成为目标为BIP数据报文,在特定的IP 管道中传输。

         上图就是IP Tunneling模式的运作原理。首先客户端还是通过访问对外的一个服务IP请求服务,当Load Balancer接受到请求以后,检查VIP注册信息,然后根据算法选择实际的一台后台服务器,通过IP管道封装技术对IP报文再次封装,然后将消息通过IP管道转发到实际的服务器,实际的服务器通过解包处理请求,然后根据包体内实际的服务请求地址,将处理结果直接返回给客户端。

         Direct routing利用Load Balancer和实际服务器共享同一VIP,简单的通过修改消息报体目标MAC地址,转发请求,然后再通过实际服务器配置VIP为本地回环,直接处理消息报文,而不再转发,当处理完以后,直接将处理结果返回给客户端。

 

         上图就是Direct Routing的运作流程,当外部请求到Load Balancer时,通过查找VIP注册信息,直接选择一台后端服务器作为新的目标地址,修改消息报文中的目标地址Mac地址,转发到目标服务器,目标服务器由于配置VIP在本地网卡回路中,因此直接处理消息,将处理完的结果直接返回给客户端。

Virtual Server三种模式的比较

         下表是官方整理出的关于Virtual Server三种不同模式的区别:

NAT

TUNNEL

DR

服务器要求

无要求

需要支持IP管道

arp组件(当前也有补丁)

网络要求

Private

LAN/WAN

LAN

可支持后端服务器节点数

较少(10-20

较多

较多

服务网关

Load Balancer

本身

本身

NAT:根据其实现原理,可以知道这种模式对于操作系统,网络都没有太多的要求和约束,但是由于消息需要打解包,同时消息的响应都必须经过Load Balancer,因此Load Balancer自身成为了瓶颈,这样一个Load Balancer能够支持的后端服务节点数量就有限了。当然可以采用混合模式来解决这个问题,也就是通过TUNNEL或者DR模式作为前端模式串联起多个NAT模式Balancer

TUNNEL:这种模式要求操作系统支持IP Tunnel,通过对IP报文再次封装转发,达到负载均衡的目的。设计这种模式的初衷是考虑,对于互联网很多服务来说,服务请求数据量和返回数据量是不对称的,返回的数据往往要远远大于请求的数据量,因此如果请求和返回都走Load Balancer会大量占用带宽,影响处理能力。IP Tunnel设计中请求是通过Load Balancer,但是返回是直接返回到客户端的,因此节省了返回的带宽,提高了请求处理的能力。

DR:这种模式要求Load Balancer和后端服务器处于同一个局域网段。DR模式处理消耗最小,消息转发和回复基本没有损耗,因此效率应该是最高的,但是约束是相对来说最多的。

posted @ 2009-08-04 22:24 岑文初 阅读(3367) | 评论 (2)编辑 收藏

    小A,30,所在公司在去年的经济危机中没有倒下,但是在今年却倒下了。小A觉得能够把一个公司混倒闭了,也算是人生的一点经历。

    公司是没了,但是工作还要继续,生活还要继续,现在将要面对一个新的环境,环境很陌生,但也比较熟悉,工作职责很清晰,但也充满了挑战。人过30,有了孩子,真的成熟了很多,知道了什么叫做责任感,知道了未来真的需要好好规划,需要一个机会,需要一个平台来找到自己,实现自己的价值,不让这黄金时代就这么过去。

   小A将要面对的挑战在心里面已经做好了准备,也有了自己的一套短期的规划及工作安排,要成长有时候就要有压力。在小A即将离开原来团队的时候,和手下的一个同学发了火,因为在这阵子调整过程中,同学的心态一直变的很差,但是小A已经竭尽全力去分析他的未来,虽然听进去,但是过几天依然又开始放弃自己,这种态度让小A原本很看好他发展的心情变得很沉重,最后就在那个探讨会上说了他一些比较重的话,虽然说完以后自己也有些后悔,可能我对他和对我自己一样,要求太高了吧,就像博士说的,如果对一个人没有想法了,就恭维几句即可,大家你好我好大家好,只有当对这个人还存在一定的期望的时候才会表现出这种比较急切的感觉。

   新的开始,新的挑战,新的环境,新的机遇,新的难题,新的称呼

   好的心态,好的沟通,好的未来

   一切都需要小A用自己的能力去证明,走自己的路,让自己走的更好。

posted @ 2009-08-03 09:58 岑文初 阅读(859) | 评论 (0)编辑 收藏

    转眼到了7月份了,今年的blog更新的很慢很慢。写点东西记录自己的生活和工作状态。
   生活:
   儿子提早10天在六月八号来到我们这个小家庭,每个好友在祝福我的同时告诉我,辛苦的日子刚刚开始。不过和大家的感觉一样,辛苦但快乐着,在别人忙着在互联网上种花种草,养猪养鸡的时候,我开始扛起培养祖国新一代的责任。睡觉基本上很难保证连续性,早晨的运动也移到了晚上给儿子洗好澡以后。以前觉得就算到30岁还是觉得自己比较年轻,但是在那个23:25分儿子出来的一瞬间,自己觉得自己真的老了,需要成熟一点了,对儿子,对老婆。

    工作:
    其实今年年初的时候就有些彷徨,自己一手培养出来的SIP和原来的目标渐行渐远,7月份我在产品会议上提出了SIP6(第一阶段最终版),功能,性能,可扩展性都能够满足到明年中旬。虽然日访问量就快突破1亿,年底可能会到几个亿,但是这些数字对我来说只能证明这个架构还可以,但是SIP原有的目标已经被抛弃,成为了一个内部的服务集成平台。
   下个阶段会在做一些中心来满足团队的需要,但在我看来其实这些东西对我对团队的价值有限,创新有限,但这就是工作。
    公司内部有些变化,当然是好是坏不得而知,不过作为我们这些level已经处于地面的人来说也没啥影响。

   文章:
   最近的文章素材其实不少,但是受到内部技术专利申请,外部投稿的影响,能够写出来直接贴的越来越少,有时候也是这样,分享固然好,但是有些时候有些东西只能够小范围分享。

   睡觉,睡觉,中午的休息是很宝贵的,一觉醒来还继续自己的路。(走自己的路,让自己无路可走。没写错,呵呵,觉得这样挺搞笑的)
posted @ 2009-07-09 12:38 岑文初 阅读(738) | 评论 (0)编辑 收藏

 

         这篇blog的问题不能算是解决,仅仅只是一种分析和猜测,后续的一些行动可能会证明一些猜想,也可能什么都解决不了。如果有和我相同情况的同学,也知道是什么问题造成的,请不吝赐教。

问题:

上周周末,没有和同事们出去Outing,在家管孩子,去生产环境观察了一下集群机器的当前运行状态,发现应用在这些多核机器上压力极端不均匀。

         Top一下大致状态如下:



         峰值的时候,单CPU的使用率都到了80%,这种情况对于多核服务器来说是很不正常的使用。对于Java的开发者来说,多线程编程是无法控制线程如何在CPU上分配的,因为Java本身不实现线程机制,说是跨平台的语言,但是性能及特性会根据操作系统的实现有很大的差异,因此Java调优有时候需要对系统配置甚至内核作调优。

分析:

         首先在测试环境下作了多次同样的压力测试,尝试了与线上一样的操作系统版本,相似的配置,但测试结果却是负载分配很均匀。

   
     

         此时重新启动了一台问题机器,发现负载降下来了,同时也很均衡,也就是说在当前的压力下不应该有这样高的cpu消耗,同时也排除了硬件或者操作系统的一些配置问题。

         CPU满负荷的情况下,很多时候会认为应该是循环造成的,对于单个CPU的消耗更是。通过Top H查看具体到底哪一个线程会长时间消耗CPU

         可以看到PID13659的线程是“罪魁祸首”,但13659究竟在干什么,是应用的线程还是系统的线程,是否是陷入了死循环,不得而知。接着就按照Java的土办法,Kill -3 pid,然后看看输出日志。

         根据线程号来查找dump出来的日志中nid,发现这个线程是VM Thread,也就是虚拟机线程。(这里作一下转换,将13659转换成为16进制就是0x355b



         pstack看了一下这个线程的工作,结果如下:

Thread 2074 (Thread 1846541216 (LWP 13659)):

#0 0x0659fa65 in ObjectSynchronizer::deflate_idle_monitors ()

#1 0x065606e5 in SafepointSynchronize::begin ()

#2 0x06613e83 in VMThread::loop ()

#3 0x06613a6f in VMThread::run ()

#4 0x06506709 in java_start ()

#5 0x00aae3cc in start_thread () from /lib/tls/libpthread.so.0

#6 0x00a1896e in clone () from /lib/tls/libc.so.6

         搜索了一下ObjectSynchronizer::deflate_idle_monitors,发现了sunbug库中有bug关于jdk1.6中由于这个方法导致运行期问题的说法:http://bugs.sun.com/bugdatabase/view_bug.do;jsessionid=803cb2d95886bffffffff9a626d3b9b28573?bug_id=6781744

         然后就直接去openjdk官方网站去查找这个类的代码,大致了解一下他的作用,具体的代码链接如下:http://xref.jsecurity.net/openjdk-6/langtools/db/d8b/synchronizer_8cpp-source.html
主要工作应该是对资源对象的回收,在加上pstack的结果,应该大致知道是对线程资源的管理。但具体代码就没有进一步分析了。

接着就分析一下自己的应用:

         压力测试(高强度、长时间)都做过,没有发现什么异常。

         本身应用是否会存在的缺陷导致问题呢。有人说VM Thread兼顾着GC的工作,因此内存泄露,对象长期积压过多也可能影响,但其实在dump的结果可以看到,GC有单独的工作线程,同时我也观察到GC这些线程的工作时间长度,因此由于GC繁忙导致CPU上去,基本上来说可以排除。

         其次在SIP项目中使用了JDK的线程池(ExecutorService)LinkedBlockingQueue。后者以前的文章里面提到在1.5版本里使用poll方法会有内存泄露,到1.6虽然没有内存泄露,但是临时锁对象增长的很快,会导致GC的频度增加。

行动:

         上面零零散散的一些分析,最终让我决定有如下的行动:

1.       升级某一台服务器的JDK,当前是1.6.0_10-b33,打算升级到1.614版本。比较观察多台机器的表现,看是否升级了JDK可以解决问题。

2.       去除LinkedBlockingQueue作为消息队列,直接由生产者将生产结果按照算法分配给消费者线程,避免竞争,锁的消耗,同时也防止LinkedBlockingQueue带来的资源消耗。

3.       测试环境继续作长时间的压力测试,同时可以结合Jprofile之类的工具来分析长时间后可能出现的问题。

后话:

         这年头真的啥都要学一点,求人不如求己。

SA,DBA,测试都需要能够去学习一些,起码在初期排查问题上自己能够做点啥,要不然别人也忙,自己又无从下手。就好比这次压力测试好不容易排上队,但是还是满足不了及时上线的需求,因此自己去LoadRunner压,好歹给出一个零时的报告先大家看着。应用的异常有时候是应用本身设计问题,也可能是开发语言的问题,也可能是操作系统的问题,因此要去定位这种比较复杂的问题,真的需要有耐心去好好的学习各种知识,现在看来知识还是匮乏啊,要不然就可以分析出openjdk中可能存在的问题。

posted @ 2009-07-09 11:59 岑文初 阅读(4377) | 评论 (3)编辑 收藏

 

         昨天在看Cache Client代码的时候,发现在从资源池中获取SocketIO部分代码在高并发情况下效率不高,因此考虑通过一些变通的方式来提高效率,下面说的内容仅仅是当前自己琢磨出来可以部分提高效率的方法,希望看了这篇文章的同学能够有更好的方式或者算法来提高效率。

情景:

       Cache Client SocketIO资源池是一个两级的Map,具体定义为:ConcurrentMap<String, ConcurrentMap<SockIO, Integer>>。第一级MapHost作为Key,第二级MapSockIO本身作为Key,三种SockIO状态(可用,占用,废弃)作为value。之所以采用一个Pool来存储三种状态主要是考虑到在高并发下,多个池之间保持原子性的复杂。

每一次获取可用的SocketIO的操作需要经历:1.遍历Host所在的Map2.逐个比较状态。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

采用了23策略以后的测试结果:

cache test consume: 9140660, average boundle consume: 45703, average per request :91

posted @ 2009-05-07 17:15 岑文初 阅读(1944) | 评论 (0)编辑 收藏

 

       服务集成平台5.6的性能测试进入尾声,这期的优化也算告一段落。这次主要的优化工作还是在三个方面:应用服务器(Apache,JBoss)配置,业务流程,Cache Client包(http://code.google.com/p/memcache-client-forjava/ )。这里把过去和这次优化对于Cache的使用作一个经验分享,希望大家能够用好Cache,提速你的应用。

       这里还是通过一些点滴的启示来介绍优化的一些心得,很多时候还是要根据具体情况来判断如何去具体实施,因此这里所说的仅仅是在一些场景下适用,并非放之四海皆准的教条。同时也希望看此文的各位同学,如果有更好的思路可以给我反馈,技术在交流中才会有发展。

积少成多,集腋成裘

       性能提不上去,多半是在一些容易成为瓶颈的“暗点”(IO,带宽,连接数,资源竞争等等)。Memcached Cache现在已经被大家广泛使用,但是千万不要认为对Cache的操作是低损耗的,要知道这类集中式CacheSocket连接数(会牵涉到linux操作系统文件句柄可用数),带宽,网络IO都是有要求的,有要求就意味着会有损失,因此积少成多,集腋成裘。服务集成平台是一个高速的服务路由器,其大部分的业务数据,访问控制策略,安全策略以及对应的一些控制阀值被缓存在Cache服务端,因此对于Cache的依赖性很强。每一次对于客户端的性能提升,总会给服务集成平台性能带来不小的影响,但是每一次优化速度后,客户端可以优化的空间越来越小,这时候需要一些策略来配合,提升应用整体性能。当前主要采用了以下几点策略:

1.  从数据获取角度来做优化,采用本地数据缓存。(因为大家的应用需要能够线形扩展,支持集群,所以才不使用应用服务器本地缓存,但是在某些缓存数据时间性不敏感或者修改几率较小的情况下,可以采用本地缓存结合集中式缓存,减少对远端服务器访问次数,提升应用性能)。

Cache ClientIMemcachedCache 接口中的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提供了计数器一整套接口和addreplace两个接口。这些特有接口可以很好的满足一些应用的高并发性处理需求。例如对于资源访问次数控制,采用Cache的计数器接口就可以实现在集群中的数量控制,原本通过Cachegetput是无法解决并发问题的(就算是本地缓存一样),这就是一组原子操作的接口。而AddReplace可以满足无需通过get方法获取内容,就可以对于key是否存在的不同情况作出相应处理,也是一种原子性操作。这些原子操作接口对于高并发系统在集群中的设计会很有帮助。

 

Cache Client Cluster

       Memcached Cache是集中式Cache,它仅仅是支持将数据能够分片分区的存储到一台或者多台的Cache Server实例中,但是这些数据并没有作冗余,因此任何一个服务实例不可用,都会导致部分缓存数据丢失。当然很多人采取持久化等方式来保证数据的完整性,但是这种方式对于效率以及恢复的复杂性都会有影响。

       简单的来想,为什么不把数据在多保存一份或者多份呢,当其中一份不可用的情况下,就用另外一份补上。这就是最原始的Cache Client Cluster的构想。在这里具体的设计细节就不多说了,主要说一下几个要点,也让使用Cache Client Cluster的同学有大致的一个了解。

       先来看看Cache Cluster的结构图:




       这张图上需要注意四个角色:Application(使用Cache的应用),Cache ClusterCache配置的虚拟集群),Cache NodeCache的虚拟节点,在同一个Cluster中的Cache Node数据保持完全一致),Cache InstanceCache虚拟节点中实际包含的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特性)。未来不排除还会有更多需要的特性加入。Activekey不存在的情况下会有些低效,因为会判断一个冗余节点是否存在内容,然后决定是否修复当前节点。(考虑采用短期失败标示之类的,不过效率不一定高,同时增加了复杂度)

 

 

运行期动态扩容部署

       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的链接,直接可以下载使用和察看。希望对需要的同学有帮助。

posted @ 2009-04-28 23:19 岑文初 阅读(3361) | 评论 (6)编辑 收藏

仅列出标题
共12页: First 上一页 3 4 5 6 7 8 9 10 11 下一页 Last