免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12
最近访问板块 发新帖
楼主: iakuf
打印 上一主题 下一主题

使用 Mojolicious 写非阻塞的应用: Part 2 (中译版,同步发行) [复制链接]

论坛徽章:
0
11 [报告]
发表于 2013-11-13 08:20 |只看该作者
回复 10# py


    Thank you for your response!

论坛徽章:
42
19周年集字徽章-周
日期:2019-10-14 14:35:31平安夜徽章
日期:2015-12-26 00:06:30数据库技术版块每日发帖之星
日期:2015-12-01 06:20:002015亚冠之首尔
日期:2015-11-04 22:25:43IT运维版块每日发帖之星
日期:2015-08-17 06:20:00寅虎
日期:2014-06-04 16:25:27狮子座
日期:2014-05-12 11:00:00辰龙
日期:2013-12-20 17:07:19射手座
日期:2013-10-24 21:01:23CU十二周年纪念徽章
日期:2013-10-24 15:41:34IT运维版块每日发帖之星
日期:2016-01-27 06:20:0015-16赛季CBA联赛之新疆
日期:2016-06-07 14:10:01
12 [报告]
发表于 2013-12-10 11:24 |只看该作者
回复 3# iakuf


    有个俄国人跟了一个AnyEvent:elay::Simple 模块

论坛徽章:
0
13 [报告]
发表于 2013-12-19 09:08 |只看该作者
还在学习中,最近在模拟测试一下阻塞和非阻塞的却别, 不知道使用sleep来做阻塞合不合适,下面是测试过程

测试代码:
Jacks-MacBook-Proroject jzhangkun$ cat myapp.pl
  1. #!/usr/bin/env perl
  2. use Mojolicious::Lite;
  3. use Mojo::IOLoop;

  4. get '/worker1' => sub {
  5.     my $self = shift;
  6.     $self->render_later;
  7.     Mojo::IOLoop->timer( 0 => sub{
  8.         sleep(5);
  9.         print "after sleep 5\n";
  10.         $self->render('text' => 'worker1: ready to work!');
  11.     });
  12. };

  13. get '/worker2' => sub {
  14.     my $self = shift;
  15.     $self->render_later;
  16.     Mojo::IOLoop->timer( 5 => sub{
  17.         print "after sleep 5\n";
  18.         $self->render('text' => 'worker2: ready to work!');
  19.     });
  20. };

  21. app->start;
复制代码
启动morbo
  1. Jacks-MacBook-Pro:Project jzhangkun$ morbo myapp.pl
  2. [Wed Dec 18 16:49:51 2013] [info] Listening at "http://*:3000".
  3. Server available at http://127.0.0.1:3000.
复制代码
阻塞测试的结果
两个并行请求
  1. Jacks-MacBook-Pro:Project jzhangkun$ ab -n 2 -c 2 127.0.0.1:3000/worker1
  2. This is ApacheBench, Version 2.3 <$Revision: 655654 $>
  3. Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
  4. Licensed to The Apache Software Foundation, http://www.apache.org/

  5. Benchmarking 127.0.0.1 (be patient).....done


  6. Server Software:        Mojolicious
  7. Server Hostname:        127.0.0.1
  8. Server Port:            3000

  9. Document Path:          /worker1
  10. Document Length:        23 bytes

  11. Concurrency Level:      2
  12. Time taken for tests:   10.011 seconds
  13. Complete requests:      2
  14. Failed requests:        0
  15. Write errors:           0
  16. Total transferred:      370 bytes
  17. HTML transferred:       46 bytes
  18. Requests per second:    0.20 [#/sec] (mean)
  19. Time per request:       10010.838 [ms] (mean)
  20. Time per request:       5005.419 [ms] (mean, across all concurrent requests)
  21. Transfer rate:          0.04 [Kbytes/sec] received

  22. Connection Times (ms)
  23.               min  mean[+/-sd] median   max
  24. Connect:        0    0   0.0      0       0
  25. Processing: 10011 10011   0.1  10011   10011
  26. Waiting:    10010 10010   0.1  10011   10011
  27. Total:      10011 10011   0.0  10011   10011
  28. ERROR: The median and mean for the waiting time are more than twice the standard
  29.        deviation apart. These results are NOT reliable.

  30. Percentage of the requests served within a certain time (ms)
  31.   50%  10011
  32.   66%  10011
  33.   75%  10011
  34.   80%  10011
  35.   90%  10011
  36.   95%  10011
  37.   98%  10011
  38.   99%  10011
  39. 100%  10011 (longest request)
复制代码
非阻塞测试的结果
两个并行请求
  1. Jacks-MacBook-Pro:Project jzhangkun$ ab -n 2 -c 2 127.0.0.1:3000/worker2
  2. This is ApacheBench, Version 2.3 <$Revision: 655654 $>
  3. Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
  4. Licensed to The Apache Software Foundation, http://www.apache.org/

  5. Benchmarking 127.0.0.1 (be patient).....done


  6. Server Software:        Mojolicious
  7. Server Hostname:        127.0.0.1
  8. Server Port:            3000

  9. Document Path:          /worker2
  10. Document Length:        23 bytes

  11. Concurrency Level:      2
  12. Time taken for tests:   5.006 seconds
  13. Complete requests:      2
  14. Failed requests:        0
  15. Write errors:           0
  16. Total transferred:      370 bytes
  17. HTML transferred:       46 bytes
  18. Requests per second:    0.40 [#/sec] (mean)
  19. Time per request:       5006.206 [ms] (mean)
  20. Time per request:       2503.103 [ms] (mean, across all concurrent requests)
  21. Transfer rate:          0.07 [Kbytes/sec] received

  22. Connection Times (ms)
  23.               min  mean[+/-sd] median   max
  24. Connect:        0    0   0.1      0       0
  25. Processing:  5004 5005   1.2   5006    5006
  26. Waiting:     5004 5005   1.2   5006    5006
  27. Total:       5004 5005   1.2   5006    5006

  28. Percentage of the requests served within a certain time (ms)
  29.   50%   5006
  30.   66%   5006
  31.   75%   5006
  32.   80%   5006
  33.   90%   5006
  34.   95%   5006
  35.   98%   5006
  36.   99%   5006
  37. 100%   5006 (longest request)
复制代码
morbo log
  1. [Wed Dec 18 16:49:57 2013] [debug] Your secret passphrase needs to be changed!!!
  2. [Wed Dec 18 16:49:57 2013] [debug] GET "/worker1".
  3. [Wed Dec 18 16:49:57 2013] [debug] Routing to a callback.
  4. [Wed Dec 18 16:49:57 2013] [debug] Nothing has been rendered, expecting delayed response.
  5. [Wed Dec 18 16:49:57 2013] [debug] GET "/worker1".
  6. [Wed Dec 18 16:49:57 2013] [debug] Routing to a callback.
  7. [Wed Dec 18 16:49:57 2013] [debug] Nothing has been rendered, expecting delayed response.
  8. after sleep 5
  9. [Wed Dec 18 16:50:02 2013] [debug] 200 OK (5.003588s, 0.200/s).
  10. after sleep 5
  11. [Wed Dec 18 16:50:07 2013] [debug] 200 OK (10.004253s, 0.100/s).


  12. [Wed Dec 18 16:50:14 2013] [debug] GET "/worker2".
  13. [Wed Dec 18 16:50:14 2013] [debug] Routing to a callback.
  14. [Wed Dec 18 16:50:14 2013] [debug] Nothing has been rendered, expecting delayed response.
  15. [Wed Dec 18 16:50:14 2013] [debug] GET "/worker2".
  16. [Wed Dec 18 16:50:14 2013] [debug] Routing to a callback.
  17. [Wed Dec 18 16:50:14 2013] [debug] Nothing has been rendered, expecting delayed response.
  18. after sleep 5
  19. [Wed Dec 18 16:50:19 2013] [debug] 200 OK (5.001051s, 0.200/s).
  20. after sleep 5
  21. [Wed Dec 18 16:50:19 2013] [debug] 200 OK (5.000403s, 0.200/s).
复制代码
从上面的测试结果看一看出,sleep明显阻塞了第二个请求,而timer不会阻塞整个。依然不是很清楚为什么sleep会阻塞住?什么样的操作算是阻塞操作?比如一个长时间的查询操作算是阻塞操作吗?

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
14 [报告]
发表于 2013-12-19 12:18 |只看该作者
回复 13# kk861123

1. perl的sleep函数是阻塞操作。就像用了使用timeout的系统调用select()一样,会阻塞整个进程。
2. 如果你的IO操作是阻塞当前进程的,就是阻塞操作,反之亦然。
3. “一个长时间的查询操作”并不一定会阻塞当前进程,所以不一定是不是阻塞操作,要看这个查询操作的实现方式。

是不是阻塞操作,和操作的类型无关,和操作的实现方式有关。
例如,不能说所有的sleep操作都是阻塞的,或是所有的数据库查询操作都是阻塞的。得看具体是怎么实现的。
   

论坛徽章:
0
15 [报告]
发表于 2013-12-19 14:19 |只看该作者
回复 14# py


   非常感谢您的回复,澄清了我关于阻塞操作的片面看法。但是应该怎样去分析一个操作是否阻塞呢?

另外,我想进一步分析一下如何对程序中有阻塞操作的情况进行调优,文档介绍过,如果有阻塞操作,最好的方法就是增加workers减少clients,意思就是多fork几个workers并降低每个worker能处理的并行请求,这是我的测试结果:


1. prefork 2 workers, 允许每个worker接受2 并行请求
  1. perl myapp.pl prefork -w 2 -c 2
复制代码
1.1 阻塞操作发送4个并行请求
  1. Jacks-MacBook-Pro:Project jzhangkun$ ab -n 4 -c 4 127.0.0.1:3000/worker1
  2. This is ApacheBench, Version 2.3 <$Revision: 655654 $>
  3. Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
  4. Licensed to The Apache Software Foundation, http://www.apache.org/

  5. Benchmarking 127.0.0.1 (be patient).....done


  6. Server Software:        Mojolicious
  7. Server Hostname:        127.0.0.1
  8. Server Port:            3000

  9. Document Path:          /worker1
  10. Document Length:        23 bytes

  11. Concurrency Level:      4
  12. Time taken for tests:   10.008 seconds
  13. Complete requests:      4
  14. Failed requests:        0
  15. Write errors:           0
  16. Total transferred:      740 bytes
  17. HTML transferred:       92 bytes
  18. Requests per second:    0.40 [#/sec] (mean)
  19. Time per request:       10008.165 [ms] (mean)
  20. Time per request:       2502.041 [ms] (mean, across all concurrent requests)
  21. Transfer rate:          0.07 [Kbytes/sec] received

  22. Connection Times (ms)
  23.               min  mean[+/-sd] median   max
  24. Connect:        0    0   0.1      0       0
  25. Processing:  5004 7506 2889.0  10008   10008
  26. Waiting:     5004 7506 2889.0  10008   10008
  27. Total:       5004 7506 2889.0  10008   10008

  28. Percentage of the requests served within a certain time (ms)
  29.   50%  10008
  30.   66%  10008
  31.   75%  10008
  32.   80%  10008
  33.   90%  10008
  34.   95%  10008
  35.   98%  10008
  36.   99%  10008
  37. 100%  10008 (longest request)
复制代码
设想mojo处理请求的流程是将两个请求分给两个workers,因为操作是阻塞的,所以每个worker在处理两个请求时是阻塞进行的,因此每个都需要10s。

1.2 非阻塞操作发送4个并行请求
  1. Jacks-MacBook-Pro:Project jzhangkun$ ab -n 4 -c 4 127.0.0.1:3000/worker2
  2. This is ApacheBench, Version 2.3 <$Revision: 655654 $>
  3. Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
  4. Licensed to The Apache Software Foundation, http://www.apache.org/

  5. Benchmarking 127.0.0.1 (be patient).....done


  6. Server Software:        Mojolicious
  7. Server Hostname:        127.0.0.1
  8. Server Port:            3000

  9. Document Path:          /worker2
  10. Document Length:        23 bytes

  11. Concurrency Level:      4
  12. Time taken for tests:   5.059 seconds
  13. Complete requests:      4
  14. Failed requests:        0
  15. Write errors:           0
  16. Total transferred:      740 bytes
  17. HTML transferred:       92 bytes
  18. Requests per second:    0.79 [#/sec] (mean)
  19. Time per request:       5058.597 [ms] (mean)
  20. Time per request:       1264.649 [ms] (mean, across all concurrent requests)
  21. Transfer rate:          0.14 [Kbytes/sec] received

  22. Connection Times (ms)
  23.               min  mean[+/-sd] median   max
  24. Connect:        0    0   0.1      0       0
  25. Processing:  5004 5024  25.8   5030    5058
  26. Waiting:     5004 5024  25.9   5030    5058
  27. Total:       5004 5024  25.8   5030    5058

  28. Percentage of the requests served within a certain time (ms)
  29.   50%   5030
  30.   66%   5030
  31.   75%   5058
  32.   80%   5058
  33.   90%   5058
  34.   95%   5058
  35.   98%   5058
  36.   99%   5058
  37. 100%   5058 (longest request)
复制代码
设想mojo也是让每个worker处理两个请求,因为是非阻塞处理,所以是5s内能全部处理完


2. prefork 4 worker, 允许每个worker接受1个并行请求
  1. perl myapp.pl prefork -w 4 -c 1
复制代码
2.1 阻塞操作,4个并行请求
  1. Jacks-MacBook-Pro:Project jzhangkun$ ab -n 4 -c 4 127.0.0.1:3000/worker1
  2. This is ApacheBench, Version 2.3 <$Revision: 655654 $>
  3. Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
  4. Licensed to The Apache Software Foundation, http://www.apache.org/

  5. Benchmarking 127.0.0.1 (be patient).....done


  6. Server Software:        Mojolicious
  7. Server Hostname:        127.0.0.1
  8. Server Port:            3000

  9. Document Path:          /worker1
  10. Document Length:        23 bytes

  11. Concurrency Level:      4
  12. Time taken for tests:   5.024 seconds
  13. Complete requests:      4
  14. Failed requests:        0
  15. Write errors:           0
  16. Total transferred:      740 bytes
  17. HTML transferred:       92 bytes
  18. Requests per second:    0.80 [#/sec] (mean)
  19. Time per request:       5024.368 [ms] (mean)
  20. Time per request:       1256.092 [ms] (mean, across all concurrent requests)
  21. Transfer rate:          0.14 [Kbytes/sec] received

  22. Connection Times (ms)
  23.               min  mean[+/-sd] median   max
  24. Connect:        0    0   0.0      0       0
  25. Processing:  5018 5022   2.9   5024    5024
  26. Waiting:     5018 5022   2.9   5024    5024
  27. Total:       5018 5022   2.9   5024    5024

  28. Percentage of the requests served within a certain time (ms)
  29.   50%   5024
  30.   66%   5024
  31.   75%   5024
  32.   80%   5024
  33.   90%   5024
  34.   95%   5024
  35.   98%   5024
  36.   99%   5024
  37. 100%   5024 (longest request)
复制代码
设想是每个worker处理一个请求,5s内能处理完

2.2 非阻塞操作,4个并行请求
  1. Jacks-MacBook-Pro:Project jzhangkun$ ab -n 4 -c 4 127.0.0.1:3000/worker2
  2. This is ApacheBench, Version 2.3 <$Revision: 655654 $>
  3. Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
  4. Licensed to The Apache Software Foundation, http://www.apache.org/

  5. Benchmarking 127.0.0.1 (be patient).....done


  6. Server Software:        Mojolicious
  7. Server Hostname:        127.0.0.1
  8. Server Port:            3000

  9. Document Path:          /worker2
  10. Document Length:        23 bytes

  11. Concurrency Level:      4
  12. Time taken for tests:   5.007 seconds
  13. Complete requests:      4
  14. Failed requests:        0
  15. Write errors:           0
  16. Total transferred:      740 bytes
  17. HTML transferred:       92 bytes
  18. Requests per second:    0.80 [#/sec] (mean)
  19. Time per request:       5007.428 [ms] (mean)
  20. Time per request:       1251.857 [ms] (mean, across all concurrent requests)
  21. Transfer rate:          0.14 [Kbytes/sec] received

  22. Connection Times (ms)
  23.               min  mean[+/-sd] median   max
  24. Connect:        0    0   0.0      0       0
  25. Processing:  5005 5006   1.0   5006    5007
  26. Waiting:     5005 5006   1.1   5006    5007
  27. Total:       5005 5006   1.0   5006    5007

  28. Percentage of the requests served within a certain time (ms)
  29.   50%   5006
  30.   66%   5006
  31.   75%   5007
  32.   80%   5007
  33.   90%   5007
  34.   95%   5007
  35.   98%   5007
  36.   99%   5007
  37. 100%   5007 (longest request)
复制代码
非阻塞更是没悬念,5s内处理完。



纵观前面的测试结果,增加worker数量确实可以帮助分散并行请求给不同的worker去处理阻塞的操作。但是我不确定降低并行数是否有效,因此我又做了下一个测试


3. prefork 4 workers, 允许每个worker接受两个请求
  1. perl myapp.pl prefork -w 4 -c 2
复制代码
3.1 阻塞操作,4个并请求
  1. Jacks-MacBook-Pro:Project jzhangkun$ ab -n 4 -c 4 127.0.0.1:3000/worker1
  2. This is ApacheBench, Version 2.3 <$Revision: 655654 $>
  3. Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
  4. Licensed to The Apache Software Foundation, http://www.apache.org/

  5. Benchmarking 127.0.0.1 (be patient).....done


  6. Server Software:        Mojolicious
  7. Server Hostname:        127.0.0.1
  8. Server Port:            3000

  9. Document Path:          /worker1
  10. Document Length:        23 bytes

  11. Concurrency Level:      4
  12. Time taken for tests:   5.006 seconds
  13. Complete requests:      4
  14. Failed requests:        0
  15. Write errors:           0
  16. Total transferred:      740 bytes
  17. HTML transferred:       92 bytes
  18. Requests per second:    0.80 [#/sec] (mean)
  19. Time per request:       5006.107 [ms] (mean)
  20. Time per request:       1251.527 [ms] (mean, across all concurrent requests)
  21. Transfer rate:          0.14 [Kbytes/sec] received

  22. Connection Times (ms)
  23.               min  mean[+/-sd] median   max
  24. Connect:        0    0   0.0      0       0
  25. Processing:  5005 5005   0.6   5006    5006
  26. Waiting:     5004 5005   0.7   5006    5006
  27. Total:       5005 5006   0.6   5006    5006
  28. WARNING: The median and mean for the processing time are not within a normal deviation
  29.         These results are probably not that reliable.
  30. WARNING: The median and mean for the waiting time are not within a normal deviation
  31.         These results are probably not that reliable.

  32. Percentage of the requests served within a certain time (ms)
  33.   50%   5006
  34.   66%   5006
  35.   75%   5006
  36.   80%   5006
  37.   90%   5006
  38.   95%   5006
  39.   98%   5006
  40.   99%   5006
  41. 100%   5006 (longest request)
复制代码
从这个结果来看,mojo还是将4个请求平均分散给4个worker,而不是分两个给两个worker,那么降低每个worker并行处理数量的意义何在?

不知道各位对这一系列处理行为有什么特殊看法?另外,mojo是如何去检测阻塞的worker并分配并行请求的,是否有文档呢?谢谢!

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
16 [报告]
发表于 2013-12-19 20:19 |只看该作者
回复 15# kk861123

所说的“增加workers减少clients”,意思不是“增加workers是有效果的做法,减少clients也是个有效的办法”。
当你的应用中所有的操作都是非阻塞的时候,你开1个worker,每个worker1000(mojo默认值)个client,你的应用同时可以有1000个并发连接。
如果你的应用中的操作是阻塞的,你开1000个worker,每个worker1个client,你的应用也可以有1000个并发连接,并且这些并发连接是同时被执行的。如果这个时候你每个worker有100个client呢?你的应用可以有100,000个并发,但因为是阻塞的,所以只能1000个1000个的处理,后进入的连接就会等待。

至于你说的“mojo是如何去检测阻塞的”,这个我不知道,也没有计划马上知道它,想知道也简单,看mojo的代码。

论坛徽章:
1
双子座
日期:2013-11-06 17:18:01
17 [报告]
发表于 2014-03-25 19:44 |只看该作者
py 发表于 2013-12-19 20:19
回复 15# kk861123

所说的“增加workers减少clients”,意思不是“增加workers是有效果的做法,减少cli ...

"当你的应用中所有的操作都是非阻塞的时候,你开1个worker,每个worker1000(mojo默认值)个client,你的应用同时可以有1000个并发连接。"
这些1000个连接可以在这1个worker里被同时处理吗

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
18 [报告]
发表于 2014-03-26 11:14 |只看该作者
seufy88 发表于 2014-03-25 19:44
"当你的应用中所有的操作都是非阻塞的时候,你开1个worker,每个worker1000(mojo默认值)个client,你的 ...


看你怎么理解这个“同时”了,单处理器单核的CPU并不存在真实意义上的“同时”,即使是多核CPU,非阻塞不是多线程,也不存在真正意义上的“同时”。

但这1000个连接是可以被认为“同时处理”的,因为真是情况下网络IO都有较长时间的等待(和CPU处理需要的时间相比),所以可以说1000个连接是同时的

论坛徽章:
1
双子座
日期:2013-11-06 17:18:01
19 [报告]
发表于 2014-03-26 15:15 |只看该作者
py 发表于 2014-03-26 11:14
看你怎么理解这个“同时”了,单处理器单核的CPU并不存在真实意义上的“同时”,即使是多核CPU,非阻塞 ...


恩,了解了。
你提到的“同时”(或是并发处理)都是相对于慢I/O(较长的等待时间)
单个process,又是非多线程的,并不存在同时

》1000个连接是可以被认为“同时处理”
这样理解,1000个FD被检测到“可读、可写”。。。
然后process挨个处理这1000个连接(如果处理时间可以忽略)
那么表面上来看,是并发处理1000个连接

非常感谢
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP