Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

はじめに 3

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

8 今回のテーマ

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

10 今日のテーマ

Slide 11

Slide 11 text

11 裏テーマ

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

22 例えばPHP

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

25 例えばJavaScript

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

28 例えばJavaScript - part2

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

34 JavaScriptで考えてみる

Slide 35

Slide 35 text

35 Amazon トップページ

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

45 うまく適用できた例

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

49 その他の適用例

Slide 50

Slide 50 text

50 Queue

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

56 いわゆる PHP のWebアプリ

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

61 例えば、Swoole PHP

Slide 62

Slide 62 text

Swooleサーバーの概要図 62

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

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

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

67 しかし、エンドポイント単位の視点に立つ と -> リクエストは同期的に処理されているよ うにみえる

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

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

Slide 73

Slide 73 text

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

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

75 Socket通信

Slide 76

Slide 76 text

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

Slide 77

Slide 77 text

77 IOモデル

Slide 78

Slide 78 text

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

Slide 79

Slide 79 text

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

Slide 80

Slide 80 text

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

Slide 81

Slide 81 text

81 Echoサーバー

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

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

Slide 84

Slide 84 text

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

Slide 85

Slide 85 text

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

Slide 86

Slide 86 text

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

Slide 87

Slide 87 text

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

Slide 88

Slide 88 text

88 Blocking IO

Slide 89

Slide 89 text

89

Slide 90

Slide 90 text

90 ブロッキングIO

Slide 91

Slide 91 text

91 ブロッキングIO SocketでListen

Slide 92

Slide 92 text

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

Slide 93

Slide 93 text

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

Slide 94

Slide 94 text

94 NonBlocking IO

Slide 95

Slide 95 text

95

Slide 96

Slide 96 text

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

Slide 97

Slide 97 text

ノンブロッキングIO 97

Slide 98

Slide 98 text

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

Slide 99

Slide 99 text

99 IO多重化

Slide 100

Slide 100 text

100

Slide 101

Slide 101 text

101 IO多重化

Slide 102

Slide 102 text

102 IO多重化 ここでBlock

Slide 103

Slide 103 text

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

Slide 104

Slide 104 text

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

Slide 105

Slide 105 text

105 Guzzleのpromise

Slide 106

Slide 106 text

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

Slide 107

Slide 107 text

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

Slide 108

Slide 108 text

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

Slide 109

Slide 109 text

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

Slide 110

Slide 110 text

110 非同期フレームワーク

Slide 111

Slide 111 text

111 Swoole, React, AmPHP

Slide 112

Slide 112 text

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

Slide 113

Slide 113 text

113 Generator

Slide 114

Slide 114 text

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

Slide 115

Slide 115 text

115 Fiber

Slide 116

Slide 116 text

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

Slide 117

Slide 117 text

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

Slide 118

Slide 118 text

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

Slide 119

Slide 119 text

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

Slide 120

Slide 120 text

120 Generatorと何が違う?

Slide 121

Slide 121 text

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

Slide 122

Slide 122 text

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

Slide 123

Slide 123 text

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

Slide 124

Slide 124 text

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

Slide 125

Slide 125 text

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

Slide 126

Slide 126 text

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

Slide 127

Slide 127 text

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

Slide 128

Slide 128 text

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

Slide 129

Slide 129 text

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

Slide 130

Slide 130 text

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

Slide 131

Slide 131 text

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

Slide 132

Slide 132 text

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

Slide 133

Slide 133 text

133 参考資料

Slide 134

Slide 134 text

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

Slide 135

Slide 135 text

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

Slide 136

Slide 136 text

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

Slide 137

Slide 137 text

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

Slide 138

Slide 138 text

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