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

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

2009年2月12日 #

     摘要: Beatles小记(三)-分布式数据流分析中Master的横向扩展  阅读全文
posted @ 2012-01-17 13:21 岑文初 阅读(5174) | 评论 (2)编辑 收藏

     摘要: Beatles小记-分布式数据流分析框架(二),局部代码设计和实现分享  阅读全文
posted @ 2011-12-09 16:44 岑文初 阅读(4740) | 评论 (4)编辑 收藏

     摘要: 分布式流式数据分析设计和代码分析  阅读全文
posted @ 2011-12-07 16:46 岑文初 阅读(9586) | 评论 (7)编辑 收藏

     摘要: java优化设计实现细节分享  阅读全文
posted @ 2011-09-23 14:03 岑文初 阅读(5044) | 评论 (1)编辑 收藏

     摘要: 两个开放平台内部组件开放   阅读全文
posted @ 2011-07-12 11:54 岑文初 阅读(3756) | 评论 (2)编辑 收藏

     摘要: 讨论一下并发消息下行的设计方案和实现  阅读全文
posted @ 2011-06-23 12:16 岑文初 阅读(4527) | 评论 (0)编辑 收藏

     摘要: Jetty内部透明简单实现  阅读全文
posted @ 2011-06-22 17:03 岑文初 阅读(3995) | 评论 (0)编辑 收藏

     摘要: 慢连接&LazyParser  阅读全文
posted @ 2011-06-20 23:47 岑文初 阅读(5330) | 评论 (0)编辑 收藏

     摘要: PipeComet测试  阅读全文
posted @ 2011-06-08 23:58 岑文初 阅读(6919) | 评论 (0)编辑 收藏

     摘要: 一段代码,几句话  阅读全文
posted @ 2011-04-13 23:11 岑文初 阅读(4575) | 评论 (1)编辑 收藏

     摘要: 开放平台的技术问题  阅读全文
posted @ 2011-03-31 00:43 岑文初 阅读(4812) | 评论 (4)编辑 收藏

     摘要: Web容器测试模型选择  阅读全文
posted @ 2011-03-31 00:40 岑文初 阅读(3372) | 评论 (0)编辑 收藏

     摘要: 十年  阅读全文
posted @ 2011-03-08 23:46 岑文初 阅读(2902) | 评论 (6)编辑 收藏

     摘要: 模拟登录看前端门外汉学习  阅读全文
posted @ 2011-03-03 23:26 岑文初 阅读(5529) | 评论 (10)编辑 收藏

     摘要: 逻辑划分线程池  阅读全文
posted @ 2011-03-01 00:32 岑文初 阅读(5150) | 评论 (4)编辑 收藏

     摘要: OAuth2的一些改变  阅读全文
posted @ 2011-02-28 23:01 岑文初 阅读(3403) | 评论 (0)编辑 收藏

     摘要: “淘宝的”开放平台  阅读全文
posted @ 2011-02-23 23:39 岑文初 阅读(5073) | 评论 (4)编辑 收藏

     摘要: 交流分享  阅读全文
posted @ 2011-02-20 23:58 岑文初 阅读(4960) | 评论 (7)编辑 收藏

     摘要: ask & answer  阅读全文
posted @ 2011-01-12 23:22 岑文初 阅读(3862) | 评论 (0)编辑 收藏

     摘要: 耗内存应用优化实际案例  阅读全文
posted @ 2010-12-22 23:40 岑文初 阅读(4296) | 评论 (0)编辑 收藏

     摘要: Local Cache的小TIP   阅读全文
posted @ 2010-12-14 22:34 岑文初 阅读(3399) | 评论 (4)编辑 收藏

     摘要: SD开放平台技术分享  阅读全文
posted @ 2010-12-13 20:35 岑文初 阅读(3190) | 评论 (2)编辑 收藏

     摘要: Facebook优化分享后记  阅读全文
posted @ 2010-12-12 19:43 岑文初 阅读(3440) | 评论 (4)编辑 收藏

     摘要: 这篇文章将会从问题,技术背景,设计实现,代码范例这些角度去谈基于管道化和事件驱动模型的Web请求处理。建议从头看,能够从概念上更多的去理解和碰撞,其中的一些描述和例子也许不是很恰当,也希望得到更多的反馈。  阅读全文
posted @ 2010-11-25 14:44 岑文初 阅读(4104) | 评论 (7)编辑 收藏

     摘要: 这篇文章将会从问题,技术背景,设计实现,代码范例这些角度去谈基于管道化和事件驱动模型的Web请求处理。建议从头看,能够从概念上更多的去理解和碰撞,其中的一些描述和例子也许不是很恰当,也希望得到更多的反馈。  阅读全文
posted @ 2010-11-24 01:26 岑文初 阅读(3358) | 评论 (4)编辑 收藏

     摘要: 图片是大纲,先抛出来,后续会有更详细的文章分享  阅读全文
posted @ 2010-11-17 01:00 岑文初 阅读(2640) | 评论 (2)编辑 收藏

     摘要: 如果关注开放平台或者关注平台的一些内容,这篇文章应该有点内容可看  阅读全文
posted @ 2010-10-11 23:42 岑文初 阅读(2914) | 评论 (1)编辑 收藏

     摘要: 美国JavaOne之行内容,需要看直播请关注微博  阅读全文
posted @ 2010-09-22 15:55 岑文初 阅读(1666) | 评论 (1)编辑 收藏

     摘要: 代码背后的点滴,通过一些设计理念来分享技术的积累  阅读全文
posted @ 2010-09-09 02:05 岑文初 阅读(4288) | 评论 (8)编辑 收藏

     摘要: 面试有感  阅读全文
posted @ 2010-09-02 11:31 岑文初 阅读(2394) | 评论 (4)编辑 收藏

     摘要: 对同学性能优化总结的一点回复  阅读全文
posted @ 2010-08-23 16:58 岑文初 阅读(2280) | 评论 (0)编辑 收藏

     摘要: ppt分享  阅读全文
posted @ 2010-08-10 07:48 岑文初 阅读(3629) | 评论 (2)编辑 收藏

     摘要: 在概念篇介绍完以后,开始实际的对TOP开始做技术改造。(这篇东西更像是对短期工作的总结和汇报,写的不是很详实,后续会有一个ppt来深化异步化的一些思想)下面将第一阶段的工作做个总结,第一阶段主要做了以下几个方面的事情  阅读全文
posted @ 2010-08-06 00:38 岑文初 阅读(4209) | 评论 (0)编辑 收藏

     摘要: 淘宝一年陈  阅读全文
