PHP meets NodeJS

17,565
-1

Published on

PHPにPUSH通知(リアルタイム処理)機能を導入するために、NodeJSと連携するための簡単な概要を説明してみました。特にどこかで発表した資料とかでは無いっす。
資料のライセンスはMITです。

Published in: Technology
0 Comments
34 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
17,565
On Slideshare
0
From Embeds
0
Number of Embeds
17
Actions
Shares
0
Downloads
42
Comments
0
Likes
34
Embeds 0
No embeds

No notes for slide

PHP meets NodeJS

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

×