Slide 1

Slide 1 text

問題解決に必要な能力 松下雅和 / @matsukaz 2022/01/27 〜CodeBuildとOPCacheに振り回された話〜 kaonavi Tech Talk #1

Slide 2

Slide 2 text

CTO Webエンジニア CTO SE アーキテクト 都築電気 株式会社 株式会社 オープンストリーム 株式会社 トランスリミット 株式会社 サイバーエージェント 株式会社 カオナビ 松下 雅和 @matsukaz 株式会社カオナビ CTO AWS, Node.js, TypeScript, Ruby, Python, PHP, Go, Scrum 2001.04 2005.08 2011.01 2014.10 2020.02 漫画, ゲーム, カメラ, 自転車

Slide 3

Slide 3 text

● 前提知識 ○ OPCache ○ Apache MPM Prefork ○ ビルドパイプラインのBefore/After ● とある事象発生 ● 調査&解決までの流れ ● 問題解決に必要な能力 アジェンダ

Slide 4

Slide 4 text

前提知識

Slide 5

Slide 5 text

● コンパイル済みバイトコード(OPCode)を共有メモリに保存し、実行のた びにスクリプトの読み込み・パースの手間を省く仕組み OPCache Lexer PHP Script Check OPCode Cache OPCode Compiler Save OPCode Execute (Zend VM) OPCode キャッシュなし Shared Memory OPCode OPCode Parser Optimizer

Slide 6

Slide 6 text

● コンパイル済みバイトコード(OPCode)を共有メモリに保存し、実行のた びにスクリプトの読み込み・パースの手間を省く仕組み OPCache PHP Script Check OPCode Cache Read OPCode Execute (Zend VM) キャッシュあり Shared Memory OPCode OPCode

Slide 7

Slide 7 text

● コンパイル済みバイトコード(OPCode)を共有メモリに保存し、実行のた びにスクリプトの読み込み・パースの手間を省く仕組み OPCache Lexer PHP Script Check OPCode Cache OPCode Compiler Save OPCode Read OPCode Execute (Zend VM) OPCode キャッシュなし キャッシュあり Shared Memory OPCode OPCode Parser Optimizer

Slide 8

Slide 8 text

Apache MPM Prefork ● Apache起動時に予め(pre)子プロセスをコピー(fork)し、アクセスに備 える方式 ● リクエストを1つの子プロセスが処理する ○ 他のプロセスの影響を受けないが、多くのメモリやCPUが必要 子プロセス コントローラー プロセス http リクエスト # ps auxf | grep httpd USER PID ... COMMAND root 11 ... httpd -DFOREGROUND apache 12 ... \_ httpd -DFOREGROUND apache 13 ... \_ httpd -DFOREGROUND 子プロセスを管理 http リクエスト SAPI 子プロセス SAPI

Slide 9

Slide 9 text

Apache MPM Prefork + OPCache ● OPCodeを共有メモリで管理(ファイル共有も可能) ○ プロセスをまたがっても同じOPCodeを共有 ○ OPCodeの保存や読み込みはセマフォを利用して排他制御 子プロセス コントローラー プロセス http リクエスト http リクエスト http リクエスト SAPI 子プロセス SAPI 子プロセス SAPI Shared Memory OPCode

Slide 10

Slide 10 text

● 同一サーバに新しいバージョンのコードを配置 ● symlinkでコードの参照を切り替え ● httpd reloadコマンドを実行 ○ 設定ファイルの再読み込み ○ OPCacheのクリア ビルドパイプライン (Before) # tree /var/www/html -L 2 /var/www/html ├── current │ ├── app │ ├── … │ └── releases ├── 20211115100000 └── 20211116100000

Slide 11

Slide 11 text

● CodeBuild + CodeDeployを利用したBlue-Green Deployment ○ リリースのたびに新しいサーバに切り替わる仕組み ALB ビルドパイプライン (After)

Slide 12

Slide 12 text