posted @ 2010-07-24 00:34 岑文初 阅读(2830) | 评论 (7)编辑 收藏

     摘要: Web服务的重放攻击的一点想法  阅读全文
posted @ 2010-07-07 00:40 岑文初 阅读(3179) | 评论 (0)编辑 收藏

     摘要: Web服务请求异步化介绍  阅读全文
posted @ 2010-06-30 08:41 岑文初 阅读(5225) | 评论 (4)编辑 收藏

     摘要: Web服务请求异步化测试  阅读全文
posted @ 2010-06-13 14:35 岑文初 阅读(4415) | 评论 (9)编辑 收藏

     摘要: 访问TOP链接超时和重置问题  阅读全文
posted @ 2010-06-09 13:34 岑文初 阅读(1706) | 评论 (1)编辑 收藏

     摘要: 对TOP高并发的一点回答  阅读全文
posted @ 2010-06-07 21:22 岑文初 阅读(1756) | 评论 (0)编辑 收藏

     摘要: TOP的价值所在  阅读全文
posted @ 2010-06-01 08:49 岑文初 阅读(3525) | 评论 (5)编辑 收藏

     摘要: 开放平台两三点感悟(下)  阅读全文
posted @ 2010-06-01 02:53 岑文初 阅读(3280) | 评论 (4)编辑 收藏

     摘要: 开放平台两三点感悟  阅读全文
posted @ 2010-05-28 02:29 岑文初 阅读(4364) | 评论 (6)编辑 收藏

http://t.sina.com.cn/fangweng

posted @ 2010-05-24 21:54 岑文初 阅读(1281) | 评论 (0)编辑 收藏

     摘要: ModJK与tomcat消息传递出现的串消息问题  阅读全文
posted @ 2010-05-11 20:00 岑文初 阅读(2764) | 评论 (0)编辑 收藏

     摘要: 异步模式下的Web请求(技术介绍篇)  阅读全文
posted @ 2010-04-20 08:50 岑文初 阅读(4232) | 评论 (1)编辑 收藏

     摘要: Q1技术点滴  阅读全文
posted @ 2010-04-02 02:26 岑文初 阅读(3113) | 评论 (5)编辑 收藏

     摘要: 普通程序员的2009  阅读全文
posted @ 2010-01-29 01:34 岑文初 阅读(2145) | 评论 (4)编辑 收藏

 

优化杂谈

Author :放翁

Bloghttp://blog.csdn.net/cenwenchu79/

         当应用遇到规模化问题的时候,就是考虑性能优化的时候了。今天同事和我聊起了NIO在客户端的使用与BIO有什么优势,也勾起了我前一阵子和其他同学交流优化的一些想法,纯粹个人的一点想法。

CPU利用率和Load

         在过去做压力测试的时候,我们经常会关注两个指标,CPULoad。有同学觉得CPU利用率上去了Load肯定也上去了,Load上去了CPU利用率同样会上去。但是在一些需要优化的场景下,常常会看到Load很高,CPU利用率却可能比较低(多核更是可能出现分配不均的情况)。Load其实就是等待处理的任务队列,当你的应用在等待同步消息返回处理的同时,CPU还是会将时间切片分配给这些线程,而真正需要CPU的线程,却不得不在到了时间片以后暂时放弃工作被挂起。因此在程序设计的时候就要考虑如何利用好CPU的这个资源,如何均匀的将压力分摊到各个CPU上(有时候就一个线程在不断循环,导致单个CPU负荷很高)。

NIO在客户端的使用

         Http消息设置keepalive和采用NIO的方式复用信道、BIO结合连接池的方式,最基本的目的就是降低建立TCP产生握手的成本,最大限度的复用已有的资源,但是否NIO就只有复用信道这点呢?

         NIOBIO在数据传输和处理的模式上有不同,NIO采用的是BufferPacket+Channel的模式,这其实和操作系统本身的传输模式很类似,而BIOStream的模式是Java自己独特的模式。在采用NIO的这种数据传输模式以后,可以充分利用操作系统本身对传输的优化,因此这是一方面好处。另一方面异步和事件机制的使用,可以降低对于昂贵的资源申请,在高并发下提高处理能力。

NIO客户端的编程模型最大特点:依赖反置,松耦合带来性能提升。在请求流程协议中支持“票根”,也就是我们说的回执。例如,你今天面试完了,不需要你在阿里巴巴前台等着结果,直接留个电话,有消息就会直接通知,电话就是通知结果和服务请求者的关联手段。(此时阿里巴巴前台和会议室就会有足够的空间给其他人来面试,这就是资源)

         服务端使用NIO就不多说了,这里主要说一下在客户端的使用场景。两者是否真的有很大的差别,是否NIO有绝对的优势,其实还是和场景有关。简单说来就一个判断标准:应用对于通道的利用率是否够高。下面列了4种场景:

1. 一次请求数据量很少,服务处理速度很快。

2. 一次请求数据量很多,服务处理速度很快。

3. 一次请求数据量很少,服务处理速度很慢。

4. 一次请求数据量很多,服务处理速度很慢。

场景1,传输效率很高,服务处理速度很快,一次请求很快就被完成,采用NIOBIO,在性能优势上除了操作系统对NIO的优化以外,BIO连接池不输于NIO。在易用性上,BIO更加容易处理。(NIO的异步机制,就要求消息传输协议需要有会话码来提供异步处理入口选择如何处理)

场景2,传输过程比较长,消耗时间比较多,服务处理速度很快,因此交互的时间大部分都还是在数据通道传输上,由于NIO在传输过程中依然是串行化的,因此BIO的连接池优于NIO,同时NIO一个客户端只有一个通道,因此BIO开的连接池越大,并行处理能力越强,因此BIO效率比较好一些。

场景3,传输量比较少,服务处理比较慢,很明显这是通道利用率低的表现,NIO有绝对的优势,特别是在高并发下。信道和服务端客户端资源被充分利用。

场景4,传输量比较多,服务处理也比较慢,这时候可以发现信道利用率取决于服务事件和传输消耗时间的比例,这类场景某些情况下BIO也会优于NIO

单线程和多线程

         在使用多线程来优化程序的时候,是否考虑过多线程的使用场景,多线程不是万能药,在某些情况下还可能是毒药。使用多线程的过程中,需要考虑这么几个因素:

1. 资源竞争,复杂度增加。

