Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
サーバーとは何かを理解して、コンテナ1つで実行しよう | PHPerKaigi2024
Search
sadnessOjisan
March 07, 2024
Technology
34
14k
サーバーとは何かを理解して、コンテナ1つで実行しよう | PHPerKaigi2024
sadnessOjisan
March 07, 2024
Tweet
Share
More Decks by sadnessOjisan
See All by sadnessOjisan
PHPこそ OpenTelemetry が嬉しい
sadnessojisan
2
68
TypeScript、上達の瞬間
sadnessojisan
50
16k
フロントエンド・オブザーバビリティを支える要素技術を学ぼう
sadnessojisan
2
500
疎通2024
sadnessojisan
5
1.4k
BasicBasic認証
sadnessojisan
5
3.9k
ISUCON入門以前_ISUNARABE_LT#1
sadnessojisan
19
5.1k
Node.js v12 を使い続けていたのはなぁぜなぁぜ?
sadnessojisan
11
27k
かにさんタワーバトル
sadnessojisan
1
23k
現実世界におけるスキーマ設計の妥協
sadnessojisan
21
30k
Other Decks in Technology
See All in Technology
Postman と API セキュリティ / Postman and API Security
yokawasa
0
200
podman_update_2024-12
orimanabu
1
260
アップデート紹介:AWS Data Transfer Terminal
stknohg
PRO
0
170
ガバメントクラウドのセキュリティ対策事例について
fujisawaryohei
0
530
Password-less Journey - パスキーへの移行を見据えたユーザーの準備 @ AXIES 2024
ritou
3
1.4k
UI State設計とテスト方針
rmakiyama
2
310
KnowledgeBaseDocuments APIでベクトルインデックス管理を自動化する
iidaxs
1
250
watsonx.ai Dojo #5 ファインチューニングとInstructLAB
oniak3ibm
PRO
0
160
KubeCon NA 2024 Recap: How to Move from Ingress to Gateway API with Minimal Hassle
ysakotch
0
200
権威ドキュメントで振り返る2024 #年忘れセキュリティ2024
hirotomotaguchi
2
730
小学3年生夏休みの自由研究「夏休みに Copilot で遊んでみた」
taichinakamura
0
140
alecthomas/kong はいいぞ / kamakura.go#7
fujiwara3
1
300
Featured
See All Featured
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
44
9.3k
Why Our Code Smells
bkeepers
PRO
335
57k
How GitHub (no longer) Works
holman
311
140k
Scaling GitHub
holman
458
140k
Building a Modern Day E-commerce SEO Strategy
aleyda
38
7k
Raft: Consensus for Rubyists
vanstee
137
6.7k
VelocityConf: Rendering Performance Case Studies
addyosmani
326
24k
Optimising Largest Contentful Paint
csswizardry
33
3k
Optimizing for Happiness
mojombo
376
70k
Why You Should Never Use an ORM
jnunemaker
PRO
54
9.1k
The Cost Of JavaScript in 2023
addyosmani
45
7k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
29
2k
Transcript
サーバーとは何かを理解して、 コンテナ1つで実行しよう @sadnessOjisan phperkaigi2024 1
• はじめに • Dockerでデプロイすることの難しさに気づくまで • 理想のDockerfileを考える • Webサーバーと並行プログラミング • PHPと並行プログラミング
• PHPとお手軽Dockerコンテナデプロイ • 2024年、Nginxは必要か不要か • まとめ 2
いきなりですが、 3
aiko のモノマネします 4
今日、電車の人〜!? YEAH!!!!!!!! 5
Laravelの人〜〜 !? 6
Symfonyの人〜〜 !? 7
Docker で実行の人 !? 8
SSHでソースコードそのまま送り込んで systemd とか deploy.sh で実行の人 !? 9
FROM php-apache の人 !? 10
FROM php-fpm の人 !? 11
ありがとう〜〜〜〜!! とても元気をもらえました! それでは次の曲です。 12
自己紹介 name: sadnessOjisan work: TechBowl(メンター、業務委託) tech: JSer, Rustacean, phper(←NEW) PHP歴:
1ヶ月 趣味: ブログの運営、ラーメン 13
blog.ojisan.io • ラーメンからシステムコール、並行プログラミングまで色んなジャンルがある • 今日はPHPにおける、システムコールと並行プログラミングの話をします • 最近バズった記事: https://blog.ojisan.io/ramen-log/ 14
TechBowl について エンジニアに、プログラミン グの相談ができるサービス。 プログラミングの学習カリ キュラムも用意していて、未 経験者でも学べる仕組み。 15
TechBowl と私 • サービス立ち上げの5年以上前からメンターとして手伝っていて、初期は予約シ ステムの開発を担ったり、今は開発アドバイザーをしている @suguru_ohki 16
TechBowl と私 • サービス立ち上げの5年以上前からメンターとして手伝っていて、初期は予約シ ステムの開発を担ったり、今は開発アドバイザーをしている 5年前の負債返済をこのように解決 した事例を紹介します 5年前の人 口を出す以上はPHPやっておくか 17
よ〜し、まずは Laravel で掲示板作って、 Cloud Run にデプロイするぞ〜 18
PHPをDockerでデプロイすることの 難しさに気づくまで 19
ローカルでサーバー起動できたら、 ファイルを COPY して、起動スクリプトを CMD するだけの簡単なお仕事 20
composer create-project laravel/laravel example-app CMD [“php”, “artisan”, “serve”] docker compose
up 21
22
チョロいな〜〜〜〜 😂 23
インターネット「ローカルサーバー起動したときのスクリプト、 本番で使っちゃダメだよ」 24
https://www.php.net/manual/en/features.commandline.webserver.php 25
しゃあない、じゃあ PHP のソースをそのまま実行するか 26
… 27
そもそも、PHP を実行するってどういうこと? 28
皆様の完成品の Dockerfile でも拝見いたしますか〜 29
Laravel Docker デプロイ [検索] 30
• Git 入れます • Vim 入れます • npm 入れます •
apt-get します • docker-php-ext-installします • pecl installします 31
• Git 入れます • Vim 入れます • npm 入れます •
apt-get します • docker-php-ext-installします • pecl installします ฅ(´・ω・`)ฅ (ここに huh-cat の画像) 32
いやいやいやいや 入れすぎ入れすぎ入れすぎ入れすぎ 33
• Git 入れます • Vim 入れます • npm 入れます •
apt-get します • docker-php-ext-installします • pecl installします • Apache 入れます • Nginx入れます 34
ฅ(´・ω・`)ฅ (ここに huh-cat の画像) ฅ(´・ω・`)ฅ (ここに huh-cat の画像) ฅ(´・ω・`)ฅ (ここに
huh-cat の画像) • Git 入れます • Vim 入れます • npm 入れます • apt-get します • docker-php-ext-installします • pecl installします • Apache 入れます • Nginx入れます 35
いやいやいやいや Apache も Nginx も関係ないやん docker compose じゃないんですよ? 36
PHP動かすために Nginx や Apache が必要と、 本気で言っているんですか!!!!!!!!!!!! 37
え、ググった結果、マジで全部 Nginx や Apache 入っている... 38
この世界と僕、どちらが間違っているのだろうか 39
ググって出てくる Dockerfile の方が、 絶対に絶対に絶対におかしい!!!!!!!!!!!!! 40
理想の Dockerfile を考えよう 41
理想の Dockerfile • 高速なビルド • 小さいイメージ • 役割を小さく 42
高速なビルド • Docker のコマンド一つ一つがレイヤーになっ ていて、コンテナはレイヤーの積み重ね • レイヤーに変更がなければキャッシュが 使える • COPYの順番、マルチステージドビルドが鍵
src にしか変更が入っていなくても、 COPY のレイヤーに差分が生まれているの で、毎回 yarn install してしまう src にしか変更が入っていないなら、 yarn install まではキャッシュが効く 43
小さいイメージ • OSに含まれる、ビルドに必要な機能 は、サーバーの実行には必要ないの で、マルチステージドビルドする • ビルド用のコンテナでビルドして、 成果物だけを小さい実行用コンテナ (e.g. distroless)に移せば、サイズを
減らせる • 余計なものが入っていないのでセ キュリティ的にも嬉しい 44
役割を小さく • サーバーの実行に不要なものは入れない • Vim も Git も要らない • Dockerコンテナの中に入って作業することはない
45
PHPで実現できる? • 高速なビルド ◦ 😄 composer の lock を COPY
すればできそう • 小さいイメージ ◦ 😖そもそも distroless が存在していない ◦ 😖PHPのサーバーを単体で実行することが難しいので Webサーバー同梱になりそう • 役割を小さく ◦ 😖設計によっては Win/Mac で同じ様に動かすのが難しく、チーム開発はコンテナを開発環境に 使った方が安定しそう 46
お前、まさかコンテナとの相性が...😢 47
なんで Apache や Nginx が必要になるのだろう? 48
拡張なしで、言語それ自体の機能として、 並行プログラミングが苦手だから 49
Web サーバーと並行プログラミング 50
Webサーバーの仕組みを知りたければ、 並行プログラミングを知るべし 51
サーバーに繋がるとはどういうことか ブラウザとサーバープログラムの通信 52
とても簡単に言うと、プロセス間通信 53
パソコンの中のプロセスとスレッド • アクティビティモニタから見れる • プロセスもスレッドもアプリケーション やプログラムの処理の単位 • プロセス: アプリケーションやプログラ ムそのもの
• スレッド: プロセスを構成する処理の単 位 • 注: 具体例から導いただけで正しい説明ではないです。環境依存でも あるので正しい説明をするのはここでは控えます 54
プロセス間通信は可能なのか • プロセス間は分離されているのでできなさそう • 例: Discord から Notion のデータにアクセスできない •
ただし、Finder の画像をChromeで添付などはできるわけで、プロセスを跨いで データをやりとりする口はありそう • ファイルディスクリプターを介す 55
ファイルディスクリプターを使った通信 • システムコールでファイルディスクリプタを操作する • プロセスにはそれぞれファイルディスクリプターを割り当てられる ◦ open, socket • ファイルディスクリプタがあれば、データの読み込み・書き込みができる
◦ read, write 56
サーバーに繋がるとはどういうことか ブラウザとサーバープログラムの通信 インターネットを経由した、 プロセス間通信 57
Socket通信 socket() でファイルディスクリプタ を作って、プロセス間通信 58
3way handshakeから始まる TCP Stream https://blog.ojisan.io/server-architecture-2023/ 接続済み socket が手に入る 59
TCPからHTTPへ • TCPの上に作られたプロトコルがHTTP • フィールド(いわゆるヘッダ)とコンテンツ(いわゆるボディ)といった HTTP Semantics に則ったフォーマットで送受信することを、サーバーとブラウザがその前提で実装する だけでよい 60
HTTPからアプリケーションロジックへ 1. ソケット経由で read すれば TCP 上の(streamの)テキストを入手できる 2. HTTPでパースできたらヘッダとボディの情報が手に入る 3.
ヘッダからパスがわかればルーティングできるし、ボディにデータが入っていたら保存 できるなど、その値を元にプログラムの分岐や処理をかける 4. 最後に(streamに) write すればレスポンスを返せる 61
システムコールのみでサーバーを実装できる! 62
同時にアクセスされたらどうしますか? 63
反復サーバー • 順番待ちをする • 前の人の処理が長いと、次 の人の処理が始まらないの で実用的ではない • php artisan
serve で立ち 上がるサーバーはこのモデ ルです... 64
処理を分担させよう! 65
マルチプロセスサーバー • システムコール fork でプ ロセスを複数つくれる • CPUのコア数まで並行に処 理を行える •
1 リクエストに紐づく処理 を別プロセスに任せるので 順番待ちにならない • リクエスト来てからプロセ ス作ると遅い 66
プリフォークサーバー • 先に fork しておく • いわばスレッドプールのよ うなものをする • プール管理はめんどくさい
かも 67
プロセスはたくさん立てても問題がないのか 68
マルチプロセスのデメリット • プロセス間でデータを共有するときはファイルディスクリプタの作成、読み書き といった処理が必要 • ファイルディスクリプタには上限数があるのでそれ以上は作れない • CPUコア数以上のプロセスを作った際の、切り替えコストが比較的高い 69
代わりにスレッドを使うと節約できる 70
マルチスレッドサーバー • システムコール clone • 各プログラミング言語にも spawn 的な名前 のメソッドが生えているはず •
メンタルモデル的にはプロセスと同じ • プロセスと違って、スレッド間はデータを共 有できる(レースコンディションの危険) 71
スレッドはたくさん立てても問題がないのか 72
C10K 問題 http://www.kegel.com/c10k.html 73
C10K問題 1req ごとに 1 native thread を割り当てていた ら、クライアントの数が増えれば増えるほど負荷 が高まる ハードウェアの性能的に余裕があっても性能が劣
化することがあり、それを C10K 問題と呼ぶ C10K 問題は fd, pid の枯渇、スレッドを固定長 サイズで確保することによるメモリの無駄遣い、 コンテキストスイッチコストを含む これを解決する方法が 1req ごとに 1 native thread を割り当てない技術で、シングルスレッ ド+イベントループ+IO 多重化 https://blog.ojisan.io/c10k-wakaran/ 74
C10K 問題はシングルスレッドで解消できる 75
それはPHPビルトインサーバーと同じ構成で、 順番待ちになるのでは... 76
シングルスレッド + 非同期処理 77
シングルスレッド・非同期処理のコンセプト • イベントループによる Reactor Pattern • IO が来たらイベントを発行し、キューに 積む •
メインループでキューの中身を取り出し て、イベントを実行 • イベントが非同期処理を呼び出したのであ れば、完了後にイベントを発行するように して、待ち時間に別のイベントを実行 https://www.oreilly.co.jp/book s/9784873118734/ 78
ファイルディスクリプターを監視する • IOが来たときに発火 • IOが来たことはファイルディスクリプタの 監視を通して行う • select, poll, epoll
• epoll がゲームチェンジャー。select, poll は自分からファイルディスクリプタを見に 行く必要があって、数が増えるとオーバー ヘッドになっていたが、epoll は IO 発生の 通知をもらえる設計。大量の IO を捌けるよ うになった。 https://blog.ojisan.io/how-to-epoll/ 79
人「CPUのコアを全部使い切りたくない?」 80
欲張りな人「マルチスレッドの上で非同期サーバー作ればいいじゃん」 81
もっと欲張りな人「自分達でスレッドを実装すれば、 もっと限界突破できるくね?」 82
グリーンスレッド • OSが用意しているスレッドはカーネルスレッドやネイティブスレッド • コンテキストスイッチ(スレッド切り替えのコスト)、リソース割り当てのスケ ジューリングに最適化の余地がある • スレッドはコンピュータの処理の単位なので、メモリとスタックを持つ。コン ピュータに元々あるメモリから、一部分切り出してそこを自由に使えば、擬似的 にスレッドを作り出せる
83
M:Nの割り当て • ユーザーが任意の数をスレッドが作れるようになると、有限のコンピュータリ ソースに対して(並行処理可能なネイティブスレッド数 = CPUのコア数上 限)、大量のスレッドを割り当てる M:N の比率で考える •
「どのタイミングで?」「どのネイティブスレッドにどのグリーンスレッドを割 り当てる?」を考える必要がある。 84
コンテキストスイッチ • CPUのスタックとレジスタをヒープに退避 • ヒープにある情報をCPUに再現する • CPUのスタックとレジスタそのものにアクセ スするのでアセンブラを書く必要があり、プ ログラムとマッピングさせるためにFFIなどが 必要となる
https://www.oreilly.co.jp//books/9784873119595/ 85
コンテキストスイッチ 86
Work Stealing • 特定のコアに処理が集中している場 合に、タスクをネイティブスレッド 間で融通させる仕組み • タスクの数、タスクの実行時間に よって割り当て直すなど、いろんな 戦略が提案されている
https://tokio.rs/blog/2019-10-scheduler 87
ガードページの削除 • スレッドの中にはヒープ領域とスタック領域がある • 処理が多すぎて、スタックにデータが乗りすぎるとリ ソース全体を逼迫するので、スタックには上限値が設 定されている • この上限値を超えることをスタックオーバーフローと 言い、ガードページを使って設定されている。
• だが使い切ることは稀なので、グリーンスレッド実装 ではこの値を削ったり動的に設定したりして、効率を 上げる。 スタック ヒープ ガードページ 0x00000000 0xFFFFFFFF 88
人類の叡智の結晶感があるよね...!!! 89
PHP と並行プログラミング 90
PHP で実現されているもの • 反復サーバー: ビルトインサーバー • マルチプロセス: Apache, CGI 91
PHPの実行方法 • Server API(SAPI) を決めて実行する • SAPI ◦ CLI: PHPコマンド
◦ CGI: WebServerがHTTPを受けて、CGIプロトコルでPHPプログラムを起動する ◦ FastCGI: 同上、FastCGIプロトコルでPHPプロセスにアクセス ◦ Apache: Webサーバー(Apache)に組み込まれているPHPモジュールを実行 92 (ゝω・)vキャピ
Apache で PHP を実行 • PHPは元々 CGI 集でしかなかったが、PHP2で NCSAサーバー(後のApache)に統合され、その 上で実行できるような仕組みになる
• なので、PHPの実行の源流とも言える • Apache と同じプロセスで PHP を実行(モジュー ル版)できるし、もちろん fork もできる https://www.oreilly.co.jp/books/9784814400270/ 93
CGI で PHP を実行 • 処理を実行するために別プロセスを立ち上げて実行されるプログラム。Web サーバーから呼び出されることが多い。 • 元々は使い捨てだが、FastCGIは一度立ち上げたプロセスを使いまわすことで効 率化を図る
• Nginxでリクエストを受けて FastCGI 経由で PHP を実行し、その結果を Nginx が返すという設計がよくされる。このときにFPM(FastCGI Process Manager) が必要になる。 94
ビルトインサーバー で PHP を実行 • PHP自体にHTTPを喋らせたかったらビルトインサーバー • シングルスレッドかつ同期的なので、2人同時にアクセスすると前の人のレスポンスが 終わらないと処理が始まらない •
本番で使ってはいけない 95
マルチプロセスで並行プログラミングをするために、 リクエストを受けるサーバーと、 forkされたアプリケーション実装という設計になり、 Apache や Nginx と組み合わせて使っていた! 96
これだけじゃありません!!!!!! 97
PHP とモダンな並行プログラミング • Swoole ◦ 非同期ランタイムを実装。Node.jsと同じモデル • FrankenPHP ◦ PHPを動かすことを想定したWebサーバー。Go実装。
少なくとも Webサーバー自体は M:N グリーンスレッ ドモデル(net/http と Goroutine への言及があるた め)。SAPI の先の処理系が扱うスレッドモデルは不 明(調べ切れていないです、詳しい人教えて欲しいで す><) 98
Apache, Nginx 以外の実行環境がある、 Dockerデプロイ簡単なのでは... 99
PHP とお手軽 Docker Deploy 100
FrankenPHP https://speakerdeck.com/dunglas/frankenphp-a-modern-app-server-for-php-written-in-go?slide=4 101
もしかして、ApacheもNginxも入れずに、 1ファイルのDockerfileで全てが完結する世界来ますか? 102
FrankenPHP を導入する • Laravel Octane が対応してインストールが簡単に • Laravel Octane: アプリケーションサーバー実装を提供することで、パフォーマンス向
上を目指した拡張セット。FrankenPHP, Swoole, RoadRunner を選べる。 103
FrankenPHP 104
FrankenPHP 105
✨ 106
2024年、Nginx は必要か不要か 107
僕「FrankenPHPあるし Nginx 不要では」 108
Laravel Octane「いるよ」 109
https://laravel.com/docs/10.x/octane#serving-your-application-via-nginx 110
2024年現在、必要なのか? • Docker使っている以上はクラウドネイティブな設計のはず。LBやCDNが前段に いるはず。 • 証明書は?: 前段を TLS 終端にすれば良い •
静的アセットは?: オブジェクトストレージから配信すればよい、CDNへの beresp で Cache-Control をつければ良い 111
僕「とはいえ公式DOCに歯向かうわけだし、本当に良いのか?」 112
Swooleのプロ氏〜 前段にWebサーバーなしでやっていいと 思います? Webサーバー置かずにやってたけど、特 に問題なかったよ (著者近影) 113
ヨシ!!!!!!!!!!!!!! 114
よくある議論らしいです https://qiita.com/emacs_hhkb/items/818f54b75a14832d9d16 115
まとめ 116
Webサーバーの実装で重要なのは並行プログラミングの実現だ。 PHPで並行プログラミングをするデフォルトの選択肢はマルチプロセスで、 PHPの実行を子プロセスとして呼び出してもらうために Apache や Nginx(FastCGI) が必要となっていた。 一方で Swoole や
FrankenPHP といった新たな非同期ランタイムのパラダ イムがPHPにも入ってきており、Laravel Octane から使える。 117
FrankenPHP / Laravel Octane があれば、 Docker 1ファイルで全部固められて、 しかもモダンなWebサーバーアーキテクチャを取り入れられる。 まだ枯れていない技術だとは思いますが、これからの PHP
の Developer Experience の未来がとても明るくて良いですね。 2024年もがんばっていきまっしょい! 118