● CodeBuild + CodeDeployを利用したBlue-Green Deployment ○ リリースのたびに新しいサーバに切り替わる仕組み デプロイ ビルド CodeDeploy CodeBuild ALB ALB ビルドパイプライン (After)

Slide 13

Slide 13 text

● CodeBuild + CodeDeployを利用したBlue-Green Deployment ○ リリースのたびに新しいサーバに切り替わる仕組み デプロイ 切り替え ビルド CodeDeploy CodeBuild ALB ALB ビルドパイプライン (After) ALB

Slide 14

Slide 14 text

とある事象発生

Slide 15

Slide 15 text

● ロードアベレージが高くなる現象が発生 ある日のリリースにて

Slide 16

Slide 16 text

● 現象発生直前のリリースが怪しいと判断し、リバートを決断 ● ただ、リバート後も判断しきれない状態が続く (サーバを増設したのに負荷が下がりきらない) ○ 月末によるカオナビの機能(人事評価)の駆け込み需要? ● その後も、リリースのたびに負荷が高かったり低かったり… 現象確認と初動対応

Slide 17

Slide 17 text

● OPCacheが怪しい… インフラGで本格的な調査開始 キャッシュヒット率

Slide 18

Slide 18 text

● OPCacheが怪しい… インフラGで本格的な調査開始 キャッシュミス回数

Slide 19

Slide 19 text

● ステージング環境でもOPCacheのヒット率低下が発生 ● 決め手がないまま、サーバの増設・縮退で高負荷を回避 ● 「カオナビの動作が最近遅い」との問い合わせも…(関連は不明) ● 開発側のメンバーも参戦! ここからは松下目線の話 根本原因がわからず

Slide 20

Slide 20 text

調査&解決までの流れ

Slide 21

Slide 21 text

● OPCacheの状態を手軽に確認したい ○ https://gist.github.com/ck-on/4959032 ● OPCacheのウォームアップを一気に行いたい ○ https://gist.github.com/klimslim/ce8f727b3b419badce243bf5a74389b6 ○ require_once()とopcache_compile_file()による違いはない ● ローカルの検証環境は大体できた まずはOPCacheの仕組みを理解

Slide 22

Slide 22 text

● ビルドパイプラインの変更とOPCache関連がやはり怪しい 以前との違いを再確認 デプロイフローの確認 以前の方式の挙動確認

Slide 23

Slide 23 text

● キャッシュミスが発生し続ける = opcache_compile_file()でキャッシュ されないファイルがあるはず ● realpathまわりが怪しい? 当たりをつける https://www.slideshare.net/hnw/realpath-opcache ■余談 php-fpmを利用していた場合は、 OPCacheと realpathとの関連はものすごく重要! 詳しくはこちらの資料を参照 →

Slide 24

Slide 24 text

挙動を再現!

Slide 25

Slide 25 text

● OPCacheの設定 ○ max_accelerated_files = 10000(デフォルト) ○ OPCacheは、内部でsymlinkとrealpathの両方のパスを 保持する(?)ため、2倍のキーを消費 ○ 16229 / 2 = 8115で頭打ちに つまり?

Slide 26

Slide 26 text

● どんな仕組みでそうなっているのかちゃんと把握 裏取り http://blog.jpauli.tech/2015-03-05-opcache-html/

Slide 27

Slide 27 text

だがしかし…

Slide 28

Slide 28 text

oh...

Slide 29

Slide 29 text

再び盛り上がる人々

Slide 30

Slide 30 text

● 誰も利用していない時間のステージング環境で再現確認 本番に近い環境で再検証

Slide 31

Slide 31 text

● 突然再現しなくなる(キャッシュミスしなくなる) 本番に近い環境で再検証

Slide 32

Slide 32 text

!?

Slide 33

Slide 33 text

● 現象発生中にキャッシュされていたファイル一覧を出力 より詳細に調査

Slide 34

Slide 34 text

● OPCache側ではなくてファイルかディレクトリの問題? ● 適当にファイル作ってみる  → キャッシュされる より詳細に調査 New