为什么前面提到的NIO客户端在处理数据流发送和读取的时候都是采用单线程,数据流的发送和读取都是在一个数据通道上的,而读取和发送本身时间消耗是固定的(不论是多线程还是单线程),同时增加了复杂度(需要处理数据包整合问题)。这其实就是在资源上的串行化操作直接导致了任务的串行化,因此任务多线程反而起到了反作用。

2. 是否是关键路径的工作,占关键路径的比例。

首先,在优化以前需要考虑优化的内容是否是关键路径的工作,如果不是,那么增加复杂度实现的多线程模式,就没有价值。其次就是看是否是在关键路径中占有比较大的比例,同样的,还是投入产出比例(多线程带来的复杂度以及在高并发下的一些资源保护措施都需要很多的维护成本)。

3. 任务的合理切分。

NIO的客户端,接受数据的事件将会写得很轻量级,但是接受到数据然后分析数据还原成业务对象,则会通过线程池的方式来分别处理。就好比监听连接到来,和实际的去建立连接分成了两个阶段的任务,让事件型的任务单纯,快速执行,让与业务相关的部分通过多线程并行的方式提高处理效率。总的来说就是把任务划分成为系统性的任务和业务性的任务,前者消耗时间少,设计尽量简单高效,采用单线程处理即可,后者通常情况下在处理流程和资源上不冲突的情况可以通过多线程并行提高效率。

         优化应用关注点:

A.关键路径是否可以优化,关键路径的任务拆分。

B.关键路径上的单个任务是否可以拆分并行执行。(是否有资源竞争,是否会有流程上的前后依赖,是否增加复杂度引入新的不稳定因素)

C.系统资源和依赖外部系统是否会成为瓶颈。(单机的CPU,IO都会在一定的压力下成下降趋势,并行执行反而降低了处理能力)

因此,可以看到不论是MapReduce设计下的Hadoop,还是Erlang语言级别的特性,都尽量的希望任务之间可以并行执行,相互之间低耦合,通过异步事件消息通知方式来交互,同时数据没有共享,防止资源竞争导致无法并行高效处理。系统设计还是要根据场景来判断使用什么方式优化,越简单越好。

posted @ 2010-01-27 01:45 岑文初 阅读(3658) | 评论 (1)编辑 收藏

     摘要: 基于MapReduce的配置型日志分析组件  阅读全文
posted @ 2010-01-12 21:58 岑文初 阅读(3852) | 评论 (5)编辑 收藏

     摘要: TOP团队招贤纳士  阅读全文
posted @ 2009-12-11 15:52 岑文初 阅读(1899) | 评论 (0)编辑 收藏

    中午左右收到一个看我blog的朋友的邮件,最近他在研究mapreduce,然后想用hadoop来做一些工作,不过遇到了一些问题,我这边也贴一下他的几个问题,同时觉得自己把自己的一些看法分享一下,当然只是自己的一些想法,也许对新学习的同学有帮助。

   问题:

  1. 从Map(K,V)的方式来看,难道mapreduce只能做统计?
  2. 目前我想除了日志分析之类的功能外,还想做一个全文检索的功能,类似windows查询一下,通过关键字查询文件的位置即可(可能还要根据匹配度做排序),这个我很迷茫不知道怎么下手,痛苦ing
  3. 你的实践是一个单机模式,如果用户把一个1G的log已经上传到hdfs了,此时分割工作已经完成,只需要从client那里得到文件基本信息和块的location就可以了,那mapreduce怎么进行下去呢?

   我给回复的邮件内容:

   首先,MapReduce的思想和Hadoop的MapReduce的架构不是一个概念,说的具体一点也就是Hadoop的架构设计只是MapReduce的一个子集思想的实现。每个人都可以根据自己对MapReduce的理解去实现业务处理,简单来说多线程处理就是MapReduce的一种最简单的实现,复杂来说多机协调工作就是一种复杂的实现。

   MapReduce的思想里面最值得借鉴的:

   a.问题分而治之。(找到流程的关键路径,优化可以并行处理的工作)

   b.计算靠近数据。(这也是hdfs存在的最重要的特点,计算的转移往往要比数据转移廉价,特别是对海量数据的处理)

   c.数据规模化随着并行处理成数量级递减。

   剩下的内容就是各个框架对于非业务性需求的处理,例如容灾,如何尽量少穿数据协调处理等等。

   针对他提出的三个问题:

    1. Hadoop的mapreduce从架构上来说最适合的就是统计分析计算。做其他方面的工作需要考虑是否适合,而不是为了技术而技术,先有需求再有技术选型。
    2.  对于你这个需求直接用搜索技术实现就可以了,不一定要硬套在mapreduce上。
    3. 对于海量数据是否一定要到hdsf上,或者就简单得数据物理或者逻辑切割来直接处理,根据自己业务场景选择。hdfs的特点就是对文件切割,容灾,数据逻辑存储和物理存储无关性(便于扩容管理,同时也是计算靠近数据的技术保证)。

    是否使用MapReduce框架,HDFS存储关键还是看你是否真的需要,当现有框架对自己来说并不合适的时候可以对小规模问题定制MapReduce的处理,最简化就是你去多线程或者多进程处理问题,需求决定技术选型。

  

posted @ 2009-12-09 13:09 岑文初 阅读(2585) | 评论 (1)编辑 收藏

Author:放翁(文初)
Email:fangweng@taobao.com
Blog:http://blog.csdn.net/cenwenchu79 

 

当前问题:

1.       不小比重的Rest请求都是无效请求,全部接纳数据消耗比较多的时间。

2.       Multipart类型的大文件流请求无法做到合理快速过滤。(参数错误请求,数据文件过多请求,文件大小过大请求)

归结来说,TOP平台处理的服务在解析参数时比较消耗时间和带宽(客户端网络速度慢导致传输字节流比较慢,文件比较大导致带宽占用严重)

处理方式:

通过自行解析字节流方式来lazy化处理请求,减少无效请求对于解析参数时间消耗(导致web容器连接消耗)及带宽消耗。

优化目标:

         Get由于内容长度有限不列入在优化范围。

         优化Post方式的请求(普通的和Multipart),要求优化后:在正常请求处理上两者处理速度不低于传统方式,非正常请求在策略命中情况下(后面会谈到什么情况下优化失效),性能有明显提高。

具体实现:

        由于现在用的是传统IO模式,因此可以用流的方式来lazy解析和处理请求(NIOchannel + buffer package就无法lazy了)。




         一共有三个组件角色:

1. 请求处理配置策略:配置在解析参数时,优先的规则(参数可以从header,uri,post body中获取,相互之间的优先性),异常抛出规则(字节流长度,文件大小,文件个数限制等),字节流解析模块的参数配置(字节流解析的窗口大小,超时时间等)。

