PHP meets NodeJS
-
Upload
takayuki-yamaguchi -
Category
Technology
-
view
16.405 -
download
0
description
Transcript of PHP meets NodeJS
![Page 1: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/1.jpg)
PHP meets NodeJSPHPに簡単にPUSH機能を組み込む
13年8月4日日曜日
![Page 2: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/2.jpg)
まずは自己紹介簡単に自己紹介
Name : takyam (たくやむ)
Work : WEBアプリケーションエンジニア?
Twitter : @takyam
Blog : http://new.takyam.com/
GitHub : http://github.com/takyam-git
Bitbucket : https://bitbucket.org/takyam
13年8月4日日曜日
![Page 3: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/3.jpg)
PHPで通知機能
PHPでFacebookの通知機能のようなものを実装したい事ありますよね?
画面遷移を挟まずにユーザーへの通知が表示される機能です。
私はPUSH通知と呼んでるのですがこれをPHPで作りたいとおもいます
13年8月4日日曜日
![Page 4: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/4.jpg)
通知機能を作るにはサーバー側からPUSHする必要がありますが、いくつかの手法があります
ポーリング(実際はPUSHでは無い)
Commet
Websocket
それぞれメリット・デメリットがあります
今回はWebsocketを使ってみたいと思います
13年8月4日日曜日
![Page 5: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/5.jpg)
Websocketを使う
PHP単体でもWebsocketを扱えるようなライブラリはあります
とはいえWAFに組み込むのは難しいので今回はNodeJSを使います
Websocketの部分はNodeJSに全ておまかせです!
13年8月4日日曜日
![Page 6: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/6.jpg)
NodeJS分かんねぇよ
そんな硬派なPHPerも大丈夫!
NodeJSは全部で100行くらいなので、コピペすりゃOK
一度作ればNodeJSメンテナンス不要なイケてるシステムです
13年8月4日日曜日
![Page 7: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/7.jpg)
今回のシステムの前提今回のPUSHを実現するための前提条件が2つあります
NodeJSがPHPと同ドメイン(ポート違いOK)で運用できる
Redisが使える
これだけ!
13年8月4日日曜日
![Page 8: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/8.jpg)
まずはイメージをつかむ
文字で説明するのも大変なので簡単なイメージ図をご紹介
まず最終的な完成形のイメージを掴んでください
13年8月4日日曜日
![Page 9: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/9.jpg)
最終的な構成HTTP POST
Redis PUBLISH
Redis SUBSCRIBEWebsocket Connections
13年8月4日日曜日
![Page 10: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/10.jpg)
最終的な構成HTTP POST
Redis PUBLISH
Redis SUBSCRIBEWebsocket Connections
投稿に対してのコメントをAjaxでPHPにPOSTリクエスト
13年8月4日日曜日
![Page 11: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/11.jpg)
最終的な構成HTTP POST
Redis PUBLISH
Redis SUBSCRIBEWebsocket Connections
コメントのDBへの保存処理などを実施
13年8月4日日曜日
![Page 12: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/12.jpg)
最終的な構成HTTP POST
Redis PUBLISH
Redis SUBSCRIBEWebsocket Connections
コメントが来たよ通知JSONをRedisにPUBLISH
13年8月4日日曜日
![Page 13: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/13.jpg)
最終的な構成HTTP POST
Redis PUBLISH
Redis SUBSCRIBEWebsocket Connections
SUBSCRIBEしてるNodeJSが通知JSONを受信
13年8月4日日曜日
![Page 14: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/14.jpg)
最終的な構成HTTP POST
Redis PUBLISH
Redis SUBSCRIBEWebsocket Connections
通知JSONから通知対象のユーザーを選択する
13年8月4日日曜日
![Page 15: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/15.jpg)
最終的な構成HTTP POST
Redis PUBLISH
Redis SUBSCRIBEWebsocket Connections
通知対象のユーザーのWebsocketを使ってPUSH通知(JSON)を送信!
13年8月4日日曜日
![Page 16: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/16.jpg)
最終的な構成HTTP POST
Redis PUBLISH
Redis SUBSCRIBEWebsocket Connections
受け取ったPUSH通知JSONを元に画面の表示を更新
13年8月4日日曜日
![Page 17: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/17.jpg)
どうですか?そんなに複雑な構成では無いとおもいます
ポイントは以下の3つ
ユーザーからのデータ送信はAjaxので処理する
Redis経由でPHPがNodeJSに、一方通行でJSONを送る
NodeはPHPからのJSONを元にWebsocketでデータを送信する
13年8月4日日曜日
![Page 18: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/18.jpg)
なんでAjax?
コレ以上Nodeに複雑な処理持たせたくないから
PHP側だけで処理できる事はPHPだけでやった方が楽ですよね
13年8月4日日曜日
![Page 19: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/19.jpg)
Redisのpub/sub?
これもNode側の実装が楽だから
HTTPリクエスト処理するための何やかんや用意しなくてOK
JSONかわいいよJSON
13年8月4日日曜日
![Page 20: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/20.jpg)
Nodeが送信?
Nodeは決まったフォーマットのJSONに従ってJSONを配信するだけ
つまり、かなり定型的な処理しか行わない
つまり、Nodeの実装が楽っ☆
13年8月4日日曜日
![Page 21: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/21.jpg)
つまり
いかにNodeを触らなくて良いかを考えた構成になってます
Node大好きっ子ですが、メインがPHPなので複雑にしたくなかったのです
13年8月4日日曜日
![Page 22: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/22.jpg)
PHP/Node間のJSON“target_user_ids” のWebsocketに対して “data” を送るだけですね
{ “target_user_ids”: [1,2,10,22], “data”: { “type”: “notice_message”, “message”: “コメントがありました”,
“datetime”: “2013-08-03 15:12:32” }}
←配信対象のユーザーIDリスト
←配信データ}13年8月4日日曜日
![Page 23: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/23.jpg)
“target_user_ids”???
ユーザーIDはPHP側にしか持ってません
NodeJS側は会員認証も何も持ってないのだから
ユーザーID渡されてもどのWebsocketがどのユーザーIDか分からなくね?
13年8月4日日曜日
![Page 24: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/24.jpg)
ユーザーIDをNodeと共有
というわけで、ここが肝なのですが、ユーザーIDをNode側に知らせる必要があります
方法は簡単、ユーザーIDを返すAPIをPHP側に用意するだけ!
ではイメージ図いってみましょう
13年8月4日日曜日
![Page 25: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/25.jpg)
ユーザーID取得処理
13年8月4日日曜日
![Page 26: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/26.jpg)
ユーザーID取得処理1.ページを開く(GETリクエスト)
13年8月4日日曜日
![Page 27: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/27.jpg)
ユーザーID取得処理1.ページを開く(GETリクエスト)
2. HTML/JSを返す
13年8月4日日曜日
![Page 28: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/28.jpg)
ユーザーID取得処理1.ページを開く(GETリクエスト)
3. Websocketを繋ぐ(リクエスト)
2. HTML/JSを返す
13年8月4日日曜日
![Page 29: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/29.jpg)
ユーザーID取得処理1.ページを開く(GETリクエスト)
3. Websocketを繋ぐ(リクエスト)
2. HTML/JSを返す
Session Cookie
SessionCookieが同時に送られる
13年8月4日日曜日
![Page 30: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/30.jpg)
ユーザーID取得処理1.ページを開く(GETリクエスト)
3. Websocketを繋ぐ(リクエスト)
2. HTML/JSを返す
Session Cookie
SessionCookieが同時に送られる
4. Websocket接続確立
13年8月4日日曜日
![Page 31: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/31.jpg)
ユーザーID取得処理1.ページを開く(GETリクエスト)
3. Websocketを繋ぐ(リクエスト)
2. HTML/JSを返す
Session Cookie
SessionCookieが同時に送られる
5.NodeからPHPにHTTPリクエスト
4. Websocket接続確立
13年8月4日日曜日
![Page 32: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/32.jpg)
ユーザーID取得処理1.ページを開く(GETリクエスト)
3. Websocketを繋ぐ(リクエスト)
2. HTML/JSを返す
Session Cookie
SessionCookieが同時に送られる
5.NodeからPHPにHTTPリクエスト
Session Cookie受け取ったSession
Cookieを添えて
4. Websocket接続確立
13年8月4日日曜日
![Page 33: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/33.jpg)
ユーザーID取得処理1.ページを開く(GETリクエスト)
3. Websocketを繋ぐ(リクエスト)
2. HTML/JSを返す
Session Cookie
SessionCookieが同時に送られる
5.NodeからPHPにHTTPリクエスト
Session Cookie受け取ったSession
Cookieを添えて
6.ユーザーIDを返す4. Websocket接続確立
13年8月4日日曜日
![Page 34: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/34.jpg)
ユーザーID取得処理1.ページを開く(GETリクエスト)
3. Websocketを繋ぐ(リクエスト)
2. HTML/JSを返す
Session Cookie
SessionCookieが同時に送られる
5.NodeからPHPにHTTPリクエスト
Session Cookie受け取ったSession
Cookieを添えて
6.ユーザーIDを返す4. Websocket接続確立
7.WebsocketとユーザーIDを紐付ける
13年8月4日日曜日
![Page 35: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/35.jpg)
ポイントは1.ページを開く(GETリクエスト)
3. Websocketを繋ぐ(リクエスト)
2. HTML/JSを返す
Session Cookie
SessionCookieが同時に送られる
5.NodeからPHPにHTTPリクエスト
Session Cookie受け取ったSession
Cookieを添えて
6.ユーザーIDを返す4. Websocket接続確立
7.WebsocketとユーザーIDを紐付ける
13年8月4日日曜日
![Page 36: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/36.jpg)
ポイントは1.ページを開く(GETリクエスト)
3. Websocketを繋ぐ(リクエスト)
2. HTML/JSを返す
Session Cookie
SessionCookieが同時に送られる
5.NodeからPHPにHTTPリクエスト
Session Cookie受け取ったSession
Cookieを添えて
6.ユーザーIDを返す4. Websocket接続確立
7.WebsocketとユーザーIDを紐付ける
Websocketコネクション時のHandshakeの時に
PHP側のSessionCookieが送られる
13年8月4日日曜日
![Page 37: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/37.jpg)
ポイントは1.ページを開く(GETリクエスト)
3. Websocketを繋ぐ(リクエスト)
2. HTML/JSを返す
Session Cookie
SessionCookieが同時に送られる
5.NodeからPHPにHTTPリクエスト
Session Cookie受け取ったSession
Cookieを添えて
6.ユーザーIDを返す4. Websocket接続確立
7.WebsocketとユーザーIDを紐付ける
SessionCookieを含めてPHPにリクエストつまり、PHP的にはユーザーからのリクエストと一緒
13年8月4日日曜日
![Page 38: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/38.jpg)
Nodeがユーザーになりきれる
Node側がユーザーを偽装する事ができますね!
PHP側がリクエストユーザーの、ユーザーIDを返すAPIを用意すればOK
これで、WebsocketにPHP側のユーザーIDを紐付ける事ができます
13年8月4日日曜日
![Page 39: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/39.jpg)
ユーザーID偽装のために
PHP側のSessionCookieをNode側に送信する必要があります
Cookieの送信ポリシー的に同じドメインである必要があります
なので、ポートは違っていいですが、NodeもPHPも同ドメインで運用してください
13年8月4日日曜日
![Page 40: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/40.jpg)
というわけで
省エネでPHPからPUSH通知を送る事ができます
例としてPHPあげましたが、PerlでもRubyでも同じ事はできるはずです
13年8月4日日曜日
![Page 41: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/41.jpg)
最後にこの資料作るきっかけになった投稿をくれた方々に感謝です
https://groups.google.com/forum/#!topic/nodejs_jp/gU2347-33PQ
簡単なサンプル(通知ではなくてチャットですが)も作りましたのでよろしければ
https://github.com/takyam-git/phpchat_example/
13年8月4日日曜日
![Page 42: PHP meets NodeJS](https://reader034.fdocuments.net/reader034/viewer/2022052619/5564af5bd8b42a3e618b4778/html5/thumbnails/42.jpg)
ありがとうございました
ご連絡は @takyam までぜひぜひ~
ブログも見てね~
http://new.takyam.com/
13年8月4日日曜日