Mojolicious+redisでチャットを作った

3,126 views

Published on

Published in: Technology, Career
0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,126
On SlideShare
0
From Embeds
0
Number of Embeds
76
Actions
Shares
0
Downloads
5
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide

Mojolicious+redisでチャットを作った

  1. 1. Mojolicious+Redisでチャット を作った Mishima.pm #1 @dokechin
  2. 2. Mojolicious • Perl のWeb Application Framework • 広大なMojoネーム空間のモジュール群をWeb アプリで使うようにしたもの
  3. 3. http://blog2.jamadam.com/?p=808 より引用
  4. 4. 私の考えるメリット • 開発コミュニティが世界的に活発 (MojoConf2014 in オスロなど。2015への 積立金もすでにプールされている。) • ドキュメント豊富、サンプルソースも一杯あふ れている • All in One • 環境構築が楽、cpanm Mojolicious
  5. 5. 非同期な話 1.MojoliciousとNode.jsは非同期サーバ
  6. 6. Mojoliciousでsleepしてみた #!/usr/bin/env perl use Mojolicious::Lite; get '/' => sub { my $self = shift; sleep(10); $self->render('index'); }; get '/hoge' => sub { my $self = shift; $self->render('hoge'); }; app->start;
  7. 7. /をGETその後すぐ、/hogeをGET /hogeが先に返ってくるのでは・・ と期待していたが・・・
  8. 8. 結果は・・ /が返ってから/hogeが返ってくる! 処理の流れを1つにすることで、サーバー資源を 節約?どこかで聞いたことあるなぁ・・・
  9. 9. 非同期な話 2.非同期vs同期ベンチマーク
  10. 10. 同期なコード package Test::Web::Example; use Mojo::Base 'Mojolicious::Controller'; use Time::HiRes qw(sleep); sub welcome { my $self = shift; sleep(0.5); $self->render( message => 'Welcome to the Mojolicious real-time web framework!'); } 1;
  11. 11. 非同期なコード package Test::Web::Example; use Mojo::Base 'Mojolicious::Controller'; use Time::HiRes qw(sleep); sub welcome { my $self = shift; $self->render_later; Mojo::IOLoop->timer(0.5 => sub { $self->render( message => 'Welcome to the Mojolicious real-time web framework!'); }); } 1;
  12. 12. Apache bench ab –c 100–n 1000 http://your_host_name/ サーバ構成 さくらVPS メモリ 1G CPU 仮想2コア nginx1.6+hyponotad 5workers nginx1.6+starman 5workers
  13. 13. 結果 0 100 200 300 400 500 600 0 0.2 0.4 0.6 0.8 1 1.2 同期(starman+5workers) 非同期(hyponotad+5worker) 同期(hyponotad+5worker)
  14. 14. トレードオフ 容易な同期的プログラ ミング 難しい非同期プログラ ミング サーバリソース大 サーバリソース小
  15. 15. その他、ベンチをやって気づいたこと ・starman,startletでは、Mojoliciousの非同期機能 が使えない
  16. 16. 非同期な話 3.実践的な非同期コードについて
  17. 17. 同期的コード sub mojo4{ my $self = shift; my $ua = LWP::UserAgent->new; my $res = $ua- >get("http://atndfc.dokechin.com"); if ($res->is_success) { $self->render(message => $res->content); } else { die $res->status_line; } }
  18. 18. 非同期的コード package Test::Web::Example; #use Mojo::UserAgent; sub mojo{ my $self = shift; $self->ua- >get('http://metacpan.org/search?q=mojo' =>sub{ my ($ua, $tx) = @_; $self->render(message => $tx->res); }); } 1;
  19. 19. Mojolicious用各種非同期APIを使う Mojo::Redis(Redis非同期クライアント) Mango(Mongo非同期クライアント)
  20. 20. ブロッキングAPIしかない場合 Mojo::IOLoop::ForkCall - run blocking functions asynchronously by forking
  21. 21. 非同期な話 3.Callback hellを避けるためには
  22. 22. # callback hell code sub mojo{ my $self = shift; $self->render_later; $ua->get('http://yahoo.co.jp/' => sub{ my ($ua, $tx) = @_; my $title1 = $tx->res->dom->html->head- >title->text; $ua->get('http://google.com/' => sub{ my ($ua, $tx) = @_; my $title2 = $tx->res->dom->html->head- >title->text; $self->render(msg => $title1 . $title2); }); }); }
  23. 23. # finish sub mojo2{ my $self = shift; $self->render_later; my $delay = Mojo::IOLoop::Delay->new; $delay->on(finish=>sub{ my $delay = shift; my @titles = map { $_->res->dom- >at('title')->text } @_; $self->render(message => "@titles"); }); $self->ua->get( $_ => $delay->begin ) for@urls; }
  24. 24. # stepsを利用したコード sub mojo3{ my $self = shift; $self->render_later; my $delay = Mojo::IOLoop::Delay->new; $delay->steps(sub{ my ($delay) = @_; $self->ua->get( "http://www.cpan.org/" => $delay->begin); $self->ua->get( "http://jognavi.com/" => $delay- >begin); }, sub { my ($delay,@args) = @_; my @messages = map {$_->res->dom->at('title')- >text} @args; $self->render(message=> "@messages"); }, ); }
  25. 25. チャットを作った話 • まずはデモ
  26. 26. morbo W WebSocket WebSocket WebSocketWebSocket UserA UserB UserC UserD ・すべておなじプロセス配下のため、同じ部屋 の発言の通知は可能。 ・スケーラブルでない RoomA RoomB
  27. 27. hypnotoad W WebSocket WebSocket WebSocketWebSocket UserA UserB UserC UserD RoomA RoomB Wプロセス間通信の手段が必要
  28. 28. Redis(部屋、部屋の入居者管理) W WebSocket WebSocket WebSocketWebSocket W RoomA RoomB Red is UserA UserB UserC UserD
  29. 29. Redis-オブジェクトキャッシュ rooms => {“rooma”,”roomb”} rooma=>{“userA”,”userB”} roomb=>{“userC”,”userD”}
  30. 30. RedisのPubSub UserA,UserBがRoomAチャンネルを購買。UserA がRoomAチャンネルへ発言、チャンネルAの購 買者(UserA,UserB)に発言内容が通知される。
  31. 31. まとめ • 非同期はパフォーマンスがよくなるが、コード は複雑化する。 • Mojoliciousは非同期に動かす仕組み(モジュール、 サーバ)が、備わっている。 • 本番環境での運用を視野にするならば、初めか らRedisなど、Kye-Valueストアを使ったほうが よい?
  32. 32. ご清聴ありがとうございました

×