2. 线程上下文:用来保存处理过的请求参数。一来复用,二来也是由于请求字节流处理不可逆(不保存字节流副本),必须保留。

3. Http请求字节流解析模块。根据具体的配置以及解析策略来解析字节流,同时将解析结果保存在线程上下文中。主要的实现代码在于对Post消息体逐步解析部分(普通的Postmultipart

压力测试结果:

    正常请求场景( 100并发用户,multipart 文件大小300k,当前业务场景这个值已经满足了):

普通post的处理能力1000TPS。(servlet方式处理差不多,不过有波动)  

  multipart处理能力610TPS。(apache开源项目fileupload,处理能力400TPS左右)

错误请求场景

         异常情况的处理有了很大提高,对于远程客户端传输较慢或者是大流量图片的错误请求都有很大的优化。

优化存在问题:

1. 参数缺失导致优化失效。

2. sign类似的交验,导致获取所有的参数。

3. 当前图片限制在300k,由于考虑处理速度快,就都没有设置超过阀值存储到本地,因此在高并发大流量的情况下也会有内存问题,当然已经做了部分保护。

针对上面的两个问题,作了部分的协议限制,对于API2.0希望将所有的系统参数和业务参数区分开,放入到Http header中或者url中,这样可以避免系统参数缺失导致优化失败,同时大量过滤系统参数出现问题的无效请求。

Sign类似的交验放在流程最后,避免过早获取所有参数。

作安全保护,设定简单丢弃或者io交互来缓解这个问题。

         这部分内容还有很多可以做得工作,其实最初的目的就是为了防止系统对于无效请求的处理消耗,我想在很多系统都会有这样的问题,利用缓存设置黑名单防止攻击也是这样的初衷。因此这点可以考虑在很多系统设计的时候都作一样的优化,对正常的不能优化,起码对错误的可以做一些优化,防止在异常请求高涨的时候,系统被击垮.

posted @ 2009-12-08 01:51 岑文初 阅读(2238) | 评论 (2)编辑 收藏

Author:放翁(文初)
Email:fangweng@taobao.com
Blog:http://blog.csdn.net/cenwenchu79


其实想说这句话很久了
,和很多同事接触,有时候或多或少的都会发现大家会陷入在自己的一亩三分地里面.

         主要表现得症状

1.       PD的需求就是目标,踏实的实现,不懂的就猜。

2.       经验盖过一切,设计系统就是要够完备够复杂。

从开发人员角度来看,第一种人多半比较有自己的想法,同时也有不少的工作经验,同时可能对技术比较着迷。另一种人多半是刚刚工作或者经验不足,要么就是习惯性把工作当任务,而不是爱好,写程序也就是一份赚钱的活。但看起来其实各自都在自己的一亩三分地上捣鼓,忘记了作为一个开发人员最基本的原则:“满足客户需求”。

先说1类型吧,在我们的Team有一个刚毕业一年多的同学,很勤奋,不论从学习以及工作,实实在在,踏踏实实。我们这边来需求,通常大需求我们都会全体过一下,一些小点的需求他就自己考虑一下就作了。那天正要上线,突然说了一下设计修改的内容,发现不仅满足不了PD原有的需求,而且给系统带来了缓存暴增的隐患。然后找来PD一谈,其实他要的功能已经在现有系统中已经实现,只是需要做部分的修改,而不需要新的去建立一套机制。这样的情况其实在前前后后出现了不少次数了,但其实一直没有和他细谈。后来我下班时候和他一起回家的时候说:“很多时候, PD为了让你理解,从开发的角度想要去描述一个需求,但其实最终失去了他自己想要的东西。因此对你来说第一步不是急忙的去考虑如何实现PD的想法或者和他争论他的设计是否合理,而是需要先问他:你想要什么,想要实现的东西最终目的是什么,能满足客户的什么需求?当他能够说清楚他想要什么,也知道要的东西能给客户带来什么价值的时候,我们再回过头来看,究竟应该怎么做?”这其实和我每次和同学分享一些设计的时候步骤是一样的,首先为什么要这么做,然后才是考虑如何从我的目标去寻找行动的方法方式,不然你会发现你和别人讨论了许久的东西,实现出来的时候已经背离了你的目标很远。因此在做任何需求或者设计的时候第一个问题就要问自己为什么要做,作的过程中时刻要记得我的目标是什么。这让我想起了我在离开阿软的那些日子和王坚博士谈话以及听他的一些对于设计的理念,很多时候还没有到规模化的情况下,先解决客户的需求,在解决客户需求以后,逐步的去考虑规模化问题的设计。(当然不是说第一版设计就可以随便作,良好的基础能够提升后续改进的速度)。

二类型的就比较多了,其实是很多开发人员的通病,包括有时候我自己也会陷入这样的误区。通常情况下有两种场景会陷入这样的误区,同时当事人却又不愿意改变。第一种情况就是觉得自己有不少的经验,同时对技术很执着,希望设计出来的都是很完美的,一次发布就可以满足个12年,但其实从这些年的设计角度来看,首先系统都是不断迭代进化的,因此一步到位的说法基本上不靠谱(除非就是一模一样的场景代码重复使用),其次系统的架构要做的足够灵活,通常情况就需要先做核心功能,预留出足够的空间和切入点,这样对未来扩展和需求变化有足够的适应度。从这两点来看,其实设计初期就是要求找到客户最想要的,扩展可以实现客户可能要的,防范客户没有估量到的。但这其实就需要和我们的产品设计师有充分的交流,好的产品设计师不会告诉你你怎么去实现,但是他会告诉你我想要的是什么,这些能给客户带来什么,这时候你可以告诉他我能够通过什么方式来满足你的需求。这样的开发和产品设计交流的结果才是技术化的产品,大家各司其职,同时也通晓对方领域的一些情况,对对方领域的只能给出建议,不是指导,这点在TOP我很庆幸有很好的黑羽同学,我们的交流就是这样产生良性互动。这有点撤远了,刚才说了第一种场景,然后说说第二种场景,就是初期其实大家都没有明确细节,但是在实施过程中开发人员会根据自己的接触面来选择一些技术和架构设计,最后看起来很复杂,很完美,但其实越是复杂的设计背后有越多的隐患。但是此时因为已经设计好了,就不愿意再去简化,也不愿意听任何人的意见,其实这是很危险的。我过去也犯过类似的错误,但是其实当你冷静下来,想想那句话,我们的目标是什么:“满足客户需求”,这时候你就会考虑,这么复杂的系统会不会给客户带来更多的不稳定以及复杂度,其实客户不关心你背后如何实现的,但是你需要满足客户的最基本的需求,用起来方便,高效,实实在在提供了解决问题的手段。

今天下午面试了一个外部的同学,工作年限比我长,看了简历也经历了很多项目,同时在描述的时候写了对高并发,分布式等等都很熟悉和热衷,我开始看了简历就担心,可能我这边不一定要他,因为我怕他开口就是说一大堆如何做高并发和分布式的内容。在我看来如果你没有搞清楚你什么时候要用牛刀,什么时候要用剪刀的人,和你谈论牛刀的构造其实没啥意思,因为在我看来,技术只要你肯花时间去学,没什么学不到的,但是做事方式和项目设计经验却是长时间积累的。幸好今天和他一谈,他对于技术的态度以及架构设计的思想都和我想的比较接近,不是为了技术而技术,不是为了过程而过程,了解如何从简如繁,再从繁入简,最终能够找到自己的目标。当然后来还是谈了很多技术细节的问题,毕竟干活还是要一个好手,作了那么多年如果没有经验和技术积累也是很可怕的事情。最后我问了他两个问题:1.你学习一个新技术的过程是怎么样的?2.你和你同事如果在设计方案上有冲突你怎么解决?他告诉我他学习新技术首先会去考虑这个技术的特点是什么,和其他技术的差别,他的擅长领域是什么,这样才能够用到实处。第二个问题他和我说就是开会讨论,最后大家群体决定。我对他第一个问题感到很满意,因为我就需要这样的同事,第二个问题我给了他一个建议,其实在很多时候,将别人的架构设计的优点融入到自己的设计中,不再以方案作为边界,那么大家最终就很容易达成一致,因为你在接受别人的思想时其实能够看到自己的不足,同时对待别人不是用否定的态度,会让你更容易得到认可和接受。(这点作起来需要不断的改变程序员自身的好胜个性,我起码还是出于变化中

我记得我小时候上政治课的时候,老师给我们划分了三种人:有能力但是没有道德的人是危险的人,没有能力但是有道德的人是对社会无害的人(觉得像葛优说的那个对社会无害的海龟一个概念),有能力同时也有道德的人是对社会有益的人。我觉得其实程序员也就可以从两个纬度看:

1.       有能力,有经验,对技术有追求。

2.       对产品化和客户没有任何感觉。

拥有了素质1但是没有素质2,那么最多也就只能说是试验室的花朵,在大学搞搞研究还不错,实际要做出产品来可能就是纸上谈兵,好钢始终用不到刀刃上,有力没地使。

素质1有所欠缺,素质2很明晰,对自己目标不断追求,其实这样的人,有时候笨鸟也会飞的比聪明的鸟更高。

拥有12的人,当然就是最好的人,只需要学会做人那么就可以发挥自己的能量。(程序员有时候就是很难改变自己的个性,去学会如何沟通和理解)
         最后一类就是自以为有12的人,这类人最怕就是面试的时候被考官通过,那么后续的问题就大了。

说了怎么多,其实也无非想说出一个程序员这些年的经历,从做开发到做基础平台,到做业务平台,该怎么踏实做事,该在什么时候找到自己的瓶颈,该在什么时候改变自己的状态,都需要自己好好的让自己冷静下来想想。做基础平台需要耐得住寂寞,同时也要知道自己是有客户的,服务不好客户,那么基础组件平台就是玩具。做业务平台需要学会去分析和沟通,需要去了解每一个层次的设计如何协作,同时在兼顾业务需求的同时满足隐性需求(稳定性,可用性,响应速度,规模化等等)。但归根到底,能给开发人员不断能量的不是技术本身,而是你用技术给你的客户带来的价值,对你的认可是长期做事的一个最基本的动力,因为当你现在觉得纯做技术能够支持你不断向前走的时候,其实在不远的将来你会体会到原来过程和目标是同样重要的。走出自己的一亩三分地,给自己多一点的空间,会让自己看得更远,走的更高。

posted @ 2009-12-08 00:54 岑文初 阅读(4228) | 评论 (6)编辑 收藏

   今年blog更新的速度比去年慢很多,当然最大的原因就是工作的转变。当选择留在云公司还是去淘宝,自己做了很快的抉择,去淘宝。其实在阿软的后面这一年,对自己来说是一个技术提升的阶段,工作任务不紧,技术预研范围较大,但对于自己这么一个已经到了30的人来说,应该是把技术转变为产品的时候了,因此义无反顾地选择了TOP作为我新的开端。

    其实每个人都会有自己不同的阶段,任何阶段都有自己的目标,同时当你发现在一个阶段停留很久,都没有什么突破,或者渐渐失去目标的时候,那么就需要考虑如何找到新的起点。对我来说,技术追求和提升是没有止尽的,但是需要真正的将所学的作出一点实在的产品,同时在参与产品团队的过程中,学会沟通,交流,分析问题,全面地看问题,这些也是不可缺少的成长经验,如果仅仅局限在狭隘的某一个技术立领域,那么就和普通的学生无异。

    到了TOP,自己的工作分成了三大块:1.救火及防火。2.整体架构支持。3.核心代码的编写。前期花了不少时间在1上,同时和各个Team交流,参与各个团队的关键性设计评审,以及对平台的统一规划,让我实实在在的作了一点2的事情。(说道实实在在,记得在阿软很多团队都抱怨我所在的架构组整天派一个人挂个名字,然后就算是架构支持了,当然这有很多原因造成,并不一定是负责架构的同学的问题)。对于3这点当然是自己最乐意做的,也是自己一直告诫自己要不断提升的,不论自己有多少理由说自己忙碌,写代码是我们这种人的生命所在,不然就会漂浮在空中,渐渐的走向“另一个世界”。 但自己觉得其实还少了一块,就是对业界的发展深入了解,这会让我看的不够远(幸好我们的产品经理黑羽同学总还会给我一些新的思路),到了年底将会多花一点时间作这部分内容。

    去年年底我写了关于对于Open API的思考和探索的一篇文章作为年底总结,今年一样,对于当前自己的工作将会有一份总结和规划,即是对今年平台发展的一个回顾,也是对平台未来的一点思考,大致已经列了一个纲要,对外可能部分内容不能全写出来,不过就算不写细节也会将一些思路写一下,大家可以相互探讨一下。这部分内容也将会成为我12月份参加淘宝内部淘宝大学讲课的内容,希望能够将今年新进淘宝的同学吸引到TOP来,为TOP增加人气。

   下面是一个mind 图,大致描述了一些内容:

posted @ 2009-11-27 00:58 岑文初 阅读(2930) | 评论 (2)编辑 收藏

     摘要: 常用模式的细节问题看设计稳定性  阅读全文
posted @ 2009-11-10 01:52 岑文初 阅读(2866) | 评论 (4)编辑 收藏

在自己的blog上做个招聘广告,TOP平台架构Team欢迎各位资深或者刚毕业的对TOP有兴趣的同学加入,可以直接给我留言或者发mail到fangweng@taobao.com,非诚勿扰^_^,同事可能比老婆相处的时间都要长。对了,请附加上你的简历,方便继续沟通。
posted @ 2009-10-30 15:51 岑文初 阅读(1328) | 评论 (2)编辑 收藏

     摘要: Author:放翁(文初) Email:fangweng@taobao.com Blog:http://blog.csdn.net/cenwenchu79   闲话:(如果图片看不清楚可以看另一个blog,因为图片在家,这里上传就只能转贴了)          为什么又叫做什么…的点滴,...  阅读全文
posted @ 2009-10-30 12:27 岑文初 阅读(3658) | 评论 (6)编辑 收藏

     摘要: 上海校招回来  阅读全文
posted @ 2009-10-13 21:27 岑文初 阅读(1456) | 评论 (4)编辑 收藏

     摘要: 客户端NIO实践分析  阅读全文
posted @ 2009-09-24 08:57 岑文初 阅读(3370) | 评论 (7)编辑 收藏

     摘要: 应用架构设计“防火”经验分享  阅读全文
posted @ 2009-08-27 00:59 岑文初 阅读(3165) | 评论 (5)编辑 收藏

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

    很奇怪,来到淘宝,都是熟人,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 岑文初 阅读(1160) | 评论 (1)编辑 收藏

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

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

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

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

 

 
posted @ 2009-08-06 05:12 岑文初 阅读(1020) | 评论 (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 岑文初 阅读(2269) | 评论 (1)编辑 收藏

     摘要: “软”负载均衡学习点滴  阅读全文
posted @ 2009-08-04 22:30 岑文初 阅读(2076) | 评论 (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 岑文初 阅读(3378) | 评论 (2)编辑 收藏

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

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

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

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

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

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

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

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

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

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

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

        blog已经快两年了,起初仅仅是为了自己“备个案”,结果慢慢演变成为了“分享成瘾”。前几天一个朋友给我的blog留言,谈到希望在新年里能够看到的不仅仅是我对技术的分享,更希望能够看到对于技术学习、职业发展的规划。因此想到了写一点什么分享一下自己这些年的一点点“收获”,周星驰的喜剧之王里面说到他是一个演员(虽然被叫做跑龙套的),我想我,就一个写代码的。

爱这行

       从事任何行业都一样,只有真正的爱上了这份工作,才会投入热情,才会在顺境中自我警醒,在逆境中寻找突破。这个行业的竞争很激烈,你停下来走,别人就立刻会跑步超过你,没有对这一行业的一种热情,就很难在困境中保持一种执着的态度坚持到底。

踏踏实实“扎马步”

       今天无意中看了“校长”的“程序员&司机”,其中谈到了关于程序员速成的问题。其实速成班毕业的 “系统杀手”早已在遍布大江南北,只是在互联网时代,互联网的应用型软件生命周期越来越短,业务驱动主导的情况下,这种速成方式看起来反而提高了企业生产效率。但这样的人才也就只能写几个Facebook上的插件应用或者iGoogle上的Gadget,真的要出GoogleAmazonYahoo改变互联网世界的企业,还是需要踏踏实实先学“扎马步”的人。

       很多在学校的同学或者刚刚毕业的朋友都看什么热门学什么,SpringAJAXHibernate等等,又有多少人在看Spring之前把J2SENIOXMLCollection等先好好学习一下,在看AJAX之前把Http协议、DTDXML Schema好好看一下,在学习Hibernate以前先把J2EE事务规范搞清楚。Java最大的好处就是开源,能够让人们站在更高的起点来作出更多的创新,但是对于学习者来说,不了解自己站在什么上面的时候,可能摔下来会很痛。在用的时候多问一些为什么,在遇到问题的时候多找找原因,在了解以后多提出一些优化的方案,这样才会进步的更快,走的更远。

       记得我前一阵子回家的时候和妈妈聊起最近的工作,虽然妈妈不太明白,但是也知道我现在做的东西技术含量比较高,嘱咐我“千万不要什么都教给自己的同事,徒弟带出就不要师傅了”(这当然是老一辈的观念了)。我和她说:“不要担心,这种学的会的不教迟早也会,学不会的教了也学不会”。其实这里说的学的会的就是技术,而学不会的就是经验和能力。这个行业的人在日积月累过程中并不会去比较掌握的知识面有多广多深,毕竟这行业更新很快,其实能力强的人在多年的学习中就积累了很多的找问题,分析问题,总结问题,提出建议,发掘创新的能力,这些才是这行业人在发展中最宝贵的财富,也是一个人成长的标志。开始的过程中,踏踏实实地“扎马步”,了解一些最基本的知识,那么上层技术的发展对于他来说仅仅只是一个短暂的学习过程,甚至可以触类旁通。因此还是要奉劝每一个新入行的同学,踏踏实实,静下心来做技术,就算工作安排得都是一些浮躁和重复的工作,用高效的方式来结束那些重复劳动,多留一些时间给自己打基础。

逆境养兵、顺境攻城掠地

       普通人的工作经历通常都是起伏不定的,一个人的能力是否能够得到体现,不仅仅靠自己的努力,有时候也需要“天时”、“地利”。马云比较有名的一句话:“今天很残酷,明天更残酷,后天很美好,但是大多数人死在明天晚上,看不到后天的太阳!!!”,其实也在说明一件事,就是很多时候需要一种坚持的精神才能得到宝贵的机会。

今天是我进入阿里巴巴满3年,这3年让我感触很深的是:1.逆境不要气馁,厚积薄发。2.顺境不要懈怠,一股作气,把握机会展现自己最大的能力。3.在逆境和顺境的转换过程中,创造机会,不要坐等机会,要学会不在其位,也谋其职。最后一点就拿我自己的亲身经历来说,我原来就职于一家通信公司,因此对于互联网应用的开发和架构设计要比很多人弱,进入阿里巴巴以后工作了半年(主要作业务开发),正好阿里软件创立,当时被分配到了阿里软件第一个产品负责客户模块,当时的应用是通过MDA框架配置搭建的,开发人员很大程度上不需要自己做太多的编码,但是这个平台并没有搭建过如此复杂的大型应用,因此存在着不少问题,当然这些问题都是通过业务产品线的人反馈给平台部的人,当时平台部门人员很少,但是却要修复和完善诺大一个平台,因此常常搁置开发人员的反馈。当时在自己工作之余就琢磨和研究平台,同时跟踪调试平台,最后直接给出解决方案,逐渐的就融入到了平台开发中,最后被吸收到了平台部门,进入平台部门以后遇到了两位很好的老大,根据我的特质给我安排了研究和学习的工作。接下去就是不断地参与阿里软件各个基础平台的构建,核心技术的研究和探索,找到了兴趣和工作的最佳结合点。因此,当你困惑的时候首先不是去抱怨,而是审视一下自己是否还有作的不够的,是否还有可以提升的空间,多给自己制造一些机会,也许我们不用等到后天,也不会死在明天夜里,明天早晨我们就看到了太阳。

海纳百川、冰冻三尺

       很多朋友可能听老师或者前辈也说过类似的话,就是作为一个技术人员要广也要钻。就好比现在很多人都要DB Scale out,同时也要Scale up。我从自己的角度来说一下广和钻的看法。广:1.要有容人之量。(很多时候程序员最大的毛病就是喜欢在技术上比较,未尝不是好事,但是一个人的能力总归有限,多看看别人的,多听听别人的,也许能够让自己少用时间获得更多的收获,特别是自己战友的声音)2.触类旁通,多问个为什么,多跨过界去学习。在阿里巴巴,PDSADBAUI等等职位各司其职,作为开发的我们其实也应该去了解如何去画Use Case,如何假设服务器和应用环境,如何写一些略微复杂的SQL,了解一些DB的特性,如何能够简单的作出一些基础的页面,使用简单的css来美化一下门面。这些就是需要多跨过界,多虚心的去学习。钻:1.本职工作技术一定要扎实,每作一个技术点就要把技术吃透,同时延伸开来,发掘更多的技术亮点。2.多接触新鲜事物,但是有选择的去了解,有目的的去学习和实践(目的的源泉就是工作的需求)。3.学会分享,一个人自己搞懂一个技术很容易,一个人要把他熟悉的技术写下来就会发觉原来自己还有那么多没有搞清楚,一个人如果要把写下来的东西宣讲给别人听,他就会发现,原来写下来的仅仅是那么一小块,因此学会分享,从自己了解,到记录分享,到演讲传播就是一个不断深化和广化的过程。个人觉得小公司锻炼人(啥都自己干),大公司培养人(该干的要干好),因此自己常回头看看自己在广和钻上的不足,可以让自己进步的更快,学的更全面。    

       学中医积累经验,学西医寻找突破

       中医以对人体经络血脉了解为基础,通过望闻问切来寻找病理根源,行医年限越久,找问题解决问题的经验越强。西医以科学技术为手段,通过试验化的方式不断寻找突破,并且将成果积累并且传递给更多的人,但是否年限越久越有能力,或者是使用得器材越广越资深,这点全要看个人对于医术的理解,如果仅仅停留在对器械的使用和对成果的依赖,那么只会成为一个庸医。当然这里绝对没有对中西医的差别化或者评价,仅仅要说明的是,在手段丰富的情况下,容易忽视了本质,只看到了皮毛,积累的时候多一些追根溯源,站在别人的成果上才更踏实,因此在对经验积累上向中医多学一些,在寻找突破,传播技术上多学一点西医的风格。不过说到低,还是要看学习的人,静的下心,沉得住气,才会有积累,才会有突破.

不做一个纯粹的“技术人员”

       不做一个纯粹的“技术人员”,其实也就是说要培养自己多方面的能力,我仅仅把自己想到的一些点列出来说说:

1. 项目产品化的思想。现在就算在学校里面给导师作项目都讲究一个商业价值,更不要说在企业里工作。作为一个开发或者架构师最重要的就是要有产品化的概念,这也是项目是否成功的关键。软件的目的是为人服务,如何服务的好,那就要以一个产品的思路去做项目,而不是作为实验室的实验品,为客户提供好服务就会给公司带来商业价值,对自己的工作也会有很好的肯定。这是一个良性循环,反之则是恶性循环(多赢变成多输)。如何做到产品化,首先就是需要去了解需求,而不是布置需求,其次就是设计时多听取一些不同角色的意见,最后就是在客户的反馈过程中反省。

2. 多一些设计,少砌两块砖。代码写的再好,其实也只是用砖块砌墙砌的比较好罢了,这年代已经不会为了节省两块砖而给一个优秀工作者了,同时技术的日新月异,总是摆弄技巧,学习花拳绣腿已经跟不上时代了。多了解一些行业背景,多参与一些架构设计,将业务设计用良好的架构体系来实现,那才是一个称得上有能力的技术人员。

3. 学会前瞻,学会自己找事。记得我刚进平台组,最不适应的就是我的老大基本不太给我布置太详细的任务,这就好比进入大学,老师不给作业,自己反而心里没底了,其实自己找事的过程就是一个自己学习的过程,当我一天下来感觉没干什么,没学到什么,心里就开始发虚。如何能够前瞻性的去选择一些目标,如何对现有情况提出一些创新和建议,都是一种更高能力的要求。现在SIP组也是一样,在我们这个组里虽然现在每周还是布置一定工作,但是我对其他两个同学的要求也是希望能够有前瞻性,学会发现问题,预防问题,更甚者就是提出创新。当你具备了这种环境的时候,你就需要锻炼自己的能力了。

4. 做个让老大放心的人。这点也许很多人和我一样在业务上很早就让老大觉得可以安心睡觉了,但是其实另一方面,如何在商业角度看问题,如何培养新人,如何协调部门合作等等,都会让你的老大更加安心。另一方面来看,其实在这些能力的培养过程中,你不再局限于业务水平的提升,让自己在更多方面更加成熟。

六脉神剑

       今天是我进入阿里巴巴3年整。在阿里巴巴有个说法,只有在阿里巴巴工作了3年,才能算是一个真正的阿里人,因为理解阿里巴巴的文化,需要三年时间的沉淀。这里就从一个写代码的角度分享一下阿里巴巴的六脉神剑文化。

客户第一:如果你是做架构的,作平台的,作开发工具的,那么客户就是和自己一样的开发者,多学习一下开源项目的精神,多从使用者角度去考虑问题,那么你的东西才会被更多的人认可和使用,永远不要去做一个“玩具”的开发者。如果你是做产品的,那么就多听,多想,多问,永远不要急着去写代码。

拥抱变化:敏捷开发的基本原则。互联网应用尤其如此,不要害怕变化,在需求和架构之间找到平衡点(说起来比较容易^_^)。

团队合作:一个人的力量始终有限,分享,交流,合作能够让自己事半功倍,学的更多,看得更远。

诚信:说到就要做到,做了就要做好,做软件开发一样也需要有责任感,贴满狗皮膏药的代码上如果注释是你的名字未来也会给你蒙羞。踏踏实实地用心去写代码,去设计架构,不经意间得到的要远远比那么一点工资来的多。

激情:还是那句话,你如果不爱这行,乘着年轻赶快转行。

敬业:专业执着,精益求精

很感谢各位能看完这篇感受分享,以上都仅仅是个人的一点感受,能够引起共鸣那么证明我们的经历很相似,如果能够给到你一点帮助,那写这些就真的有意义了。不论你在别人眼里是一个资深架构师还是开发人员,其实如果你爱这个行业的话,你应该就是一个写代码的,但是每个人的经历都是一本“写代码的自我修养”,珍惜自己的选择,让自己在兴趣和工作中找到最佳结合点。

posted @ 2009-03-11 02:38 岑文初 阅读(4998) | 评论 (20)编辑 收藏

 

       今天看了“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和分区的对应关系被保存,通过查找目录可以得到分区信息。适合扩展,就是增加查询损耗。

如何将数据分布的尽量均匀,如何平衡各个服务器之间的负载,如何在新增存储机器和删除存储机器的时候不影响原有数据,同时能够将数据均摊,都是算法的关键。在分布式系统中DHTDistribute Hash Table)被很多人研究,并且有很多的论文是关于它的。

数据的横向切分给应用带来的问题:

1. 跨区的数据查询变得很困难。(对于复杂的关联性数据查询无法在一个请求中完成)

2. 数据一致性和引用完整性较难保证。(多物理存储的情况下很难保证兼顾效率、可用性、一致性)

3. 数据分区之间的负载均衡问题。(数据本身的不均衡性,访问和读写的不均衡性都会给数据分区的负载均衡带来困难)

4. 网络配置的复杂性。(需要保证服务器之间的大数据量频繁的交互和同步)

5. 数据备份策略将会变得十分复杂。

解决这些问题当前已经有的一些开源项目:

1. MySql Cluster,解决读写分离问题已经十分成熟。

2. MySql Partitioning,可以将一个大表拆分为很多小表,提高访问速度,但是限制与这些小表必须在同一台服务器上。

3. HSCALESpock Proxy都是建立与MySql Proxy基础上的开源项目,MySql Proxy采用LUA脚本来进行数据分区。

4. HiveDBMySql分区框架的java实现。

5. 另外还有HyperTable,HBase,BigTable等等。

Netblog几个需求:

1.              需要灵活的可扩展性。对于存储增加减少需要能够动态的及时实施,因为数据量增长很快,如果策略会导致数据失效或者部署需要重新启动,则就不能满足需求。

2.              不想引入全新的数据层和与原有系统不匹配的抽象层,因为并不是所有数据都需要切分,仅仅在需要的情况下通过API的方式来透明切分数据。

3.              分区的主键需要可配置。

4.              需要封装API,对开发人员透明数据切分的工作。

      Netblog Sharding的实现




    上图就是
NetblogSharding的结构图,主要分成了三部分:ShardSharddbSharddbhostShard就是一个表,里面存放了部分用户数据。Sharddb是一个表的组合就像一个虚拟的DBSharddbhost是具体的存储分区。ShardSharddb可以根据负载的情况被移动到不同的host中去。

       对于Shard的管理,Netblog采用的是目录查询的管理方式。目录信息也存储在MySql中,同时会通过互备,Memcache,集群来确保安全性和高效性。

       Shard Table API采用了多一层的映射模式来适合各种不同属性的查询情况。数据和记录在数据库中存储除了UserID以外还有对应的ItemIDItemID的作用就是定义了具体获取数据的字段信息,例如关联照片表时,ItemID就是PhotoId,关联视频表时,ItemID就是videoID

       一个获取用户id26博客信息的范例:

1Where is user 26?

   User 26 is on shard 5.

2On shard 5; Give me all the $blogIDs ($itemIDs) of user 26.

That user's $blogIDs are: array(10,12,30);

3On 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-mastermaster-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降低框架复杂度。

另一方面,如果发现了业务增长情况出现必须要扩展的趋势,那么就要尽早着手去实施和规划扩展的工作,并且在切分和扩展过程中要不断地去优化和重构。

后话:

       其实任何架构设计首要就是简单直接,不过度设计,不滥竽充数。其实就是要平衡好:可用性、高效性、一致性、可扩展性这四者之间的关系。良性循环、应时应事作出取舍和折中。用的好要比学会用更重要,更关键。

posted @ 2009-03-04 00:58 岑文初 阅读(1996) | 评论 (2)编辑 收藏

 

目标:

         根据四方面的配置调整,观察SIP5.5在高并发下的性能情况。

         由于SIP接收的请求都是服务型处理请求,因此认为Apache+Jboss只会带来多余的转发损耗,所以正好这次也作一个验证,看看Apache+JBoss是否不适合于这种纯动态服务请求的情况。 
        四方面环境比较:

1. JBoss APR模式与Http1.1模式性能差异。(确切来说应该是JBoss内置Tomcat采用APR的情况)。

2. 是否采用Apache+JBossApache不同的转发模块带来的性能差异。

3. Memcached Client版本优化后对性能影响。

4. ISP有不同延时对于SIP的性能影响。

前置条件:

SIP版本5.5,并发用户600ISP默认耗时20msApache配置和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.22.4版本在单独测试的环境下:500并发用户,每个并发用户1000getset,性能相差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的方法需要有足够的“理由”和“度”。Java1.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模式对于服务器处理能力有很大的影响,EpollUnix 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的管道,UnixSocket)Tomcat有配置监听器直接会检测APR模块是否存在,在bin目录下建立native目录,并且放置对应的so或则dll即可。

posted @ 2009-03-03 20:14 岑文初 阅读(1816) | 评论 (2)编辑 收藏

    在大型网站中常常会遇到大流量的数据输出问题,过于频繁的输出到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/ 下载。

posted @ 2009-02-12 21:09 岑文初 阅读(2467) | 评论 (5)编辑 收藏