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

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

Author:放翁(文初)

Date: 2010/4/14

Email:fangweng@taobao.com

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

这部分是结果,大家可以当看倒序的电影,后续会有前篇给出。

Web服务异步化

         包括两部分,数据传输层异步化(大家已经熟知的NIO),Http业务请求异步化(continuationsservlet3.0)。服务异步处理我将会有一个详细的说明文档(服务异步化的概念,服务异步化的几种标准实现,服务异步化容器的特点),后续给出。

Web服务异步化测试原因

         TOP应用特殊性:

1.自身服务能力由后端的服务能力决定。(对同步Web请求的转发)

2.后端服务部署等同性,但要求服务互不影响。

第一点导致TOP无法预估自身服务能力(不同后端服务处理速度下的TOP有不一样的支持能力),同时也无法应对在后端服务异常的情况下,整体的服务质量。

第二点导致TOP只有在物理上分隔不同服务提供者所对应的TOP集群(资源浪费,同时无法动态调整资源来满足服务变化情况)。

         因此需要对TOP实施web服务异步处理的测试。这里简单的说一下服务异步化的使用场景需要满足的几个特点:

1.       处理耗时大多消耗在于对后端或者外部服务资源的请求上。

2.       后端或者外部资源在更多的流量下不会成为瓶颈。

TOP来解释一下:TOP自身处理主要包括路由,安全,流控等,但是最耗时的是在请求后端各个淘宝团队的服务。其次当前后端服务能力尚未达到真实的处理高峰,因此很多请求被堵在TOP平台,特别是当某些服务异常的时候,另一些服务就会被拖累无法得到充分利用。(当然我们有流控,发现后端服务能力已经成为瓶颈的时候可以对单独服务作限制)。

长话短说,上测试结果……

环境说明

Linux 2.6.9-55.ELsmp

4 Core

4 G Memory

JDK 1.6.0_07

测试工具:loadRunner 9.5

测试涉及到了四种容器部署:后面都会用缩写在测试结果上注明

1.       Apache + modjk + Jboss(后面缩写为Jboss)

此模式Apache配置如下:

<IfModule mpm_worker_module>

ServerLimit          80

ThreadLimit          128

StartServers         10

MaxClients           10240

MinSpareThreads      64

MaxSpareThreads      800

ThreadsPerChild      128

MaxRequestsPerChild 10000

</IfModule>

   Jbossweb容器配置如下:

<Connector port="8009" address="${jboss.bind.address}" connectionTimeout="8000" protocol="AJP/1.3" maxThreads="500" minSpareThreads="40" maxSpareThreads="75" maxPostSize="512000" acceptCount="300" bufferSize="16384" emptySessionPath="false" enableLookups="false" redirectPort="8443" URIEncoding="utf-8"/>

Jbossweb部分以APR模式启动。

2.       Tomcat6APR

关键配置如下:

<Executor name="topThreadPool" namePrefix="top-exec-"

        maxThreads="500" minSpareThreads="40"/>

    <Connector port="7777" protocol="HTTP/1.1"

               executor="topThreadPool" connectionTimeout="20000" acceptCount="1000"

               redirectPort="8444" />

3.       Tomcat7 RC 4APR

关键配置如下:

    <Executor name="topThreadPool" namePrefix="top-exec-"

        maxThreads="500" minSpareThreads="4"/>

    <Connector executor="topThreadPool" port="3333" protocol="HTTP/1.1"

               connectionTimeout="20000" acceptCount="1000"

               redirectPort="6443" />

4.       Jetty7

关键配置如下:

<Set name="ThreadPool">

      <!-- Default queued blocking threadpool -->

      <New class="org.eclipse.jetty.util.thread.QueuedThreadPool">

        <Set name="minThreads">10</Set>

        <Set name="maxThreads">500</Set>

    </Set>

    <Call name="addConnector">

      <Arg>

          <New class="org.eclipse.jetty.server.nio.SelectChannelConnector">

            <Set name="host"><SystemProperty name="jetty.host" /></Set>

            <Set name="port"><SystemProperty name="jetty.port" default="6060"/></Set>

            <Set name="maxIdleTime">300000</Set>

            <Set name="Acceptors">2</Set>

            <Set name="statsOn">false</Set>

            <Set name="confidentialPort">8443</Set>

            <Set name="lowResourcesConnections">20000</Set>

            <Set name="lowResourcesMaxIdleTime">5000</Set>

          </New>

      </Arg>

    </Call>

附注:

