Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PHPで書いて覚える非同期処理 / php-async-programming

PHPで書いて覚える非同期処理 / php-async-programming

これを読んでも、非同期処理はわかりませんが、暗いトンネルの先に光が見えます。

Ryo Tomidokoro

October 03, 2021
Tweet

More Decks by Ryo Tomidokoro

Other Decks in Technology

Transcript

  1. @hanhan1978
    PHPで
    書いて覚える非同期処理
    PHPカンファレンス 2021

    View Slide

  2. @hanhan1978
    ● 富所 亮
    ● 所属
    ○ 株式会社カオナビ
    ● 職業
    ○ Webアプリケーションエンジニア
    ● ブログ
    ○ https://blog.hanhans.net
    ● Yokohama North AM
    ○ https://anchor.fm/yokohama-north-am
    2

    View Slide

  3. はじめに
    3

    View Slide

  4. 4
    PHPアプリケーションは
    同期的なBlocking IOが基本

    View Slide

  5. 5
    私達が書いたプログラムは書いた順番に
    処理されて動作する
    人間の脳にとてもやさしい

    View Slide

  6. 6
    非同期は、分かりにくい
    界隈では、関連情報が増加してきているのは感じる
    Swoole, React, AmPHP…. Generator, Fiber

    View Slide

  7. 7
    書いたプログラムは書いた順番に動くとは
    限らない
    人間の脳にとても厳しい

    View Slide

  8. 8
    今回のテーマ

    View Slide

  9. 9
    「非同期が分からない!」
    を分解

    View Slide

  10. 10
    今日のテーマ

    View Slide

  11. 11
    裏テーマ

    View Slide

  12. 12
    システムコールとか、Socket通信とかを
    PHPで書こうと思う人を増やす

    View Slide

  13. 13
    Webサーバーが作れるようになるぞ!
    https://speakerdeck.com/hanhan1978/phpdewebsabazuo-rou

    View Slide

  14. PHPでPHPを動かす時代が来る!
    14
    多分

    View Slide

  15. 小ネタ
    平行じゃない => 並行
    平行 : parallel
    並行 : concurrent, (parallel)
    並列 : parallel
    15

    View Slide

  16. 1. 用語の定義
    2. なぜ必要なのか?
    3. 非同期関連の実装
    4. PHPで使える解決策
    目次
    16

    View Slide

  17. 同期的なプログラミング
    記述したとおりの順番で動作するようなプログラミングモデル
    非同期プログラミング
    独立して発生するイベントに対する処理を記述するための並行プログラミン
    グ手法の総称
    17
    高野祐輝. (2021). 並行プログラミング入門 5章 (初版.). オライリー・ジャパン.

    View Slide

  18. 同期的なプログラミング
    記述したとおりの順番で動作するようなプログラミングモデル
    非同期プログラミング
    独立して発生するイベントに対する処理を記述するための並行プログラミン
    グ手法の総称
    18
    高野祐輝. (2021). 並行プログラミング入門 5章 (初版.). オライリー・ジャパン.
    処理の順番はイベントの発
    生順に依存する

    View Slide

  19. 19
    Async Programming - ColdBox HMVC Documentation
    https://coldbox.ortusbooks.com/digging-deeper/promises-async-programming

    View Slide

  20. 20
    Async Programming - ColdBox HMVC Documentation
    https://coldbox.ortusbooks.com/digging-deeper/promises-async-programming
    タスクは直列に実行され
    るため、全ての処理を足
    し合わせた実行時間にな

    View Slide

  21. 21
    Async Programming - ColdBox HMVC Documentation
    https://coldbox.ortusbooks.com/digging-deeper/promises-async-programming
    タスクは並列に実行され
    るため、全体の処理時間
    ≒ 最も長いタスクの時間

    View Slide

  22. 22
    例えばPHP

    View Slide

  23. 23
    ToDoリストを検索するバックエンドの処理(例)

    View Slide

  24. 24
    ToDoリストを検索するバックエンドの処理(例)
    直列に処理しなければ、整合
    性が取れない。
    同期的処理に意味がある

    View Slide

  25. 25
    例えばJavaScript

    View Slide

  26. 26
    buttonクリックで発生するイベント

    View Slide

  27. 27
    buttonクリックで発生するイベント
    ボタンがいつ押されるかは分
    からない。
    非同期的処理に意味がある

    View Slide

  28. 28
    例えばJavaScript - part2

    View Slide

  29. 29
    ページ読込み後にAjaxでAPIをコールする例

    View Slide

  30. 30
    buttonクリックで発生するイベント
    付帯情報は、あとでページに表示
    されれば問題ない
    非同期的処理に意味がある

    View Slide

  31. 改めて比べてみると
    向き・不向きに合わせてプログラミングモ
    デルが選択されているだけ
    31
    特にJavaScriptは、処理をブロックしないことに心血を注いでいる

    View Slide

  32. 32
    小ネタ2
    JSの人たち
    「たまには同期してほしい」
    PHPの人たち
    「たまには非同期してほしい」

    View Slide

  33. 1. 用語の定義
    2. なぜ必要なのか?
    3. 非同期関連の実装
    4. PHPで使える解決策
    目次
    33

    View Slide

  34. 34
    JavaScriptで考えてみる

    View Slide

  35. 35
    Amazon トップページ

    View Slide

  36. 36
    Amazon トップページ
    各要素は、スクロールに合わ
    せて読み込まれる
    非同期であることがUX向上に
    ダイレクトにつながる

    View Slide

  37. JSの非同期処理の実行モデル
    37
    https://zenn.dev/qnighy/articles/345aa9cae02d9d

    View Slide

  38. 38
    PHP(バックエンド)で考えてみる

    View Slide

  39. 39
    いわゆるMVCフレームワーク

    View Slide

  40. 40
    いわゆるMVCフレームワーク
    1. 認証して

    View Slide

  41. 41
    いわゆるMVCフレームワーク
    2. 過去の参加イベントを
    取る

    View Slide

  42. 42
    いわゆるMVCフレームワーク
    3. メインに表示する情報
    を取得

    View Slide

  43. 43
    非同期にしてしまうと、事前に必要なデー
    タが取れていない。
    同期的であることに意味があるパターン
    が多い。

    View Slide

  44. 44
    バックエンドのひとつのエンドポイントから
    考えると、非同期処理の必要性が分から
    なくなる

    View Slide

  45. 45
    うまく適用できた例

    View Slide

  46. 46
    https://speakerdeck.com/suzuki/guzzle-promisewoshi-tuta-fei-tong-qi-chu-li-niy
    oruapikorufalsegao-su-hua

    View Slide

  47. 47
    https://www.slideshare.net/techblogyahoo/phpioyield-phpcon2014

    View Slide

  48. 48
    同時に実行しても問題ないIO処理を束ね

    View Slide

  49. 49
    その他の適用例

    View Slide

  50. 50
    Queue

    View Slide

  51. 51
    Laravel Queues [ Pocket Guide ] - DEV Community
    https://dev.to/mvpopuk/laravel-queues-pocket-guide-c6a

    View Slide

  52. 52
    イベント監視が別プロセスだけど...
    メール送信、退会バッチ処理等、適用範囲も広
    い。長いIOを他のプロセスにまかせてしまい結
    果をすばやく戻す

    View Slide

  53. 53
    PHP単体だと、非同期処理は適用範囲が
    狭い

    View Slide

  54. 54
    なぜ非同期フレームワークは生まれ
    なぜFiberは実装されるのか

    View Slide

  55. 55
    視野を広げてみる必要がある

    View Slide

  56. 56
    いわゆる PHP のWebアプリ

    View Slide

  57. 57
    Nginx + PHP-FPM
    PHP処理系の気の効いた図

    View Slide

  58. 1リクエストに対して 1つのPHP実行プロセス
    58

    View Slide

  59. 1リクエストに対して 1つのPHP実行プロセス
    59
    各リクエストは、隔離されたプロセ
    スで実行され、互いに影響しない

    View Slide

  60. 60
    既存のPHPの処理モデルは
    同期的、ステートレス

    View Slide

  61. 61
    例えば、Swoole PHP

    View Slide

  62. Swooleサーバーの概要図
    62

    View Slide

  63. Swooleプロセス自体が1つのPHPプロセス
    63

    View Slide

  64. Swooleプロセス自体が1つのPHPプロセス
    64
    各リクエストは、同じプロセス内で
    実行される。
    コルーチンで分離されている

    View Slide

  65. 65
    Swoole が非同期で目指すこと
    1つのコルーチンがIO処理待ちになったら、次のコ
    ルーチンに処理を移す
    CPUの利用効率をあげる。

    View Slide

  66. 66
    Swoole が目指すのは
    非同期的でステートフルな処理モデル

    View Slide

  67. 67
    しかし、エンドポイント単位の視点に立つ

    -> リクエストは同期的に処理されているよ
    うにみえる

    View Slide

  68. 68
    だから、PHPerには非同期処理がわかり
    ずらい。

    View Slide

  69. 1. 用語の定義
    2. なぜ必要なのか?
    3. 非同期関連の実装
    4. PHPで使える解決策
    目次
    69

    View Slide

  70. この章はPHPで非同期実装の感覚を養う話
    70

    View Slide

  71. 71
    PHP単体での非同期処理の仕組みはな
    い(多分)
    システムコールと組み合わせて、非同期
    に処理を行う実装を行う

    View Slide

  72. 72
    ここで、ちょっとだけ事前説明

    View Slide

  73. 73
    システムコール
    オペレーティングシステム (OS)(より明確に言えばOS
    のカーネル)の機能を呼び出すために使用される機構
    のこと。

    View Slide

  74. 74
    Socket Functions
    https://www.php.net/manual/en/ref.sockets.php

    View Slide

  75. 75
    Socket通信

    View Slide

  76. 76
    https://world4java.wordpress.com/2014/02/28/socket-programming/
    Socket Programming

    View Slide

  77. 77
    IOモデル

    View Slide

  78. 78
    ● ブロッキング IO
    ● ノンブロッキング IO
    ● IO 多重化
    ● シグナル IO
    ● 非同期 IO

    View Slide

  79. 79
    ● ブロッキング IO
    ● ノンブロッキング IO
    ● IO 多重化
    ● シグナル IO
    ● 非同期 IO ← この2つは今日は扱いません

    View Slide

  80. 80
    IOモデルを文章だけで
    理解するのは難しいので...

    View Slide

  81. 81
    Echoサーバー

    View Slide

  82. 82
    文字列を受け取って、文字列を返すだけのサーバー

    View Slide

  83. 83
    文字列を受け取って、文字列を返すだけのサーバー
    echoサーバーに接続

    View Slide

  84. 84
    文字列を受け取って、文字列を返すだけのサーバー
    入力した文字列がそのま
    ま戻ってくる

    View Slide

  85. 85
    Echoサーバー実装は、非同期処理関連の実
    装技術を知るための、極めて効果的でコスパ
    が高い方法
    写経をオススメします!!

    View Slide

  86. 86
    https://speakerdeck.com/bati11/otozhong-liang-kunaruhua
    C言語の実装例
    本当はコレを写経するのが良い
    が...

    View Slide

  87. PHPでの実装例
    87
    https://github.com/hanhan1978/shadow-php/tree/master/echo-server

    View Slide

  88. 88
    Blocking IO

    View Slide

  89. 89

    View Slide

  90. 90
    ブロッキングIO

    View Slide

  91. 91
    ブロッキングIO
    SocketでListen

    View Slide

  92. 92
    ブロッキングIO
    ここでBlock

    View Slide

  93. 93
    ブロッキングIO
    このサーバーは、通信をBlockするの
    で、一度に1クライアントしか扱えない

    View Slide

  94. 94
    NonBlocking IO

    View Slide

  95. 95

    View Slide

  96. 96
    ノンブロッキングIO
    SocketをNonBlockに設定

    View Slide

  97. ノンブロッキングIO
    97

    View Slide

  98. ノンブロッキングIO
    98
    このサーバーは、無限Loopしなが
    ら、接続したクライアントを自分で管
    理して、通信できる。

    View Slide

  99. 99
    IO多重化

    View Slide

  100. 100

    View Slide

  101. 101
    IO多重化

    View Slide

  102. 102
    IO多重化
    ここでBlock

    View Slide

  103. 103
    IO多重化
    Select は状態が変化したSocket全
    てを検知できるので、Blockはしてい
    るが、複数のクライアントを処理でき

    View Slide

  104. 104
    例えば... Guzzleのasyncリクエスト

    View Slide

  105. 105
    Guzzleのpromise

    View Slide

  106. 106
    Guzzleのpromise
    内部では curlmulti が使われて
    いて、poll でIO多重化されてる

    View Slide

  107. 107
    非同期処理では、システムコールやIOモ
    デルの理解が重要になる

    View Slide

  108. 108
    小ネタ3
    雑に strace を使うと、裏側で使っている
    システムコールが簡単に見れる

    View Slide

  109. 1. 用語の定義
    2. なぜ必要なのか?
    3. 非同期関連の実装
    4. PHPで使える解決策
    目次
    109

    View Slide

  110. 110
    非同期フレームワーク

    View Slide

  111. 111
    Swoole, React, AmPHP

    View Slide

  112. 112
    3者ともに、ノンブロッキングのイベント駆
    動を指向
    -> 解決しようとする課題は同じ
    Amp は V3 で Fiber に対応している

    View Slide

  113. 113
    Generator

    View Slide

  114. 114
    Generator (非対称コルーチンの非同期処理実装例 )
    Ngyuki chatの例 https://qiita.com/ngyuki/items/1f0ec69db9d78ba50ebb

    View Slide

  115. 115
    Fiber

    View Slide

  116. 116
    https://wiki.php.net/rfc/fibers
    RFC

    View Slide

  117. 117
    https://qiita.com/rana_kualu/items/6247441f6fdd63c10a06
    【PHP8.1】PHPで簡単に非同期処理を書けるようになる

    View Slide

  118. 118
    とまあ建前は置いておいて

    View Slide

  119. 119
    ● 一般開発者が使う機能ではない
    ● コアに入ったのでXdebugが動く
    ● Schedulerとかはまだ
    ● Async/Await とかもまだ

    View Slide

  120. 120
    Generatorと何が違う?

    View Slide

  121. 121
    ● スタックのどこからでも停止・再開
    ● FiberError, FiberExit

    View Slide

  122. 122
    じゃあ、今の状態で何ができる?

    View Slide

  123. 123
    Generator同様に、メソッドの実行停止・再開ができる

    View Slide

  124. 124
    Generator同様に、メソッドの実行停止・再開ができる
    Fiberインスタンス生成

    View Slide

  125. 125
    Generator同様に、メソッドの実行停止・再開ができる
    Fiber実行開始

    View Slide

  126. 126
    Generator同様に、メソッドの実行停止・再開ができる
    ここで止まる

    View Slide

  127. 127
    Generator同様に、メソッドの実行停止・再開ができる
    ここで再開

    View Slide

  128. Main と Fiber を行ったりきたり
    128

    View Slide

  129. Main と Fiber を行ったりきたり
    129
    これは非同期じゃない。シングル
    スレッドで同期的に動いている

    View Slide

  130. 非同期IOと組み合わせると...
    130

    View Slide

  131. 非同期IOと組み合わせると...
    131
    ノンブロッキングやIO多重化を組
    み合わせることで suspend に意
    味がでる

    View Slide

  132. Generatorを使った実装のサンプルはま
    だまだ少ない
    私と一緒に是非 shadow-php へ...
    132

    View Slide

  133. 133
    参考資料

    View Slide

  134. 134
    Mastering Swoole PHP - Bruce Dou
    Swoole 作者による解説著作
    全体の2/3がPHPの処理モデル
    やIOモデルの説明となっていて、
    非同期を取り巻く状況を雑観でき
    る。

    View Slide

  135. 135
    並行プログラミング入門 - 高野 祐輝
    並行処理について、裏側の仕組
    みから解説してくれる本
    包括的に書かれていて、とりあえ
    ずコレ一冊やるとだいぶ霧が晴れ
    る感じがあります。

    View Slide

  136. 136
    n月刊ラムダノート Vol.1
    コルーチンについて、歴史から詳
    しく載っています。
    これを読んだおかげで、
    Async/Await や Promiseについ
    ても理解が深まりました。

    View Slide

  137. 137
    計算機プログラムの構造と解釈 第2版
    第五章 Stream
    直接非同期には関係ないのだけ
    れど、関数に状態を閉じ込めると
    いう考え方が、非対称コルーチン
    に通じるところがあり、面白いで
    す。

    View Slide

  138. @hanhan1978
    相談・指摘・その他 
    下記のTwitterアカウントにどうぞ
    138

    View Slide