laravel websocket(use redis pubsub) [laravel meetup tokyo]

Post on 15-Jan-2015

2.192 Views

Category:

Technology

8 Downloads

Preview:

Click to see full reader

DESCRIPTION

laravel meetup tokyo Vol.3 発表のスライドです。 laravelを使ったwebsocket実装でredisのpubsubを用いた内容です sample code https://github.com/ytake/laravel-websocket

TRANSCRIPT

laravel + websocket + RedisLaravel Meetup Tokyo JP Vol.3 2014/04/05

yuuki.takezawa

PROFILE

yuuki takezawa social

github (https://github.com/ytake) facebook (https://www.facebook.com/yuuki.takezawa)

qiita (http://qiita.com/ytake) twitter(https://twitter.com/ex_takezawa)

!ベンチャー、フリー、現

php node.js RDBMS NoSQL !

sample code

本発表と対応したサンプルは下記になります https://github.com/ytake/laravel-websocket

!

laravelってどんなの?

良い意味でとにかく話題が多い => 注目度高い? illuminateコンポーネントの手軽さ container, databaseおすすめです

redis好きにはたまらない親和性(個人的な意見) 簡単に書くこともできて、がっちり堅実派にもおすすめ(間口が広い)

codeigniter系とはまたちょっと違う

Laravelを使ってみた感想 Why i chose Laravel?

新しいフレームワークを探していたときにたまたま見つけた laravel歴 1年

メインで使っていて、もう手放せないくらい それまでのphpと違う記述方法にほれた

DIがとにかくシンプルかつ強力 世界とつながる強力なコミュニティ

新技術対応がスムーズ(粗結合且つシンプルさ故に) MVCだけどそうじゃない自由さ(delete model!)

Laravel ちょっとあれなところ

他のフレームワークを使う時に書き方を忘れる 大規模になるとRouterがデカい IDEヘルパー必須(補完が効かない) Symfony\Componentべったり

attention!

require mcrypt!! router 記述 (don’t forget)

chmod -R 777 app/storage composerになれていない方はこれを機に慣れましょう

Better get used to composer

websocket

What is web socket?

双方向通信規格 お互いが情報発信源

持続した接続 リアルタイム性

チャット、お絵描き共有、ブラウザゲームなど 仲間はAjax long polling、HTTP Polling、Silverlightなど

モダンブラウザ以外は非対応

一般的なHTTP通信(イメージ)

requestがあってresponseがあります !

websocket(イメージ)

サーバからの一方的なrequestも可能になりました !

websocket 複数台あるけど 同期どうやるの?

What is Redis?

NoSQLという分類に入るインメモリ KVS (RDBMSはもういらない という意味じゃありません)

データの永続性(再起動してもデータあります) 早い、らくちん

(インメモリ故に低コストとは言いがたい) CPUの1コアを使う

イベントドリブンで即反応 スキーマなどはありません

memcachedのようにsession, cacheもおまかせ STRINGS, LISTS, SETS, HASHES, SORTED SETS

なぜRedisなのか

pubsubsubscriberへpublish

登録している全プロセスへ通知

実装

必要なもの

Redis zeromq php extension(PECL or build)

event extension(PECL) phpiredis extension(hiredis必要)

!React Ratchet

Predis\Async

つかったもの

Routing Controllers

Ioc Container(bind, make, service provider) Artisan CLI Model(Redis) Blade template

Modelmodel sample !class Datastore implements DatastoreInterface{ ! const KEY = "timeline:"; ! /** * @param array $array * @return mixed */ public function set(array $array) { return \Redis::connection()->rpush(self::KEY, json_encode($array)); } ! /** * @return \stdClass */ public function get() { $array = []; $result = \Redis::connection()->lrange(self::KEY, 0, -1); if(count($result)) { array_walk($result, function($value) use(&$array){ $array[] = json_decode($value); }); return $array; } return $result; } !

Controllercontroller sample interfaceをタイプヒンティング(redis以外の何かにするかもしれない!) ! protected $datastore; ! /** @param DatastoreInterface $datastore */ public function __construct(DatastoreInterface $datastore) { $this->datastore = $datastore; } ! public function index() { $view = \View::make('emit.index'); $view->with('list', $this->datastore->get()); return $view; } ! public function store() { if($this->datastore->publish( ['body' => \Input::get('body', null)])) { return \Response::json(['result' => true] ,200); } }

ServiceProviderServiceProvider sample app/config/app.php, app/config/{env}/app.phpに忘れずに追記します クラスとインターフェースの関係性を実装 CLIの追加は、ServiceProvider、またはstart/artisan.phpで追加可能です ! public function register() { $this->app->bind("Model\Interfaces\AsyncInterface", function(){ return new \Models\Redis\Async(new \ZMQContext()); }); ! $this->app->bind("Ratchet\Wamp\WampServerInterface", "Models\Websocket\Push"); ! $this->app->bind("pubsub.server", function() { return new \App\Commands\PubSubCommand( $this->app->make("Model\Interfaces\AsyncInterface"), $this->app->make("Ratchet\Wamp\WampServerInterface") ); }); $this->commands("pubsub.server"); } ! public function provides() { return ["pubsub.server"]; } !!

ArtisanArtisan sample 実装していきます (Symfony\Component\Console) ! public function __construct(AsyncInterface $loop, WampServerInterface $wamp) { parent::__construct(); $this->loop = $loop; $this->wamp = $wamp; } ! public function fire() { $loop = $this->loop->async(); $this->info('redis subscribe start'); ! $this->pull($loop, $this->wamp); ! $webSock = new \React\Socket\Server($loop); $webSock->listen($this->option('port'), '0.0.0.0'); ! $webServer = new \Ratchet\Server\IoServer( new \Ratchet\Http\HttpServer( new \Ratchet\WebSocket\WsServer( new \Ratchet\Wamp\WampServer($this->wamp) ) ), $webSock); ! $this->info('websocket server boot'); $this->comment('Listening on port ' . $this->option('port')); $loop->run(); }

Exception

app/start/global.php エラーをcatchして処理してくれます !<?php !App::error(function(\Symfony\Component\HttpKernel\Exception\NotFoundHttpException $exception, $code) { return \Response::make('not found', 404); }); !!App::error(function(\Predis\Connection\ConnectionException $exception, $code) { return "Redis {$exception->getMessage()}"; });

便利なものを作ったら パッケージとして公開しましょう!

!日本ではまだまだこれから

top related