Asyn表示异步模式,syn表示同步。Asyn中还分成resumecomplete两种方式,后续在介绍技术背景的时候详细描述。

         对于服务端的load不是每一个测试都做了记录,选取了最全面的1500并发用户做了测试。

         最大服务请求处理数是通过应用自身实现,具体代码可以参考后面的代码附件。

测试结果如下:

场景1500 并发用户场景下,后端服务一次请求消耗3秒钟

容器

模式

TPS

Average Response Time(s)

Average Throughput(byte/s)

最大请求处理数

Success rate

Jetty7

asyn(resume)

162.8

3.008

38430

500

100%

Tomcat6

syn

163.3

3.005

18453

500

100%

这个场景测试的目的是比较在线程池资源足够的时候,异步和同步的差别。(也就是TOP服务器所有的资源处于正常服务,前台请求没有因为前段连接被消耗完,导致服务质量降低)

         可以看到,在TPSResponse Time上两者基本上没有太大差别,TPS就等于500/3=167左右(3秒一个请求,因此用这种简单算式可以算出),响应时间也较为正常。当时我发现在每秒吞吐量上有些差别,后来单个测试case跑了一下,发现是返回的http header比较大,应该是在做异步化时重入等作的一些标识(后面其他容器的异步化也是一样)。

         最大处理请求数都在服务端后台看到是500,等同于最大的并发用户数。

场景21000 并发用户场景下,后端服务一次请求消耗3秒钟

容器

模式

TPS

Average Response Time(s)

Average Throughput(byte/s)

最大请求处理数

Success rate

Jetty7

asyn(resume)

317.06

3.036

74826

1000

100%

Tomcat6

syn

163.323

5.904

18455

500

100%

         场景2就在资源不足的情况下,比较异步服务请求与同步请求处理能力。(例如由于后端某些服务比较慢,导致前段的服务器能够承载的请求数目超过了线程数)

         这个场景的结果可以看到TPS在异步模式下与并发用户数呈现同步增长,就好比配置了1000个线程作为线程池一样,同样在后端打出的最大请求数上也证明了这一点,因此前段线程池的服务能力在异步的情况下充分复用(当然这里使用的异步服务处理使用的是NIO而不是BIOConnector)。同样在吞吐量上依然是增加的,由于异步附加的内容。

场景31500 并发用户场景下,后端服务一次请求消耗3秒钟

容器

模式

TPS

Average Response Time(s)

Average Throughput(byte/s)

Server Load

Success rate

Jboss

syn

75.546

5.347

21002

0.115

68%

Jetty7

Syn

163.156

8.788

19252

0.129

100%

Jetty7

Asyn(complete)

432.153

3.312

76491

2.649

100%

Jetty7

Asyn(resume)

423.638

3.375

99979

2.826

100%

Tomcat6

Syn

163.836

8.75

18513

0.258

100%

Tomcat7

ASyn

423.501

3.328

54632

1.064

99.3%

场景三比对了现有TOP的部署模式(Apache + modjk + Jboss)和Jetty7的同步模式,两种异步模式,Tomcat同步模式,Tomcatservlet3.0异步模式的处理情况。根据测试可以得到的信息如下:

1.              现有部署方式在后端服务处理耗时较大的情况下,处理能力不如Jetty7Tomcat6,同时出错率很高。

2.              Jetty7的同步处理测试结果和Tomcat6的同步处理测试结果很类似,但是load方面jetty7更好。

3.              异步处理方面Jetty7的两种方式基本上差别不大(后续还需要深入源码看看对于数据缓存资源复用的状况),Tomcat7的异步处理成功率有些问题(错误多半是在获取response回写的时候,response已经被提前释放,看来Tomcat7还是需要一些时间来考验),load上来说tomcat结果比较好。

4.              异步请求在提高处理能力的情况下,对于资源消耗也较大(线程切换较为频繁),不过还是在承受范围。

三个场景组合比较:

容器

并发用户

模式

TPS

Average Response Time(s)

Average Throughput(byte/s)

Success rate

Jetty7

500

asyn(resume)

162.8

3.008

38430

100%

Jetty7

1000

asyn(resume)

317.06

3.036

74826

100%

Jetty7

1500

asyn(resume)

423.638

3.375

99979

100%

Tomcat6

500

syn

163.3

3.005

18453

100%

Tomcat6

1000

syn

163.323

5.904

18455

100%

Tomcat6

1500

Syn

163.836

8.75

18513

100%

最后将三个场景合并起来做一个简单的比较,得到信息如下:

