你想建设一个能承受500万PV/每天的网站吗? - p1 i" M, h' q# @- N/ E
500万PV是什么概念?我的服务器每秒要处理多少个请求? % m- n5 |0 V( d( @0 V
- p, z7 D4 P5 p. {+ P" \* l
PV是什么? ! I, G5 d! |1 w( n" R4 C4 K7 O
PV是page view的简写。PV是指页面刷新的次数,每一次页面访问,就算做一次pv流量。 % U# H4 F3 K' w. G( K
$ I9 s# L1 ]9 G8 s0 f3 i计算模型: 5 Y5 ]$ G% [( K# P2 ?( O% q& D* E; ?
每台服务器每秒处理请求的数量=((80%*总PV量)/(24小时*60分*60秒*40%))/服务器数量 / Z0 ^* R2 l! W8 k( w5 j3 ]
其中关键的参数是80%、40%。表示一天中有80%的请求发生在40%的时间内。24小时的40%是9.6小时,有80%的请求发生一天的9.6个小时当中(很适合互联网的应用)。 & H4 X* U2 Z: Y7 ~2 U# Q
- |& G9 X f" ^+ x0 o
((80%*500万)/(24小时*60分*60秒*40%))/1 = 1157个请求/秒
$ N8 V6 m) J+ [, w; H# G((80%*100万)/(24小时*60分*60秒*40%))/1 = 231个请求/秒 7 X6 l* h0 z" V$ o* u. Q
9 E, N8 C' o: Z6 O
; n: P" f: ~$ Z* q6 Z
结论:
# ~3 L7 L5 Z% {2 b+ p6 V现在我们在做压力测试时,就有了标准,如果你的服务器一秒能处理1157个请求,就可以承受500万PV/每天。这里不关心是请求的是静态的html,还是动态的jsp。 ^2 ]% g4 M' f6 {: J, c
如果你的服务器一秒能处理231个请求,就可以承受100万PV/每天.
, z4 i3 y' C! l* A1 g4 `
# I' B. j, M( R说明:这里说明每秒N个请求,更像是TPS。而不是请求一个html页面而附带请求的css,js,图片。因为我关心的是应用程序处理业务的能力。 , c9 q1 ^) C" e& x! g' q
% q2 S) a7 M5 }6 M/ ~: e. P0 u; q5 t; L" j/ N' p: Q! t b! `
---------------------------------------------------------------------------------------
+ s# p+ U) i' ^) [5 ^2 j! F- y基本概念: ( A }( a# D+ A4 z6 f7 B/ b
Throughput(吞吐量):按照常规理解网络吞吐量表示在单位时间内通过网卡数据量之和,其中即包括本机网卡发送出去的数据量也包括本机网卡接收到的数据量。 . M b: Y" |0 O, y, y' x' }
并发用户数:是同时执行操作的用户 ) c) X$ g9 R! F8 V
响应时间:对请求作出响应所需要的时间
% x3 Y* G& K3 E8 [% _---------------------------------------------------------------------------------------
2 @# C L+ s sJMeter测试参数说明: 5 {3 t: j7 Z" N
& b4 X9 b# h. G" B8 H$ }
Label:每一个测试单元的名字。 1 Q' i& ^# w) M) T, [
! {2 M; \: x: D E* p& Q& N5 Q#Samples:表示一个测试单元一共发出了多少个请求。
: n+ E8 A# N: Y, j G' X
1 m3 }4 m8 G4 Z; g$ s2 PAverage:平均响应时间——默认情况下是单个 Request 的平均响应时间,当使用了 Transaction Controller 时,也可以以Transaction 为单位显示平均响应时间。,不重要。
' v1 u6 n2 g% t/ q3 H( V0 d' s0 U; r f" n8 ]' C# d7 Z
Median:中位数,也就是 50% 用户的响应时间,如果把响应时间从小到大顺序排序,那么50%的请求的响应时间在这个范围之内。重要。
! J! j7 `/ \& E& Y" H) L+ W# D/ R1 W& G/ C" n7 g
90% Line:90% 用户的响应时间,如果把响应时间从小到大顺序排序,那么90%的请求的响应时间在这个范围之内。重要。
, t& b. q' y; B( B' L3 G
2 L- P1 B7 V0 n2 p, x) S( r4 S: x9 LMin:最小响应时间,不重要。 5 u, n' |; u/ T3 T8 Z' p7 h; K( h/ O
7 e+ W: @5 y% V9 }1 L; L0 B* m
Max:最大响应时间,出现几率只不过是千分之一甚至万分之一,不重要。 ; ~. X3 Z- M% M& ~2 \
# W5 S+ o+ W; eError%:本次测试中出现错误的请求的数量
; f( H1 Q' e! t8 Y5 u% r
/ Y E! W. g# u2 l" h/ W! K( l$ HThroughput:吞吐量——默认情况下表示每秒完成的请求数(Request per Second),当使用了 Transaction Controller 时,也可以表示类似 LoadRunner 的 Transaction per Second 数 4 E! D# C4 u3 B, V/ \& D! T: [
1 E1 y7 D- b7 F; c- D/ |7 G' c
KB/Sec:每秒从服务器端接收到的数据量,相当于LoadRunner中的Throughput/Sec % v) a. a0 ?/ M$ }& ]1 D. e% ~
---------------------------------------------------------------------------------------
! X7 v4 ]: ?* Q. rloadrunner测试参数说明: ) g% ?+ n( @& o1 p* q, Y z
6 h7 |5 V* z' _+ I8 G/ s9 g7 d e
响应时间: 取90%值,如果把响应时间从小到大顺序排序,那么90%的请求的响应时间在这个范围之内。重要。 $ B7 N( M( ]$ W e4 ~
- D1 N& C( y& F# F
每秒点击数 :hits per Second,每秒钟向服务器提交请求的数量。 % [" t$ j8 L u$ q& Y. y1 `$ p
0 f0 q/ L. _% f6 z$ ETPS: Transaction per Second ,每秒事务数,一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程 , a' F$ i: q$ S5 D/ w
3 [9 g! ^. K* s) u) A- Y
Throughput(吞吐量): Loadrunner记录的Throughput是接收到服务器返回的所有字节数之和,与本地发出的字节数无关。
w9 D6 N7 x0 C! i3 {5 T F* w* o
Throughput/Sec: 每秒的吞吐量。
e5 f" K: _3 e+ x& f3 o1 Y z' i. q% G" P8 v
, r4 R6 R1 v; z6 q3 t' B. {对于BS架构的一般分析 响应时间、点击率、吞吐量、TPS(每秒事务数)。 5 x/ _/ H* z. l% C7 y; D3 {
对于CS架构的一般分析 TPS(每秒事务数) % _$ A6 n( n5 P# f
8 i/ O& W/ v) [0 C& P# t
---------------------------------------------------------------------------------------
. p6 J; b' _$ M+ w
$ U4 H8 F/ |& G9 @( @Apache ab测试参数说明:
" t# M9 N1 ^, } c
% V% E8 R3 A6 w7 m# tRPS: Request per Second,每秒处理的请求数 1 d# W$ v" U. l1 B
' J+ Z) {) d) m! w/ i3 m9 H% R5 s
详见: $ Y7 r7 w& M/ R& j
http://blog.chinaunix.net/u3/108043/showart_2260477.html
% C- h! p( M2 m5 R--------------------------------------------------------------------------------------- + w4 H; O3 ~% \
' u- _+ `$ j+ [# L4 P
5 u0 g9 F1 V* O7 B0 b- k+ U测试配置如下图: 其实jmeter还是很弱的,我打开"集合点(synchronizing Timer)","察看结果树","用表格查看结果"中的任何一个都会导致性能下降和小部分请求的响应出错(可能是线程数太多了),所以禁用了。只启用了cookie管理器。 2 i& O# D: R% i; Q: y) o, D8 `
6 V% r0 ?' W: j8 b# b" f0 r; ?4 W; i
" h% i! ^! t9 m) D, M" `) k- ]# L- v---------------------------------------------------------------------------------------
/ Z0 u2 [, R% x# F! G; G' KTomcat6.0 配置文件的说明 ,做测试之前是要整清楚的。 3 b3 S" r7 [& h3 o# n
默认的Server.xml中如下 ; y# }5 P, F3 r% A' \
<connector port="8080" maxhttpheadersize="8192"
/ \' @' p+ l, O4 o' d' tmaxThreads="150" minSpareThreads="25" maxSpareThreads="75"
4 J: P( `1 J6 T% wenableLookups="false" redirectPort="8443" acceptCount="100" 2 B" o' R0 t( \# b; @
connectionTimeout="20000" disableUploadTimeout="true" />
; b6 v- Y5 z- j8 N& c! W4 z2 O! [
0 T- a) r- j: g; u5 ~; ^% x y/ s' C' Q. B' ^% x. E
enableLookups 8 A% m9 n1 b: ?* \" d9 A- o, G
是否允许DNS查询,当web应用程序要通过域名服务器查找机器名转换为IP地址时。会使用DNS查询,需要占用网络,延长较长
, b# b! K' K8 u7 Q+ O- w, B3 g# W qmaxThreads 4 Z. w+ r: {9 T. @7 a( |
Tomcat可创建的最大的线程数,每一个请求须要一个线程来处理,原来的150太小了,我们测试时并发会超过他的。 : H/ a: F7 u. L# u* T: d7 p
acceptCount - U1 Q* z: i4 P4 o: d7 h ]* a! m4 N/ I
指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,就是被排队的请求数,超过这个数的请求将拒绝连接。 ) w! P, B- h4 Z) p) i! }
connnectionTimeout 1 G* N9 F9 \- d/ r7 }- f, J
网络连接超时,单位:毫秒。设置为0表示永不超时,这样设置有隐患的。通常可设置为20000毫秒。 6 k2 k& @2 S6 k" ~: {' u. b3 q% u& B
minSpareThreads
$ f- K; g2 e. R% y/ X6 u" YTomcat初始化时创建的线程数
) z9 P5 M: k' V: ]maxSpareThreads 7 M& D; j1 b3 p& H ]6 I: {
一旦创建的线程中空闲线程超过这个值,Tomcat就会关闭不再需要的socket线程。 7 e$ q& f3 U2 y( ]) H
5 `2 {( U, ~ J0 U9 p+ L
注意:maxThreads 设置为500,也就是最多有500个线程,为下一步的压力测试做好准备。
# R; }5 a! m0 S7 b. [2 K! E; J; W6 X7 ~
--------------------------------------------------------------------------------------- , w, C; S |3 b/ S/ B! v
* f N+ _+ s# ]8 A6 c7 U测试环境说明:
4 ^! w6 d O3 j服务器: 4G内存,至强3.0 (4核超线程)CPU,windows 2003
6 h: b- @) p! S测试机:笔记本 2G内存,p8600 CPU,windows XP 1 R, {( t2 C6 s
网络:100Mb局域网 3 {2 @ c# d$ t% C8 j
测试软件: 9 e7 Z, i! M. f7 m7 _. e' P9 Y* j
Jmeter 2.3.4 分配了512M内存 ; v! X, v* l2 i3 V, G7 Z: ~% \
tomcat 6 默认内存大小
: L3 C/ i, P. C& T. O--------------------------------------------------------------------------------------- G; A( U; R% `
测试时服务器CPU使用率 10% * Y9 ^8 G- o4 j+ F* x2 G
测试时测试机CPU使用率 100%(测试机不行啊) 0 B$ b' x# J z/ E/ [( N
每次测试CPU都这样,就统一写这里了。 x9 V" v, R$ E8 f( v7 L
# E: Q; ^/ B0 h1 G! Y. v. w1 s, {
测试1:2213个请求/秒 ) a3 ~6 t! O$ v# X J: ^
100并发,循环100次,共10000个请求,请求一个大小3.34KB的jsp页面。 % S9 `% S- S& v6 @
9 }1 _& q& v+ B W/ `
: v* \) ?+ S8 T2 [" e5 Z" k3 o, A) T+ h2 ~( u1 i0 E
测试2:1889个请求/秒 + }2 m: B1 ?5 d9 `+ X& _9 E8 W6 U
100并发,循环100次,共10000个请求,请求一个servlet总控制器,验证权限后,new一个Action,再转发到一个大小3.34KB的jsp页面。
0 T% a4 j/ @- d( k
% z2 T# N3 e$ j* ^ k8 R; `6 W6 c& j- M
t) _( Z" E' Y1 v6 G
测试3:2607个请求/秒
5 a7 l9 z+ u* _5 X6 `, L100并发,循环100次,共10000个请求,请求一个3.2KB的html页面。 " x9 Y5 d/ F# S; ^, o& t' C
V1 H& Y6 N' l" j6 s% @) }" G0 H! I* F, p+ b5 q. i; L
: O, T; z( s* M0 d% L' C! r" |测试4: 833个请求/秒
! {5 W @" P$ G* B8 J4 m100并发,循环100次,共10000个请求,请求一个13.4KB的html页面。与上面比是只是文件大了一些,性能就降了不少!! h. T+ E, p" ~+ H% `' w5 X- y2 I
6 K1 ~" k' [8 q, u. `
' F- J* b4 g4 r; R
2 N" O2 z/ b" P$ k
测试5: spring 2012个请求/秒 1 r' E8 k1 h7 @( C" l4 o8 d
100并发,循环100次,共10000个请求,请求一个spring3 MVC的action,再转发到一个0.8K的JSP,其内容是简单的html
# _8 i0 ]' y( j
# D! @0 t& ^4 n7 r
9 M1 T: _: C( @2 S& [
4 k* w6 ?" l- W. d/ f1 Y( _( F测试6: spring 1800-1924个请求/秒 , H+ i: I3 b5 n; H
100并发,循环100次,共10000个请求,请求一个spring3 MVC的action,两个参数类型转换为int、Date,再new 一个List,再转发到一个1.3K的JSP,用JSTL标签显示List中的内容。
9 O+ f# m! ^1 F/ ]/ s5 i
) {+ \2 l& [/ ~, V5 m9 h/ y
JSTL标签内容是如下,看来JSTL标签性能还是不错的。
4 k; {4 n( n) M: ~: s, ?
7 |3 n" L0 z- t B/ [ $ A: ~2 d* ?% F1 Q% g& d; ~2 d% A' X
无记录! 6 s R. [8 x; d: O6 L. U
! _6 @8 s: b- f+ O" ?8 ]: D " n5 J6 [3 a6 V9 q0 S* x' ?
3 a# A0 A( }% ]; E. e) x9 W
! N" a% x8 w7 P3 C& D
从 1 开始的迭代计数
- u, y# a- t6 }7 Y. V从 0 开始的迭代计数 8 B, p7 l8 t3 x3 c- w# f
产品名称 3 D5 @0 g; u5 t- ^. g# U$ o: K
& ]5 G" J1 \/ m) n- O5 e, y4 r
/ W; X( z3 c' [) \* \6 ~/ O
4 n, ^3 U$ y( D) d: R) |${s.count} % e, v/ C3 s8 m( a
${s.index}
* g; w( ^7 Y0 l( i" P) ]& n( h' K${item} % a: ~* e9 z& z2 L! F
! d# C; @7 z& M5 d 7 Z% w: {, {* l+ _. d: ~ ^2 n
) [" j3 o+ @$ @2 H
$ D6 {. M d' u9 [: ], f4 x/ [% r1 U- ]9 f& y; y
测试7: 图片 1997个请求/秒 1 _4 J' w) w% L) v9 [3 G
100并发,循环100次,共10000个请求. 因为我使用了spring3 MVC,拦截/,所以图片不能访问,所以添加了:
! x' P8 v' L& U! Y+ M & L5 C3 z0 E& l, g1 D
default
' F4 `. j, Z5 e' F) L3 l *.jpg
! O+ B6 K4 x7 I1 a
' t& U( p& ~# d) q8 [3 f& d8 u走默认的servlet,来访问2.5K的图片 3 E+ v. r9 o% x( }# ?
3 a$ F' r; e: i7 N$ F1 u5 n4 h8 `
# I* w% S1 z w4 q# c4 A: i' v& P) [, F1 ]; o2 B- V* _3 E! b) ^
测试8: 图片 1967个请求/秒 # q( i5 m x* I/ f% L
100并发,循环100次,共10000个请求,因为我使用了spring3 MVC,拦截/,所以图片不能访问,所以添加了: 4 F) s8 m) y! |, H
) W C7 Z P2 W0 j来访问2.5K的图片,会走spring的可匹配的一个拦截器。
+ F u! K/ s) c( ?7 G) c8 p) `
& ~3 V4 H, {1 L5 Y% Z
2 G- l7 X& g' t! ^* d7 u2 L. O测试9:struts2的测试 2 o, L7 {1 Z7 C/ t* f" Y; P
100并发,循环1次,没有循环100次,因为strtus2在这次测试中响应太慢了,我等不起了,所以单个url的测试样本从10000降到了100.一共11个url,共1100个样本。
' n& g) P& w, i8 H"spring" 使用的就是前面“测试5”的URL,放在这里是为了与strtus2对比的。 - T& Z* m2 J& v8 }6 i
"html" 使用的就是前面“测试3”的URL,放在这里是为了与strtus2对比的。 5 W( \5 z4 W% S) @6 Z6 g8 d9 X
"struts2-1" 使用的是官方自带的示例项目,名称是struts2-blank-2.1.8.1.war ! \' \" U& @$ n0 q
"struts2-2" 使用的是官方自带的示例项目,名称是struts2-showcase-2.1.8.1.war,我在其中随便选了一个action来做测试 3 a9 ^. u9 `- Q& ?5 Y) v: h
"struts2-3" 同上 % E: Q6 T3 Q. v- p) _8 [
"struts2-4" 同上 * J" o8 I5 A/ e: c" s T+ l+ D
"struts2-5" 同上 ) M" Q* i1 A% U8 N% u
"struts2-6" 同上 5 r' Y4 B2 Z# h9 |
"struts2-7" 同上 ! ^0 {+ p% y# s4 X! e( j: V
"struts2-8" 同上
. @* {4 a9 v+ n"struts2-9" 同上
) R, ?8 N$ \7 s! K5 V8 X! R( k太忙了,没有时间对Struts2做优化,使用的都是官方带的示例,Struts2的测试结果不理想,放在这里做一个参考。“struts2-1”是struts2中测试成绩最好的,但也不理想。
}& q" W. w% h
* A' `4 o1 [5 F& q. p, h
6 t+ @: b7 Y" t- D
5 _5 h8 Y7 G; s9 a$ s测试10:Struts2的测试。 ! \+ }- Z' F7 r* [* O$ u* n
上一个测试结果太离谱了,第二天,想了想又重新测试了下,使用的还是struts2官方提供的struts2-blank-2.1.8.1.war示例。访问下面的action,action内容简单就是转发到一个JSP。 # }, c; |. t1 S: t
http://192.168.0.5/struts2/example/HelloWorld.action
F" j1 S! a. _
. m W2 f. t/ i+ r8 G9 G下图是示例默认的action,我没有修改:
( v3 z+ K' |4 e: V. F- f7 l5 R' E
9 m% C9 t- T2 i7 b. I" t! t/ Z
要说一说转发到的jsp,其中有struts2标签
0 v8 j8 j4 d4 {, p
3 K6 [2 ~2 n' M% x $ X8 B/ F% N( I, A0 m' ^
en
$ c- G/ Y! [) v* Y
! G' q+ ~! J8 g9 F( ZEnglish , J+ v, o! w e2 I8 U) N% L5 y
& }3 y! m+ [7 u
我把jsp改了,删除了所有struts2标签,只输出一行文件
+ Q7 b. c! U( r, |2 N
8 \1 {2 ~, S: s7 H b+ P; y+ _天啊,性能超出我的想像,太好了。看来是struts2标签拖了后腿。
0 D; G! P, _; @$ @3 ^% e( k8 o' `5 G/ a& E" _
我把jsp改了,换了其它的struts2标签
/ g& d9 L5 F+ H L I
- Y" D' E3 }$ H ?5 y3 A, n7 a0 a
标签是:
" e2 A3 R) T+ m" ]6 u
8 f9 t% t% d! G
1 w% G! U- {+ O$ s1 Z 8 B+ ?4 v) C' o5 P& l O
0 A, n# J& ^4 s* W1 U9 y
* @* v3 J) Z; c [9 c0 Y4 B看来struts2的标签性能太差了。 ' K' g- }5 G- m5 i) {
) x0 l, B' ^7 I; L; l
Struts2由于采用了 值栈、OGNL表达式、struts2标签库等,会导致性能下降。如果避免或减少使用这些,性能还是很好了。
( C) a# [' D m3 XStruts2的 多层拦截器、 多实例action不是导致性能问题的原因。
7 s i0 T1 p! J( R- n: K9 j4 O3 L) O" _+ y) b
# S/ Z+ N: a6 r
注:以上测试都没有数据库,也没有业务,action中,jsp中内容很简单。 6 ? O9 _7 \( w3 t8 k
% S. A! j$ y* C
--------------------------------------------------------------------------------------- 7 j5 q, q# l8 {
/ x. L) P" d( T- p
其它测试文章: " j+ s% O& l* f$ c3 H
http://zhaoshg.iteye.com/blog/356231 5 }7 G& ^* z- ] h* k. R9 E
http://www.iteye.com/topic/679543 4 L( f! v! a& |: D
+ R7 _% E1 B( `( @MVC框架性能比较 ( Y$ Q& j9 K- w) S/ g- u2 f
http://wenku.baidu.com/view/148d7e34eefdc8d376ee32ac.html & K; k9 l2 L2 }, N% v
! T# _/ o3 R& S7 ~
spring3mvc与struts2比较 / P V$ G. u4 W9 ]8 `# l
http://www.iteye.com/topic/646240
( q4 K& h* ?: u/ @8 O0 a" W8 x" g0 I, y& i$ w9 D
' @- t; S4 P' H5 ^ G
& p+ u5 E$ n- c8 i8 H2 \& ^8 E
附:2 k; N5 x- \8 c1 r8 W, K. E" E! I+ @
几种标签和框架组合解析数据时候的 性能测试对比
: C* ?6 m6 | t8 i3 A1 R一、 数据 数据通过查询日志表得到数据,共 1302 条数据,将查询出的数据放入一个静态 List 中,保证每次请求的数据相同。 测试页面的元素相同,只是在取数据方式上不同。 二、 测试目标 1、 在 JSP 页面使用 struts2 标签的性能; 2、 在 JSP 页面使用 JSTL 标签的性能; 3、 在 Freemarker 页面使用 struts2 标签的性能; 4、 在 Freemarker 页面使用 JSTL 标签的性能; 5、 在 Freemarker 页面使用其本身的数据加载方式的性能。 三、 加载耗时对比 时间: ms 注:每一次对比都是在同一时间段按同一顺序依次执行下列几种方式 1 G9 A: e) p8 U% f/ k, w, r
) J. ?- g/ \$ ], H+ U0 M
| | | | | | 第一次 | | | | . {6 q0 Q# `4 X9 |" p
| | 第二次 | | | |
' e+ ~) p. n9 t- M0 C
| | 第三次 | | | |
* G* }4 K% { i* v) Z. ^% Y/ o1 O
| | 第四次 | | | | 1 K5 I5 i4 i6 Z4 Y/ m+ p" K
| | 第五次 | | | |
7 m5 i4 H2 W# X5 P7 _. ~
| | 第六次 | | | | % N5 Y0 L$ W% T+ F) W2 [
| | 第七次 | | | | $ }9 p2 c' ^+ O5 a* e p1 w7 K' x
| | 第八次 | | | | ) x& q/ N. ?& K5 N# [+ V, S
| | 第九次 | | | | % \& U2 \0 [/ K+ i( x' Y) Z* D
| | 第十次 | | | | ! z. b% o$ d0 J1 j7 f2 Q
| | 平均值 | | | | . f/ j2 c2 \! x* ]: S
| | 去掉最高和最低 |
* F* n4 O9 r8 c4 R6 {& c |