Slide 35

Slide 35 text

● OPCache側ではなくてファイルかディレクトリの問題? ● 適当にファイル作ってみる  → キャッシュされる ● 同じ内容のファイルを作ってみる  → キャッシュされる より詳細に調査 New Not Cached New

Slide 36

Slide 36 text

● OPCache側ではなくてファイルかディレクトリの問題? ● 適当にファイル作ってみる  → キャッシュされる ● 同じ内容のファイルを作ってみる  → キャッシュされる ● コピーしてみる  → キャッシュされ…ない?! より詳細に調査 New Not Cached New Not Cached Copied

Slide 37

Slide 37 text

● statで該当ファイルを見てみる… なぜか未来日付!! より詳細に調査

Slide 38

Slide 38 text

大勝利!!

Slide 39

Slide 39 text

解説

Slide 40

Slide 40 text

そして解決へ…

Slide 41

Slide 41 text

● いまだ不明… ● 必ずなるわけでもない、ますます謎 ● AWSのサポートに問い合わせてみたものの分からず ○ CodeBuildでビルドした時点でなってる模様 そもそもなぜ未来日付になる?

Slide 42

Slide 42 text

問題解決に必要な能力

Slide 43

Slide 43 text

● インフラ ○ ファイルシステム、symlink ○ AWS関連(Codepipeline、CodeDeploy) ● ミドルウェア ○ Apache MPM Prefork ● PHPの動作の仕組み ○ OPCache 対象に関連する前提知識

Slide 44

Slide 44 text

● 論理的思考 ○ 広く・深く考える ○ 分割して考える ○ 筋道を考える ● ラバーダッキング マインド・考え方

Slide 45

Slide 45 text

● 発生している事象を正確に洗い出す ● 期待する状態との差異を把握 問題解決までの行動 現状認識 原因特定 解決策の 立案 解決策の 実施

Slide 46

Slide 46 text

問題解決までの行動 現状認識 原因特定 ● 原因となりうる要素の洗い出し ● 再現環境の構築・再現方法の確立 ● 原因の絞り込み ○ 当たりをつける(思い込みには注意) ○ どこまでOKでどこからNGか、境界を見極める 解決策の 立案 解決策の 実施

Slide 47

Slide 47 text

問題解決までの行動 現状認識 原因特定 解決策の 立案 解決策の 実施 ● 取りうる選択肢の洗い出し ● 判断軸をもとに解決策を決定 ○ 暫定対応・恒久対応 ○ 緊急性 ○ 対応にかかるコスト ■ スピード・リソース ○ 影響範囲・副作用の有無

Slide 48

Slide 48 text

問題解決までの行動 現状認識 原因特定 解決策の 立案 解決策の 実施 ● 解決策による効果を測定 ● 想定外の副作用に注意 ● いつでも実施前の状態に戻せるようにする

Slide 49

Slide 49 text

● 実装技術の向上やフルスタックエンジニアを目指す以外にも、それぞれの 領域を深く掘り下げる意識も必要 ○ フロントエンジニア ■ 通信やブラウザの仕組み、端末の挙動 ○ バックエンドエンジニア ■ 実行環境の設定・ミドルウェア・OSの仕組み ○ インフラエンジニア ■ 動作させるミドルウェアやアプリケーションの特性や挙動の特徴 エンジニアとして大事なこと

Slide 50

Slide 50 text

● インシデントは初動が大事 ○ いろんなレイヤーで起こるため、原因の切り分けが難しい ○ 組織全体で協力が必要な場面もある ○ 「自分は関係ない」ではなく、 「知ってる知識が役に立つかも?」というスタンスで ● スピード感を持って動ける体制を作る 組織として大事なこと

Slide 51

Slide 51 text

● 問題解決のときにこそ、その人の地力が現れる ○ 組織力としても同様 ● エンジニアリングの世界は奥が深い! ● 完全に理解した、から一歩その先へ まとめ

Slide 52

Slide 52 text

おわり