1.       随着并发用户的增加,本身异步处理也会有衰减,同时对于性能消耗(线程切换)也会不断增长。

2.       异步化在消息头上会增加一些数据,会增加回写的带宽消耗(不过量不大),一个请求增加了100byte左右的消息数据。

测试总结:

1.       Web请求异步化在TOP很合适。

重复两个条件:

a.       处理耗时大多消耗在于对后端或者外部服务资源的请求上。

b.       后端或者外部资源在更多的流量下不会成为瓶颈。

2.       Web请求异步化在Jetty67上已经经历了2年多的成长(Google App Engine , Yahoo Hadoop),稳定性和效率较好。(同时很多优化可以通过扩展自行定制,jetty的可扩展性很好Tomcat7servlet3上处于刚发布阶段,还有待继续完善。(Servlet3的另一种模式尚未执行成功,直接导致jvm退出)

后续需要继续跟进的:

1.       对于大数据量请求的容器间性能对比。(图片上传或者大数据量的Post请求)

2.       容器安全性。(是否容易被攻击)

3.       代码迁移成本。

后续篇涉及:服务异步化的概念,服务异步化的几种标准实现,服务异步化容器的特点和实现,现有容器可优化的点。

 打个广告:http://blog.open.taobao.com/archives/1417 TOP需要人才加入

posted on 2010-06-13 14:35 岑文初 阅读(4242) 评论(9)  编辑  收藏

评论

# re: Web服务请求异步化测试 2010-06-13 15:30 melin
期待后续的文章......  回复  更多评论
  

# re: Web服务请求异步化测试 2010-06-22 17:53 孔夫子
作者的博客好多文章,估计要看很久。
我也说几句吧,呵呵,免费看了你这么多文章,估计你写的也挺辛苦的。
其实技术,现在在web这一块,基本上都没有技术含量,当然java也不例外。
技术不应该是重点,应用才是重点。
技术需要的就是使用,多用用就会了,当然多花些时间也是要的。呵呵,我觉得技术最重要的是创新,但可惜创新很难哦。
技术人员很喜欢陶醉在技术里面,其实说真的,真的没有什么东西好钻研的。需要钻研的其实是技术以外的东西。可惜很多人都走火入魔,九阴真经倒着练。
其实我要表达的观点是技术不难,难在创新而已。技术人员关心的不应该在技术本身上。
完了,这就是我的观点,呵呵,肯定很多人会反对我的观点。
多花些时间在别的上面吧,花在哪都比花在技术上好啊




  回复  更多评论
  

# re: Web服务请求异步化测试 2010-06-23 10:41 岑文初
@孔夫子
首先技术的目标就是服务客户,这就是最更本的要求,否则就是一个没有毕业的大学生,因此我所涉及的内容不会为了技术而技术,是产品需要而生。其次,这年头一堆人搞忽悠,没有人踏踏实实的写点代码,基本不靠谱,同时创新不是脑袋里蹦出来的,而是在使用前人已有的技术时发现无法满足需求才去思索和实践得到的结果,整天想着创新却不踏踏实实的干点事情,那就是等着天上掉馅饼,呵呵,不多说,仁者见仁,智者见智,少一些抱怨,多一些实干,把平凡的事情做的不平凡那就够了  回复  更多评论
  

# re: Web服务请求异步化测试 2010-06-23 11:57 孔夫子
@岑文初
仁兄还是没理解我的话,我不是说不要技术,而是说不要因此走火入魔,舍本求末,我本人曾经看过一个几千万的项目栽在一个浙大技术狂徒手上而一文不值,对设计模式,对代码规范本身,对架构,这些都不要太过,我见过一个年轻人为了一个设计一个向导,从设计模式,从通用性,从耦合度,甚至从架构上考虑,我当时对他说你走火入魔了,九阴真经倒着练,可惜对走火的人这种话是听不进去的,过犹不及。
我以为真正的高手,眼里是没有技术,没有语言的,只有流程、规范、标准、业务,用户需求,这或许就是无招胜有招吧。
我本人可以左右的项目,我是坚决不用spring,hibernate,struts,jquery这些的,更别说更花哨的,因为我不想舍本求末  回复  更多评论
  

# re: Web服务请求异步化测试 2010-06-23 12:12 岑文初
@孔夫子
这么说我同意,呵呵,学形,学意或者悟道都是不断进步的,这也是我们这些老家伙为什么会比新人值钱的原因,如果仅仅关注技术外在那么做个五年还就是一个熟练工  回复  更多评论
  

# re: Web服务请求异步化测试 2010-06-24 00:32 一意孤行
@岑文初
关于老家伙为什么比新人值钱,我曾经跟我老板有过对话。我说你一个月给我2w,是否有考虑过招2个1w的,或者是4个5千的,或者是5个4千的。我老板的回答是我肯定还是要你,甚至我可以还可以给你更多。因为你写的代码我放心,我不能让那些新人来我这里练兵,bug一大堆,那还赚什么钱,再说了最后你让他们写,最后你发觉还是还是要你自己写。
这是老板的考虑,我觉得很贴切。其实bug才是值钱的因素。没有那么多其他的原因。
其实我不喜欢blogjava,这里面技术太浓了,光怎么用struts,hibernate,spring,还有一些稀奇古怪的技术框架一大堆,这是舍本求末的。
我提到过taobao api must die,可能很残忍,但是其实这并不是一件不好的事情,任何一家要成为伟大公司的,没有经历过这或那的失败也是不可能的。
只是真的很不希望这么多人陷在技术的泥潭里而不能自拔。青春虽然是用来挥霍的,但挥霍在这些上真的不值得。
其实现在很少跟人这么交流了,只是看到仁兄这么好的才华,惺惺相惜,担心对于技术太过于痴迷,毕竟这样的人我见了不少。
我本来在blogjava里面也有几篇文章的,后面也都删了,总有点担心误人子弟。






  回复  更多评论
  

# re: Web服务请求异步化测试 2010-06-24 00:47 一意孤行
想来这些年,java,c++,js,php,flash都玩过,数据库更是玩了一遍,但我从不钻研,都是用前先看,用后就扔的原则,所以我很不喜欢那些问你hashmap和hashtable区别是什么,java的一些技术问题,c++智能指针的问题,唯一一次印象深刻的是我老板面试时问我,你觉得软件开发最难的地方在哪呢?当时着实让我想了好久。
技术可以用来玩,但不能随便在项目里面玩,这点很重要。
其实还是性格问题,技术人员都不喜欢主动发言交流,不喜欢走进客户,不喜欢走出去问客户到底要什么,所以说中国的软件很适合外包。

  回复  更多评论
  

# re: Web服务请求异步化测试 2010-06-24 00:59 岑文初
@一意孤行
呵呵,大部分都同意啦,只是有句俗话说的好:少不读三国,老不读红楼,在适合的时候做适合的事情,青春就是用来烧的,这也是将来成熟的一种历练。感谢你对我的关注,对我来说,技术是一种爱好,但是现在我更在乎的是产品,不再会和过去一样为了技术而技术,如何用技术来支持产品满足用户是我在乎的(当然设计的好的架构(不是啥开源框架,呵呵)在用户需求不断变化的时候可以更快的响应,能够前瞻到用户的潜在需求,挖掘出用户真正的需求)。最后贴一段我的Boss(菲青)前一阵子给我的一段评语:回放翁的文章。放翁和自雪应该是阿里/淘宝开放的先行者。从08年我们开始干开放的活儿,就是大家从无到有的累积。当然,新业务的建立需要时间,革命尚未成功。但是,看到放翁的转变从一个技术狂爱者到一个以业务为支撑的技术专家,我很佩服他的成长,也感觉TOP很幸运有了这些人,才使得TOP能够继续成长。我们的目标是以技术来支撑,改变业务产品,但不是技术主导业务。当然,因为我们流量及业务复杂度的关系,这中间沉淀下来的技术含量绝不亚于淘宝内部的一些大型系统!  回复  更多评论
  

# re: Web服务请求异步化测试 2010-06-24 08:52 jollyant
不能为了技术而技术,而是为了满足用户需求而是用技术~
但是任何满足用户需求的产品都是以技术支撑的
任何一个真正的高手都不是天生就是高手,无招胜有招,是需要先从手中无招到手中有招再到心中无招的,这个过程是一定要经历的~
首先要学习吸收别人先进的思想,才能让自己成为真正的高手~
目前所使用的技术都是前人经过千辛万苦开发出来的~
没有人能到不用别人开发的技术,光靠自己就能满足用户的需求吧?!用什么东西去满足用户的需求呢?!
在手中无招的时候去讨论要心中无招,只能误导别人,把新人带到沟里去~
学形,学意,会意,悟道~~这个过程终归是要经历的
或许能有一些天才人物从零开始,直接悟道的吧~呵呵
当然还是希望不要做技术狂人,而成为一个以业务为支撑的技术专家
  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: