免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 13882 | 回复: 18
打印 上一主题 下一主题

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

论坛徽章:
1
辰龙
日期:2014-05-15 19:37:15
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-11-06 13:31 |只看该作者 |倒序浏览
本帖最后由 iakuf 于 2013-11-06 13:35 编辑

上次 , 我想你看了用 Mojolicious 实现 写非阻塞的 (web) 应用  .在那个例子中,  每个动作都只执行了单个的非阻塞的动作. 在今天这篇文章中, 我打算讲深入一点.向你介绍 Mojo::IOLoop::Delay ,今天我们的例子会使用这个 delay 对象来等待同时执行的多个非阻塞的操作.直到他们完成操作之前, 在同一个进程内服务器都不会阻断其它请求的处理.

译者注: Mojo::IOLoop::Delay 这个模块是我最喜欢 Mojo 的一个原因, 大量的用到了这种技术, 这个模块做事件同步超级方便. 使用这种技术, 非常实用,例如, 我们一个动作可能要查询多次数据库, 我们可能想都查询出来,才做下一个动作.  我也写过一个这样的文章,可以看 "Mojolicious 之类事件程序的异步和技巧"

The Application

这个应用的演示和全部代码在 , 通过这个例子, 这个应用的目标是从其它的 websites 站点取得网站标题的列表. 这是一个简单的任务,但非常有用,也能说明更加复杂的一些情况.

       
  1. #!/usr/bin/env perl

  2. use Mojolicious::Lite;
  3. app->ua->max_redirects(10);

  4. my @urls = qw/mojolicio.us mojocasts.com/;

  5. helper 'render_dumper' => sub {
  6.   my $self = shift;
  7.   $self->render( text => $self->dumper( \@_ ) );
  8. };

  9. # The routes will go here!

  10. app->start;
复制代码


必然,我需要导入 Mojolicious::Lite, 这会自动的导入 strict, warnings, utf8 和  v5.10 的特性. 每个应用内部其实有默认的 Mojo::UserAgent 的 ua 的 helper . 我们会在以后使用它. 接下来的行, 我们重新定义了 redirect 对每个请求最多可以 10 次. 接下来我们定义了一个 @urls 的列表, 是我们接下来要抓取的网站. 在这个例子中, 我其实建议你写更加多的网站地址, 但现在,我们只是一个演示.

我们可以通过 helper 来创建很多有意思的 rendering helper . 在这是一个简单的 web 接口的应用, 在这我们会给全部的参数通过我们自己创建的 Data::Dumper  的 helper 来 dump 出来. 当然 ,如果你有兴趣, 也可以给 render_dumper 这个自己的 helper 替换为  $self->render( json => [...] ) 这样会使用原生的 Mojo::JSON 来渲染这个数据结构,也会更加容易.

其它的路由的子函数没列出来, 我们先跳过这些. 现在我们启动我们的应用程序, 注意我们这个例子中没使用任何模板.

如果你存成 titles.pl 你可以这样运行

[code]perl titles.pl get

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
2 [报告]
发表于 2013-11-06 13:44 |只看该作者
支持!我上午才看了原文,这么快就翻译出来了。

论坛徽章:
1
辰龙
日期:2014-05-15 19:37:15
3 [报告]
发表于 2013-11-06 17:01 |只看该作者
本帖最后由 iakuf 于 2013-11-06 17:01 编辑

回复 2# py

我其实写了一个 AnyEvent::Delay 实现一样的功能的, 明天我看来要放到 cpan 上去. 这样普通 AnyEvent 的应用用起来就方便.


   

求职 : 软件工程师
论坛徽章:
3
程序设计版块每日发帖之星
日期:2015-10-07 06:20:00程序设计版块每日发帖之星
日期:2015-12-13 06:20:00程序设计版块每日发帖之星
日期:2016-05-05 06:20:00
4 [报告]
发表于 2013-11-06 17:18 |只看该作者
本帖最后由 104359176 于 2013-11-06 17:20 编辑

我理解的非阻塞方式编程,不知道对不对:

发送请求和接收响应分成了两个独立的进程或协程。每个发送的请求都会自动进行编号,并且将这个编号放到缓冲队列中。当对应的响应到达时,也会按照请求编号的原则,保存在缓冲的一个队列中,并同时触发请求缓冲队列中相应编号的信息,触发一个消息,发送到一个消息队列中。系统进程在发送间隙,会检测这个消息队列,并执行相应挂起的进程或协程,处理应答。

而在编程层面,很多东西隐藏起来,程序员看不到缓冲队列,也看不到挂起的进程,只看到 编程风格,这似乎让很多人很难理解。

论坛徽章:
0
5 [报告]
发表于 2013-11-12 08:25 来自手机 |只看该作者
非常感谢您的分享!使用Mojo::IOLoop:elay来实现非阻塞果然清晰明了。作者也提到实现这个,所请求的程序也一定要有非阻塞机制,像上个例子的mango和这个例子中的ua。我还不清楚如何为自己的程序实现这种非阻塞机制,是不是从AnyEvent入手?谢谢!

论坛徽章:
1
辰龙
日期:2014-05-15 19:37:15
6 [报告]
发表于 2013-11-12 10:20 |只看该作者
回复 5# kk861123


   如果你本地安装了 EV(理解成 AnyEvent 的一个驱动) 的话, Mojo 本身就会使用 EV 做事件驱动. 这样所有 AnyEvent 的模块在 Mojo 内部可以直接使用.

论坛徽章:
0
7 [报告]
发表于 2013-11-13 03:40 |只看该作者
  1. get '/counter' => sub {
  2.   my $self = shift;
  3.   # Synchronize multiple events
  4.   my $delay = Mojo::IOLoop::Delay->new;
  5.   $delay->on(finish => sub { $self->render( text => 'BOOM!') });
  6.   for my $i (1 .. 10) {
  7.     my $end = $delay->begin;
  8.     Mojo::IOLoop->timer($i => sub {
  9.       my $left = 10 - $i;
  10.       say $left;
  11.       $end->($left);   #? doesn't work ...
  12.     });
  13.   }
  14.   $delay->wait unless Mojo::IOLoop->is_running;
  15. };
复制代码
@iakuf[@]py[/@]

can you help take a look at this sample? I want to figure out how to pass the parameters to $delay->begin, but failed...

论坛徽章:
0
8 [报告]
发表于 2013-11-13 03:42 |只看该作者
[@]py[/@] can you help as well? thanks!

论坛徽章:
0
9 [报告]
发表于 2013-11-13 06:39 |只看该作者
I found the solution! the ticky part is in "begin", which will automaticlly strip the first arguments. so I changed 11th line to:
  1. $end->(0,$left);
复制代码
please correct me if I was wrong. Thanks all!

PS: sorry for having to type in english as the computer from my company doesn't support chinese enviroment right now.

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
10 [报告]
发表于 2013-11-13 07:30 |只看该作者
kk861123 发表于 2013-11-13 06:39
I found the solution! the ticky part is in "begin", which will automaticlly strip the first argument ...


这个问题我也遇到过。
当begin这个callback需要参数传递的时候,就要写成$delay->begin(0)。(这其实在文档中有说明的,当时没仔细看)
例如,当需要配合 Mojo::IOLoop:elay 使用AnyEvent:BI::MySQL的时候,就要begin(0)
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP